proxMon/agent/lib/proxmox_agent/diagnostics.ex
Carsten 3367b95b91 chore(agent): log /proc reads, log diagnostics enable, comment trap_exit
Addresses final code review:
- Host collector's /proc reads now go through Diagnostics.log_read/3,
  appearing in commands.log formatted as `$ cat /proc/loadavg`
- configure/1 logs an info line on successful enable so the operator
  has a breadcrumb in the journal
- Writer.init/1 documents the deliberate trap_exit omission
2026-04-22 22:29:26 +02:00

70 lines
2 KiB
Elixir

defmodule ProxmoxAgent.Diagnostics do
@moduledoc """
Optional diagnostic dump of external commands and outgoing samples.
Controlled by `:dump_dir` in the application env. When unset or nil,
`log_command/4` and `log_sample/2` are no-ops and incur no I/O.
When set, they cast to `ProxmoxAgent.Diagnostics.Writer` (if running)
which serializes appends to `commands.log` and `samples.log`.
"""
require Logger
@type command_result ::
{:ok, String.t()}
| {:error, term()}
@spec configure(String.t() | nil) :: :ok
def configure(nil), do: disable()
def configure(""), do: disable()
def configure(dir) when is_binary(dir) do
case File.mkdir_p(dir) do
:ok ->
Application.put_env(:agent, :dump_dir, dir)
Logger.info("diagnostics: enabled, writing to #{dir}")
:ok
{:error, reason} ->
Logger.warning("diagnostics: mkdir_p #{dir} failed (#{inspect(reason)}); dumping disabled")
disable()
end
end
@spec enabled?() :: boolean()
def enabled?, do: not is_nil(Application.get_env(:agent, :dump_dir))
@spec dump_dir() :: String.t() | nil
def dump_dir, do: Application.get_env(:agent, :dump_dir)
@spec log_command(String.t(), [String.t()], command_result(), non_neg_integer()) :: :ok
def log_command(cmd, args, result, duration_us) do
cast({:command, cmd, args, result, duration_us})
end
@spec log_sample(String.t(), map()) :: :ok
def log_sample(kind, payload) when is_binary(kind) and is_map(payload) do
cast({:sample, kind, payload})
end
@spec log_read(Path.t(), command_result(), non_neg_integer()) :: :ok
def log_read(path, result, duration_us) do
log_command("cat", [to_string(path)], result, duration_us)
end
defp disable do
Application.delete_env(:agent, :dump_dir)
:ok
end
defp cast(msg) do
if enabled?() do
case Process.whereis(ProxmoxAgent.Diagnostics.Writer) do
nil -> :ok
pid -> GenServer.cast(pid, msg)
end
end
:ok
end
end