akkoma/lib/pleroma/healthcheck.ex

74 lines
2 KiB
Elixir
Raw Permalink Normal View History

# Pleroma: A lightweight social networking server
2022-02-25 23:11:42 -07:00
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
2019-04-22 01:19:53 -06:00
defmodule Pleroma.Healthcheck do
@moduledoc """
Module collects metrics about app and assign healthy status.
"""
alias Pleroma.Healthcheck
alias Pleroma.Repo
@derive Jason.Encoder
2019-04-22 01:19:53 -06:00
defstruct pool_size: 0,
active: 0,
idle: 0,
memory_used: 0,
2019-09-26 05:49:57 -06:00
job_queue_stats: nil,
2019-04-22 01:19:53 -06:00
healthy: true
@type t :: %__MODULE__{
pool_size: non_neg_integer(),
active: non_neg_integer(),
idle: non_neg_integer(),
memory_used: number(),
2019-09-26 05:49:57 -06:00
job_queue_stats: map(),
2019-04-22 01:19:53 -06:00
healthy: boolean()
}
@spec system_info() :: t()
def system_info do
%Healthcheck{
memory_used: Float.round(:recon_alloc.memory(:allocated) / 1024 / 1024, 2)
2019-04-22 01:19:53 -06:00
}
|> assign_db_info()
2019-09-26 05:49:57 -06:00
|> assign_job_queue_stats()
2019-04-22 01:19:53 -06:00
|> check_health()
end
defp assign_db_info(healthcheck) do
2019-05-30 02:33:58 -06:00
database = Pleroma.Config.get([Repo, :database])
2019-04-22 01:19:53 -06:00
query =
"select state, count(pid) from pg_stat_activity where datname = '#{database}' group by state;"
result = Repo.query!(query)
2019-05-30 02:33:58 -06:00
pool_size = Pleroma.Config.get([Repo, :pool_size])
2019-04-22 01:19:53 -06:00
db_info =
Enum.reduce(result.rows, %{active: 0, idle: 0}, fn [state, cnt], states ->
if state == "active" do
Map.put(states, :active, states.active + cnt)
else
Map.put(states, :idle, states.idle + cnt)
end
end)
|> Map.put(:pool_size, pool_size)
Map.merge(healthcheck, db_info)
end
2019-09-26 05:49:57 -06:00
defp assign_job_queue_stats(healthcheck) do
stats = Pleroma.JobQueueMonitor.stats()
Map.put(healthcheck, :job_queue_stats, stats)
end
2019-04-22 01:19:53 -06:00
@spec check_health(Healthcheck.t()) :: Healthcheck.t()
def check_health(%{pool_size: pool_size, active: active} = check)
when active >= pool_size do
%{check | healthy: false}
end
def check_health(check), do: check
end