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
70 lines
2 KiB
Elixir
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
|