Feature/826 healthcheck endpoint
[akkoma] / lib / healthcheck.ex
1 defmodule Pleroma.Healthcheck do
2 @moduledoc """
3 Module collects metrics about app and assign healthy status.
4 """
5 alias Pleroma.Healthcheck
6 alias Pleroma.Repo
7
8 defstruct pool_size: 0,
9 active: 0,
10 idle: 0,
11 memory_used: 0,
12 healthy: true
13
14 @type t :: %__MODULE__{
15 pool_size: non_neg_integer(),
16 active: non_neg_integer(),
17 idle: non_neg_integer(),
18 memory_used: number(),
19 healthy: boolean()
20 }
21
22 @spec system_info() :: t()
23 def system_info do
24 %Healthcheck{
25 memory_used: Float.round(:erlang.memory(:total) / 1024 / 1024, 2)
26 }
27 |> assign_db_info()
28 |> check_health()
29 end
30
31 defp assign_db_info(healthcheck) do
32 database = Application.get_env(:pleroma, Repo)[:database]
33
34 query =
35 "select state, count(pid) from pg_stat_activity where datname = '#{database}' group by state;"
36
37 result = Repo.query!(query)
38 pool_size = Application.get_env(:pleroma, Repo)[:pool_size]
39
40 db_info =
41 Enum.reduce(result.rows, %{active: 0, idle: 0}, fn [state, cnt], states ->
42 if state == "active" do
43 Map.put(states, :active, states.active + cnt)
44 else
45 Map.put(states, :idle, states.idle + cnt)
46 end
47 end)
48 |> Map.put(:pool_size, pool_size)
49
50 Map.merge(healthcheck, db_info)
51 end
52
53 @spec check_health(Healthcheck.t()) :: Healthcheck.t()
54 def check_health(%{pool_size: pool_size, active: active} = check)
55 when active >= pool_size do
56 %{check | healthy: false}
57 end
58
59 def check_health(check), do: check
60 end