108 lines
2.8 KiB
Elixir
108 lines
2.8 KiB
Elixir
defmodule Prymn.Agents.Health do
|
|
@moduledoc """
|
|
The Health struct keeps simple health information of whether or not the
|
|
target host machine is up to date, has any tasks running, its resources are
|
|
getting depleted, or if it's unable be reached.
|
|
"""
|
|
|
|
defstruct [:host, :version, :status, tasks: [], message: "Unknown"]
|
|
|
|
alias PrymnProto.Prymn.HealthResponse
|
|
|
|
@type t :: %{
|
|
host: String.t(),
|
|
version: String.t(),
|
|
status: atom(),
|
|
message: String.t()
|
|
}
|
|
|
|
def start() do
|
|
:ets.new(__MODULE__, [:set, :public, :named_table, read_concurrency: true])
|
|
end
|
|
|
|
def subscribe(host) do
|
|
Phoenix.PubSub.subscribe(Prymn.PubSub, "health:#{host}")
|
|
end
|
|
|
|
def broadcast!(%__MODULE__{host: host} = health) do
|
|
Phoenix.PubSub.broadcast!(Prymn.PubSub, "health:#{host}", health)
|
|
end
|
|
|
|
def update_and_broadcast(nil) do
|
|
nil
|
|
end
|
|
|
|
def update_and_broadcast(%__MODULE__{host: host} = health) do
|
|
:ets.insert(__MODULE__, {host, health})
|
|
broadcast!(health)
|
|
end
|
|
|
|
def delete(host_address) do
|
|
:ets.delete(__MODULE__, host_address)
|
|
end
|
|
|
|
def lookup(host_address, opts \\ []) do
|
|
default = Keyword.get(opts, :default, false)
|
|
|
|
case :ets.lookup(__MODULE__, host_address) do
|
|
[{^host_address, value}] -> value
|
|
[] when default -> %__MODULE__{host: host_address}
|
|
[] -> nil
|
|
end
|
|
end
|
|
|
|
def new(agent_id, %{"cpu_status" => cpu, "memory_status" => memory, "disk_status" => disk}) do
|
|
%__MODULE__{host: agent_id, version: "0.1.0"}
|
|
|> do_cpu(cpu)
|
|
|> do_memory(memory)
|
|
|> do_disks(disk)
|
|
end
|
|
|
|
defp do_cpu(health, cpu) do
|
|
%__MODULE__{health | message: "Connected", status: :connected}
|
|
end
|
|
|
|
defp do_memory(health, memory) do
|
|
health
|
|
end
|
|
|
|
defp do_disks(health, disks) do
|
|
health
|
|
end
|
|
|
|
def make_timed_out(%__MODULE__{} = health) do
|
|
%__MODULE__{health | status: :unreachable, message: "Connect timed out"}
|
|
end
|
|
|
|
def make_disconnected(%__MODULE__{} = health) do
|
|
%__MODULE__{health | status: :disconnected, message: "Disconnected"}
|
|
end
|
|
|
|
def make_from_proto(%HealthResponse{system: system, version: version, tasks: tasks}, host) do
|
|
%__MODULE__{host: host, status: :connected}
|
|
|> do_version(version)
|
|
|> do_system(system)
|
|
|> do_tasks(tasks)
|
|
end
|
|
|
|
defp do_version(health, version) do
|
|
%__MODULE__{health | version: version}
|
|
end
|
|
|
|
defp do_system(health, system) do
|
|
case system.status do
|
|
"normal" -> %__MODULE__{health | message: "Connected"}
|
|
status -> %__MODULE__{health | message: "Alert: #{status}"}
|
|
end
|
|
end
|
|
|
|
defp do_tasks(health, tasks) do
|
|
tasks =
|
|
Enum.map(tasks, fn {task_key, task_value} ->
|
|
progress = Float.round(task_value.progress, 2)
|
|
{task_key, %{task_value | progress: "#{progress}%"}}
|
|
end)
|
|
|
|
%__MODULE__{health | tasks: tasks}
|
|
end
|
|
end
|