logging fix and some other codex fixes
This commit is contained in:
parent
3e70f0ba48
commit
e026930f25
11 changed files with 74 additions and 63 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -92,6 +92,7 @@ profiles.json
|
|||
.runtime/
|
||||
.claude/
|
||||
.beads/
|
||||
.agents/
|
||||
.logs/
|
||||
.direnv/
|
||||
|
||||
|
|
|
|||
|
|
@ -1906,10 +1906,22 @@ defmodule Towerops.Snmp do
|
|||
end)
|
||||
|> tap(fn {_s, errors, error_samples} ->
|
||||
if errors > 0 do
|
||||
Logger.warning("#{errors} ARP upsert failures for device #{device_id}",
|
||||
samples_text =
|
||||
case Enum.reverse(error_samples) do
|
||||
[] ->
|
||||
""
|
||||
|
||||
samples ->
|
||||
"\nSample errors:\n" <>
|
||||
Enum.map_join(samples, "\n", fn sample ->
|
||||
" - IP: #{sample.ip}, MAC: #{sample.mac}, errors: #{inspect(sample.errors)}"
|
||||
end)
|
||||
end
|
||||
|
||||
Logger.warning(
|
||||
"#{errors} ARP upsert failures for device #{device_id}#{samples_text}",
|
||||
device_id: device_id,
|
||||
error_count: errors,
|
||||
sample_errors: Enum.reverse(error_samples)
|
||||
error_count: errors
|
||||
)
|
||||
end
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -398,12 +398,6 @@ defmodule ToweropsWeb.AgentLive.Index do
|
|||
{:noreply, maybe_update_agent(socket, agent_token_id, organization_id)}
|
||||
end
|
||||
|
||||
# Handled by StatusTitleComponent in layout - ignore to prevent crashes
|
||||
@impl true
|
||||
def handle_info({:alert_changed, _org_id}, socket) do
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:agents_stale, _stale_agents}, socket) do
|
||||
{:noreply, reload_agent_data(socket)}
|
||||
|
|
|
|||
|
|
@ -186,11 +186,6 @@ defmodule ToweropsWeb.AlertLive.Index do
|
|||
{:noreply, load_alerts(socket, socket.assigns.current_scope.organization.id)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:alert_changed, _org_id}, socket) do
|
||||
{:noreply, load_alerts(socket, socket.assigns.current_scope.organization.id)}
|
||||
end
|
||||
|
||||
defp load_alerts(socket, organization_id) do
|
||||
all_alerts = Alerts.list_organization_alerts(organization_id, %{"limit" => 500})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,37 +1,9 @@
|
|||
defmodule ToweropsWeb.Live.Components.StatusTitleComponent do
|
||||
@moduledoc """
|
||||
LiveComponent that subscribes to organization alert changes and updates the page title emoji.
|
||||
LiveComponent that renders the browser-title status hook target.
|
||||
"""
|
||||
use ToweropsWeb, :live_component
|
||||
|
||||
alias ToweropsWeb.Helpers.StatusHelpers
|
||||
|
||||
def mount(socket) do
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
def update(%{organization_id: org_id}, socket) do
|
||||
if connected?(socket) do
|
||||
Phoenix.PubSub.subscribe(Towerops.PubSub, "organization:#{org_id}:alerts")
|
||||
end
|
||||
|
||||
{:ok, assign(socket, :organization_id, org_id)}
|
||||
end
|
||||
|
||||
def handle_info({:alert_changed, _org_id}, socket) do
|
||||
# Get the organization from the parent socket
|
||||
org_id = socket.assigns.organization_id
|
||||
organization = Towerops.Organizations.get_organization!(org_id)
|
||||
|
||||
if organization do
|
||||
emoji = StatusHelpers.status_emoji(organization)
|
||||
# Push event to JavaScript hook to update the browser title
|
||||
{:noreply, push_event(socket, "update_status_emoji", %{emoji: emoji})}
|
||||
else
|
||||
{:noreply, socket}
|
||||
end
|
||||
end
|
||||
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div id="status-title-watcher" phx-hook="StatusTitle" phx-target={@myself} style="display: none;">
|
||||
|
|
|
|||
|
|
@ -96,11 +96,6 @@ defmodule ToweropsWeb.DashboardLive do
|
|||
{:noreply, load_dashboard_data(socket, socket.assigns.current_scope.organization.id)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:alert_changed, _org_id}, socket) do
|
||||
{:noreply, load_dashboard_data(socket, socket.assigns.current_scope.organization.id)}
|
||||
end
|
||||
|
||||
defp load_dashboard_data(socket, organization_id) do
|
||||
organization = socket.assigns.current_scope.organization
|
||||
summary = Dashboard.get_dashboard_summary(organization_id)
|
||||
|
|
|
|||
|
|
@ -276,12 +276,6 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
{:noreply, reload_device_stream(socket)}
|
||||
end
|
||||
|
||||
# Handled by StatusTitleComponent in layout - ignore to prevent crashes
|
||||
@impl true
|
||||
def handle_info({:alert_changed, _org_id}, socket) do
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
defp tick_interval_ms do
|
||||
if Application.get_env(:towerops, :env) == :test, do: :infinity, else: to_timeout(second: 15)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -244,12 +244,6 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
{:noreply, assign(socket, :show_check_form, false)}
|
||||
end
|
||||
|
||||
# Handled by StatusTitleComponent in layout - ignore to prevent crashes
|
||||
@impl true
|
||||
def handle_info({:alert_changed, _org_id}, socket) do
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
# Private functions
|
||||
|
||||
defp maybe_subscribe_and_schedule_refresh(socket, device_id) do
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ defmodule ToweropsWeb.Router do
|
|||
{ToweropsWeb.UserAuth, :require_authenticated_user},
|
||||
{ToweropsWeb.UserAuth, :require_totp_enrollment},
|
||||
{ToweropsWeb.UserAuth, :load_current_organization},
|
||||
{ToweropsWeb.UserAuth, :subscribe_to_status_updates},
|
||||
{ToweropsWeb.UserAuth, :handle_policy_consent}
|
||||
] do
|
||||
scope "/orgs/:org_slug", ToweropsWeb do
|
||||
|
|
@ -389,6 +390,7 @@ defmodule ToweropsWeb.Router do
|
|||
{ToweropsWeb.UserAuth, :require_authenticated_user},
|
||||
{ToweropsWeb.UserAuth, :require_totp_enrollment},
|
||||
{ToweropsWeb.UserAuth, :load_default_organization},
|
||||
{ToweropsWeb.UserAuth, :subscribe_to_status_updates},
|
||||
{ToweropsWeb.UserAuth, :handle_policy_consent}
|
||||
] do
|
||||
scope "/", ToweropsWeb do
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ defmodule ToweropsWeb.UserAuth do
|
|||
alias Phoenix.LiveView
|
||||
alias Towerops.Accounts
|
||||
alias Towerops.Accounts.Scope
|
||||
alias ToweropsWeb.Helpers.StatusHelpers
|
||||
|
||||
# Make the remember me cookie valid for 14 days. This should match
|
||||
# the session validity setting in UserToken.
|
||||
|
|
@ -545,9 +546,10 @@ defmodule ToweropsWeb.UserAuth do
|
|||
def on_mount(:subscribe_to_status_updates, _params, _session, socket) do
|
||||
organization = socket.assigns[:current_scope] && socket.assigns.current_scope.organization
|
||||
|
||||
if organization && LiveView.connected?(socket) do
|
||||
Phoenix.PubSub.subscribe(Towerops.PubSub, "organization:#{organization.id}:alerts")
|
||||
end
|
||||
socket =
|
||||
socket
|
||||
|> maybe_subscribe_to_status_updates(organization)
|
||||
|> attach_status_title_hook(organization)
|
||||
|
||||
{:cont, socket}
|
||||
end
|
||||
|
|
@ -980,4 +982,25 @@ defmodule ToweropsWeb.UserAuth do
|
|||
|
||||
defp determine_login_method(_conn, %{"remember_me" => _}), do: "password"
|
||||
defp determine_login_method(_conn, _params), do: "password"
|
||||
|
||||
defp maybe_subscribe_to_status_updates(socket, organization) do
|
||||
if organization && LiveView.connected?(socket) do
|
||||
Phoenix.PubSub.subscribe(Towerops.PubSub, "organization:#{organization.id}:alerts")
|
||||
end
|
||||
|
||||
socket
|
||||
end
|
||||
|
||||
defp attach_status_title_hook(socket, nil), do: socket
|
||||
|
||||
defp attach_status_title_hook(socket, organization) do
|
||||
LiveView.attach_hook(socket, :status_title_updates, :handle_info, fn
|
||||
{:alert_changed, org_id}, socket when org_id == organization.id ->
|
||||
emoji = StatusHelpers.status_emoji(organization)
|
||||
{:halt, LiveView.push_event(socket, "update_status_emoji", %{emoji: emoji})}
|
||||
|
||||
_message, socket ->
|
||||
{:cont, socket}
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -144,6 +144,35 @@ defmodule ToweropsWeb.SiteLiveTest do
|
|||
live(conn, ~p"/sites/#{other_site.id}")
|
||||
end
|
||||
end
|
||||
|
||||
test "handles alert_changed broadcasts without crashing and pushes title update", %{
|
||||
conn: conn,
|
||||
organization: organization
|
||||
} do
|
||||
{:ok, site} =
|
||||
Sites.create_site(%{name: "Alert Site", organization_id: organization.id})
|
||||
|
||||
{:ok, device} =
|
||||
Towerops.Devices.create_device(%{
|
||||
name: "Tower Router",
|
||||
ip_address: "10.0.0.1",
|
||||
site_id: site.id,
|
||||
organization_id: organization.id
|
||||
})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/sites/#{site.id}")
|
||||
|
||||
{:ok, _alert} =
|
||||
Towerops.Alerts.create_alert(%{
|
||||
device_id: device.id,
|
||||
alert_type: "device_down",
|
||||
triggered_at: DateTime.utc_now(),
|
||||
message: "Device down"
|
||||
})
|
||||
|
||||
assert_push_event(view, "update_status_emoji", %{emoji: "🔴"})
|
||||
assert render(view) =~ "Alert Site"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Show - Metrics Bar" do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue