From ceded37d9cf85b51bf31999c72e1108b38f009e1 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Mon, 19 Jan 2026 13:38:43 -0600 Subject: [PATCH] improve agent --- lib/towerops_web/channels/agent_channel.ex | 46 +++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/lib/towerops_web/channels/agent_channel.ex b/lib/towerops_web/channels/agent_channel.ex index 8f2f70f0..b16c499a 100644 --- a/lib/towerops_web/channels/agent_channel.ex +++ b/lib/towerops_web/channels/agent_channel.ex @@ -25,11 +25,13 @@ defmodule ToweropsWeb.AgentChannel do alias Towerops.Agent.AgentHeartbeat alias Towerops.Agent.AgentJob alias Towerops.Agent.AgentJobList + alias Towerops.Agent.MonitoringCheck alias Towerops.Agent.SnmpDevice alias Towerops.Agent.SnmpQuery alias Towerops.Agent.SnmpResult alias Towerops.Agents alias Towerops.Devices + alias Towerops.Monitoring alias Towerops.Snmp alias Towerops.Snmp.Discovery @@ -118,6 +120,13 @@ defmodule ToweropsWeb.AgentChannel do {:noreply, socket} end + def handle_in("monitoring_check", %{"binary" => binary_b64}, socket) do + binary = Base.decode64!(binary_b64) + check = MonitoringCheck.decode(binary) + _ = process_monitoring_check(socket.assigns.organization_id, check) + {:noreply, socket} + end + # Private helpers @spec build_jobs_for_agent(Ecto.UUID.t()) :: [AgentJob.t()] @@ -151,7 +160,9 @@ defmodule ToweropsWeb.AgentChannel do ip: device.ip_address, community: device.snmp_community, version: device.snmp_version, - port: device.snmp_port || 161 + port: device.snmp_port || 161, + monitoring_enabled: device.monitoring_enabled || false, + check_interval_seconds: device.check_interval_seconds || 60 }, queries: build_discovery_queries() } @@ -168,7 +179,9 @@ defmodule ToweropsWeb.AgentChannel do ip: device.ip_address, community: device.snmp_community, version: device.snmp_version, - port: device.snmp_port || 161 + port: device.snmp_port || 161, + monitoring_enabled: device.monitoring_enabled || false, + check_interval_seconds: device.check_interval_seconds || 60 }, queries: build_polling_queries(device) } @@ -357,6 +370,35 @@ defmodule ToweropsWeb.AgentChannel do # since it requires complex LLDP/CDP parsing end + defp process_monitoring_check(organization_id, check) do + with {:ok, device} <- fetch_device(check.device_id), + :ok <- verify_device_organization(device, organization_id) do + # Parse status from protobuf string ("success" or "failure") + status = + case check.status do + "success" -> :success + "failure" -> :failure + _ -> :failure + end + + timestamp = DateTime.from_unix!(check.timestamp, :second) + + # Create monitoring check record + Monitoring.create_check(%{ + device_id: device.id, + status: status, + response_time_ms: check.response_time_ms, + checked_at: timestamp + }) + else + {:error, :device_not_found} -> + Logger.error("Device not found for monitoring check: #{check.device_id}") + + {:error, :wrong_organization} -> + Logger.error("Device #{check.device_id} not in agent's organization") + end + end + # Enqueue discovery job - safe to call in test environment defp enqueue_discovery(device_id) do if Application.get_env(:towerops, :env) == :test do