Packages
ex_esdb
0.6.1
0.11.0
0.10.0
0.9.0
0.8.0
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14-alpha
0.0.13-alpha
0.0.12-alpha
0.0.11-alpha
0.0.10-alpha
0.0.9-alpha
0.0.8-alpha
0.0.6-alpha
0.0.5-alpha
0.0.4-alpha
0.0.3-alpha
0.0.2-alfa
0.0.1-alfa
ExESDB is a reincarnation of rabbitmq/khepri, specialized for use as a BEAM-native event store.
Current section
Files
Jump to
Current section
Files
lib/ex_esdb/monitoring/health_checker.ex
defmodule ExESDB.Monitoring.HealthChecker do
@moduledoc """
Performs comprehensive health checks on the ExESDB system.
Monitors system processes, configuration validity, resource usage,
and overall system health to detect potential issues.
"""
use GenServer
# API
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def perform_health_check(store_id \\ nil) do
GenServer.call(__MODULE__, {:health_check, store_id})
end
def check_system_processes(store_id \\ nil) do
GenServer.call(__MODULE__, {:check_system_processes, store_id})
end
def check_resource_usage() do
GenServer.call(__MODULE__, :check_resource_usage)
end
# GenServer callbacks
@impl true
def init(_opts) do
{:ok, %{}}
end
@impl true
def handle_call({:health_check, store_id}, _from, state) do
store_id = store_id || :default_store
checks = [
{"System Processes", fn -> check_processes(store_id) end},
{"Configuration", fn -> check_configuration(store_id) end},
{"Resource Usage", fn -> check_resources() end},
{"Supervision Tree", fn -> check_supervision(store_id) end}
]
results = perform_checks(checks)
health_status = determine_health_status(results)
{:reply, {:ok, %{status: health_status, results: results}}, state}
end
@impl true
def handle_call({:check_system_processes, store_id}, _from, state) do
result = check_processes(store_id)
{:reply, result, state}
end
@impl true
def handle_call(:check_resource_usage, _from, state) do
result = check_resources()
{:reply, result, state}
end
# Private functions
defp perform_checks(checks) do
Enum.map(checks, fn {name, check_fn} ->
try do
result = check_fn.()
{name, result}
rescue
error -> {name, {:error, inspect(error)}}
end
end)
end
defp determine_health_status(results) do
errors = Enum.count(results, fn {_, result} -> match?({:error, _}, result) end)
warnings = Enum.count(results, fn {_, result} -> match?({:warning, _}, result) end)
cond do
errors > 0 -> :unhealthy
warnings > 0 -> :degraded
true -> :healthy
end
end
defp check_processes(store_id) do
system_name = ExESDB.System.system_name(store_id)
case Process.whereis(system_name) do
nil -> {:error, "System process not found"}
pid when is_pid(pid) ->
if Process.alive?(pid) do
:ok
else
{:error, "System process is dead"}
end
end
end
defp check_configuration(_store_id) do
# Basic configuration check
try do
# This would check various configuration aspects
:ok
rescue
_ -> {:error, "Configuration validation failed"}
end
end
defp check_resources() do
{memory_total, memory_used, _} = :memsup.get_memory_data()
memory_utilization = (memory_used / memory_total) * 100
process_count = length(Process.list())
process_limit = :erlang.system_info(:process_limit)
process_utilization = (process_count / process_limit) * 100
cond do
memory_utilization > 90 or process_utilization > 90 ->
{:error, "Critical resource usage"}
memory_utilization > 75 or process_utilization > 75 ->
{:warning, "High resource usage"}
true ->
:ok
end
end
defp check_supervision(store_id) do
system_name = ExESDB.System.system_name(store_id)
case Process.whereis(system_name) do
nil -> {:error, "System supervisor not found"}
pid ->
try do
children = Supervisor.which_children(pid)
alive_children = Enum.count(children, fn {_, child_pid, _, _} ->
child_pid != :undefined and Process.alive?(child_pid)
end)
if alive_children == length(children) do
:ok
else
{:warning, "#{alive_children}/#{length(children)} children alive"}
end
rescue
_ -> {:error, "Unable to inspect supervision tree"}
end
end
end
end