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
This commit is contained in:
Carsten 2026-04-22 22:29:26 +02:00
parent 2bb901873f
commit 3367b95b91
4 changed files with 34 additions and 3 deletions

View file

@ -51,13 +51,13 @@ defmodule ProxmoxAgent.Collectors.Host do
end
defp read_loadavg(proc_dir) do
body = File.read!(Path.join(proc_dir, "loadavg"))
body = read_and_log(Path.join(proc_dir, "loadavg"))
[l1, l5, l15 | _] = String.split(body, ~r/\s+/, trim: true)
{to_float(l1), to_float(l5), to_float(l15)}
end
defp read_meminfo(proc_dir) do
body = File.read!(Path.join(proc_dir, "meminfo"))
body = read_and_log(Path.join(proc_dir, "meminfo"))
parsed =
body
@ -76,11 +76,23 @@ defmodule ProxmoxAgent.Collectors.Host do
end
defp read_uptime(proc_dir) do
body = File.read!(Path.join(proc_dir, "uptime"))
body = read_and_log(Path.join(proc_dir, "uptime"))
[secs | _] = String.split(body, " ", trim: true)
secs |> to_float() |> trunc()
end
defp read_and_log(path) do
start = System.monotonic_time(:microsecond)
result = File.read(path)
duration_us = System.monotonic_time(:microsecond) - start
ProxmoxAgent.Diagnostics.log_read(path, result, duration_us)
case result do
{:ok, body} -> body
{:error, reason} -> raise File.Error, reason: reason, action: "read file", path: to_string(path)
end
end
defp kb_to_bytes(nil), do: nil
defp kb_to_bytes(str) do

View file

@ -22,6 +22,7 @@ defmodule ProxmoxAgent.Diagnostics 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} ->
@ -46,6 +47,11 @@ defmodule ProxmoxAgent.Diagnostics 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

View file

@ -19,6 +19,9 @@ defmodule ProxmoxAgent.Diagnostics.Writer do
def init(opts) do
dir = Keyword.fetch!(opts, :dir)
# No trap_exit: the Writer owns no linked processes other than the supervisor.
# If you add a linked port/task, restore Process.flag(:trap_exit, true) and
# add a matching handle_info({:EXIT, _, _}, state) clause.
with {:ok, commands} <- open(Path.join(dir, "commands.log")),
{:ok, samples} <- open(Path.join(dir, "samples.log")) do
{:ok, %{dir: dir, commands: commands, samples: samples}}

View file

@ -96,5 +96,15 @@ defmodule ProxmoxAgent.DiagnosticsTest do
assert body =~ "kind=fast"
assert body =~ "\"zfs_pools\""
end
test "log_read/3 writes to commands.log formatted as cat", %{dir: dir} do
assert :ok = Diagnostics.log_read("/proc/loadavg", {:ok, "0.12 0.34 0.56 1/200 3000"}, 150)
:ok = GenServer.call(ProxmoxAgent.Diagnostics.Writer, :flush)
body = File.read!(Path.join(dir, "commands.log"))
assert body =~ "$ cat /proc/loadavg"
assert body =~ "0.12 0.34 0.56"
assert body =~ "exit=0"
end
end
end