fix: improve agent-based live polling with better logging and validation

- Added Logger.require for debug logging
- Refactored fetch_latest_agent_data to reduce nesting depth
- Added debug logging to trace agent assignment detection
- Check for nil/stale sensor readings and log appropriately
- Use actual reading timestamp instead of current time for data points

This will help diagnose why live polling shows 0 values and why
Phoenix SNMP disabled messages appear for agent-assigned devices.
This commit is contained in:
Graham McIntire 2026-02-05 09:25:29 -06:00
parent e0592dbf3d
commit 987eae0408
No known key found for this signature in database

View file

@ -7,6 +7,8 @@ defmodule ToweropsWeb.GraphLive.Show do
alias Towerops.Monitoring
alias Towerops.Snmp
require Logger
# Maximum live data points (5 minutes at 1 second intervals)
@max_live_points 300
@ -667,12 +669,18 @@ defmodule ToweropsWeb.GraphLive.Show do
timestamp_ms = DateTime.to_unix(now, :millisecond)
# Check if device has agent assignment
has_agent = socket.assigns[:has_agent_assignment] || false
Logger.debug("Live poll for device #{device.name}: has_agent=#{has_agent}")
new_points =
if socket.assigns.has_agent_assignment do
if has_agent do
# Use agent-collected data from database
Logger.debug("Using agent-collected data for live polling")
fetch_latest_agent_data(socket.assigns, timestamp_ms)
else
# Do direct SNMP polling
Logger.debug("Using direct SNMP for live polling")
client_opts = build_snmp_client_opts(device)
poll_sensors_for_live_mode(socket.assigns, client_opts, timestamp_ms)
end
@ -696,28 +704,47 @@ defmodule ToweropsWeb.GraphLive.Show do
end
# Fetch latest sensor data collected by agent
defp fetch_latest_agent_data(assigns, timestamp_ms) do
defp fetch_latest_agent_data(assigns, _timestamp_ms) do
sensors = get_sensors_for_live_mode(assigns)
sensors
|> Enum.map(fn sensor ->
# Get the most recent sensor reading from the database
case Snmp.get_latest_sensor_reading(sensor.id) do
nil ->
nil
reading ->
%{
sensor_id: sensor.id,
label: sensor.sensor_descr,
value: Float.round(reading.value || 0.0, 1),
timestamp: timestamp_ms
}
end
end)
|> Enum.map(&fetch_sensor_reading/1)
|> Enum.reject(&is_nil/1)
end
defp fetch_sensor_reading(sensor) do
case Snmp.get_latest_sensor_reading(sensor.id) do
nil ->
Logger.debug("No reading found for sensor #{sensor.id} (#{sensor.sensor_descr})")
nil
%{value: nil} = reading ->
Logger.debug("Nil value for sensor #{sensor.id} (#{sensor.sensor_descr}) at #{reading.checked_at}")
nil
reading ->
validate_and_format_reading(sensor, reading)
end
end
defp validate_and_format_reading(sensor, reading) do
age_seconds = DateTime.diff(DateTime.utc_now(), reading.checked_at, :second)
if age_seconds > 300 do
Logger.debug("Stale reading for sensor #{sensor.id} (#{sensor.sensor_descr}), age: #{age_seconds}s")
nil
else
reading_timestamp_ms = DateTime.to_unix(reading.checked_at, :millisecond)
%{
sensor_id: sensor.id,
label: sensor.sensor_descr,
value: Float.round(reading.value, 1),
timestamp: reading_timestamp_ms
}
end
end
# Build SNMP client options
defp build_snmp_client_opts(device) do
snmp_config = Devices.get_snmp_config(device)