974 lines
63 KiB
Text
974 lines
63 KiB
Text
2026-02-13
|
|
refactor: zero credo strict issues — fix all warnings, readability, nesting, aliases
|
|
fix: broken route paths in dashboard and insights templates
|
|
feat: device list polish — status summary bar, compact mode, type icons, hover previews
|
|
feat: loading skeletons and page fade-in transitions
|
|
feat: SEO meta tags, OG tags, favicon, theme-color in root layout
|
|
feat: global CSS polish — smooth transitions, hover effects, scrollbar styling, status pulse
|
|
feat: loading skeletons and page fade-in transitions
|
|
feat: breadcrumb navigation on device detail, site detail, config timeline, trace pages
|
|
feat: nav search trigger button with ⌘K keyboard shortcut hint
|
|
fix: remove experimental badges from Alerts and Network Map nav
|
|
feat: polished empty states for alerts (all-clear), insights, sites pages
|
|
feat: enhanced activity feed — real-time updates, time grouping, search, device links, item counts
|
|
feat: complete marketing page rewrite — WISP-focused positioning, pain points, pricing tiers, use cases
|
|
fix: safer float formatting, nil crash prevention in templates
|
|
fix: add missing age_text and severity_color helpers to alert_live
|
|
fix: prevent nil Decimal/Calendar crashes in trace template
|
|
feat: smart alert triage with site grouping, severity colors, and resolve
|
|
- Alerts page now groups by site (tower) with subscriber impact counts
|
|
- Filter tabs: All, Critical, Unresolved, Resolved
|
|
- Sort by severity, age, or subscriber impact
|
|
- Resolve button to mark alerts as resolved
|
|
- Color-coded severity indicators
|
|
feat: global search (Cmd+K / Ctrl+K) across devices, sites, accounts, alerts
|
|
- Spotlight-style search overlay
|
|
- Categorized results with icons
|
|
- Keyboard navigation (up/down/enter/esc)
|
|
- Debounced search input
|
|
feat: rewrite site detail page with full enrichment
|
|
- Summary stat cards (subscribers, MRR, devices, alerts)
|
|
- QoE summary with capacity bar
|
|
- Device health grid with status dots and response times
|
|
- Active alerts panel with urgency indicators
|
|
- Recent config changes panel
|
|
feat: add Trace, Activity Feed routes and nav items
|
|
- Wired /trace (subscriber trace / help desk mode) into router
|
|
- Wired /activity (org-wide activity feed) into router
|
|
- Added Trace and Activity to desktop and mobile navigation
|
|
- Fixed all compile errors in trace_live (missing helpers, components)
|
|
- Removed broken changelog_live (missing ChangelogParser dep)
|
|
|
|
feat: device list health indicators
|
|
- Added health status dot (green/yellow/red/gray) per device row from worst-case check state
|
|
- Added relative "last seen" indicator with color-coded staleness
|
|
- Added response time badge from latest monitoring check
|
|
- Added subscriber count badge from Gaiia inventory items
|
|
- New batch queries: Monitoring.get_device_health_summary/1,
|
|
Monitoring.get_device_latest_response_times/1, Gaiia.get_device_subscriber_counts/1
|
|
- All queries batched to avoid N+1 on device list page
|
|
|
|
feat: config change → performance correlation system (Roadmap #2)
|
|
- New `config_change_events` table + migration linking backup diffs to time windows
|
|
- Schema: device_id, organization_id, backup_before_id, backup_after_id, changed_at,
|
|
diff_summary, sections_changed (array), change_size
|
|
- `Towerops.ConfigChanges` context: record_change_event/3, list_device_changes/2,
|
|
list_org_changes/2 with date range filters (:after, :before, :limit)
|
|
- Automatic section detection from diffs (firewall, interface, routing, wireless, queue,
|
|
nat, address, dns, dhcp, bridge, vlan, snmp, user, system, ppp)
|
|
- Enhanced agent_channel backup flow: after MikrotikBackup creation, automatically
|
|
emits config_change_event when hash differs from previous backup
|
|
- `Towerops.ConfigChanges.Correlator` engine: compares Preseem QoE metrics in a
|
|
2h-before / 4h-after window around config changes
|
|
- Calculates metric deltas (latency, jitter, loss, throughput) and scores significance
|
|
(latency >20%, loss >50%, throughput drop >15%)
|
|
- Creates "suspect_config_change" insight with severity (warning/critical) and full
|
|
metric delta data when correlation detected
|
|
- Added "suspect_config_change" to valid insight types
|
|
- New Config Timeline LiveView at /devices/:device_id/config-timeline
|
|
- Date range selector (24h, 7d, 30d)
|
|
- QoE metrics data (latency, throughput, loss) passed to chart hook
|
|
- Check results (up/down) status data for status bar
|
|
- Config change events as clickable table rows with diff summary detail view
|
|
- Links to full backup compare view for each change
|
|
- Device page integration: "Config Timeline" tab in device detail navigation,
|
|
"Recent Config Changes" mini-card in overview with color-coded size indicators
|
|
- Dashboard integration: "Recent Config Changes" section showing org-wide changes
|
|
with device name, timestamp, sections changed, and color-coded impact dots
|
|
- Fixed pre-existing bug: integrations_live.html.heex sync schedule block was
|
|
outside the `if integration` scope, causing compilation error
|
|
|
|
2026-02-13
|
|
feat: unified insights page, integration nav improvements, sync transparency
|
|
- Created top-level Insights LiveView at /insights (replaces buried settings page)
|
|
- Unified insights from all sources (Preseem, Gaiia, SNMP, System) in one view
|
|
- Source filter pills, urgency filters (Critical/Warning/Info), status tabs (Active/Dismissed)
|
|
- Bulk select/dismiss with select all/deselect all
|
|
- URL param support: ?source=preseem&urgency=critical&status=active
|
|
- Added "Insights" to main navigation bar (desktop + mobile) between Alerts and Agents
|
|
- Added route /insights in authenticated scope
|
|
- Integration pages now show sync schedule info:
|
|
- Preseem: "Syncs every N minutes. Baselines and fleet profiles computed nightly."
|
|
- Gaiia: "Syncs every N minutes. Reconciliation runs nightly. Real-time webhook updates."
|
|
- "Next sync in ~Xm" calculated from last_synced_at + sync_interval_minutes
|
|
- Exposed sync_interval_minutes as editable field in integration config form (min: 5)
|
|
- Added next_sync_minutes/2 helper to IntegrationsLive
|
|
- Added horizontal tab navigation to integration detail pages:
|
|
- Preseem: Devices | Insights (links to /insights?source=preseem)
|
|
- Gaiia: Entity Mapping | Reconciliation
|
|
- Dashboard insights section now links to /insights (View All →)
|
|
- Dashboard insight titles clickable, linking to /insights?source={source}
|
|
- Integration "Network Insights →" link now points to /insights?source=preseem
|
|
- Old /settings/integrations/preseem/insights route kept for backward compatibility
|
|
- Files: lib/towerops_web/components/layouts.ex, lib/towerops_web/router.ex,
|
|
lib/towerops_web/live/insights_live/index.ex,
|
|
lib/towerops_web/live/insights_live/index.html.heex,
|
|
lib/towerops_web/live/org/integrations_live.ex,
|
|
lib/towerops_web/live/org/integrations_live.html.heex,
|
|
lib/towerops_web/live/org/preseem_devices_live.html.heex,
|
|
lib/towerops_web/live/org/gaiia_mapping_live.html.heex,
|
|
lib/towerops_web/live/org/gaiia_reconciliation_live.html.heex,
|
|
lib/towerops_web/live/dashboard_live.html.heex
|
|
|
|
2026-02-13
|
|
feat: impact dashboard with MRR at risk, active incidents, enhanced site health
|
|
- Added Dashboard.get_impact_summary/1: aggregates current outage impact —
|
|
total subscribers affected, MRR at risk, sites with outages, down device count.
|
|
Computes Gaiia ImpactAnalysis for each down device.
|
|
- Added Dashboard.list_active_incidents/1: returns down devices enriched with
|
|
Gaiia subscriber impact (subscribers, MRR), Preseem QoE score, site info,
|
|
and outage duration (from last_status_change_at). Sorted by MRR descending.
|
|
- Added Dashboard.get_site_impact_summaries/1: enhanced site summaries with
|
|
subscribers_affected, mrr_at_risk (from down devices), avg_qoe (from Preseem APs),
|
|
and site_health (:green/:yellow/:red based on device status + QoE thresholds).
|
|
- Dashboard top stats row: added "MRR at Risk" card (red when > $0, shows affected
|
|
subscriber count) and conditional display when impact data exists.
|
|
- New "Active Incidents" section between stats and alerts: each incident card shows
|
|
device name, site link, downtime duration, subscribers affected, MRR at risk,
|
|
Preseem QoE score. Color-coded by MRR severity (red ≥$1k, orange ≥$100, yellow >$0).
|
|
- Enhanced Site Health Grid using site_impact_summaries: color-coded health dots
|
|
(green/yellow/red), QoE scores, subscribers affected, MRR at risk per site.
|
|
- Added helper functions: format_duration/1, incident_severity_classes/1,
|
|
site_health_border/1, site_health_dot/1, decimal_to_float/1, mrr_at_risk_positive?/1,
|
|
format_qoe/1
|
|
- Impact analysis only computed for currently-down devices (performance guard)
|
|
- Existing empty-state (0 devices) flow untouched
|
|
- Files: lib/towerops/dashboard.ex, lib/towerops_web/live/dashboard_live.ex,
|
|
lib/towerops_web/live/dashboard_live.html.heex
|
|
|
|
2026-02-13
|
|
feat: add 12/24-hour time format setting with consistent timezone display
|
|
- Wired time_format into Scope struct (for_user/1, for_impersonation/2)
|
|
- Added time_format to User profile_changeset with validation (12h/24h)
|
|
- Added time format selector to Personal tab in user settings
|
|
- Changed TimeHelpers defaults from 12h to 24h format
|
|
- Added format_datetime_for_scope/2 convenience function
|
|
- Added format_utc_hour/3 with configurable time_format
|
|
- Updated format_timestamp_in_timezone to accept time_format parameter
|
|
- Replaced all user-facing Calendar.strftime calls with centralized helpers
|
|
- Files: lib/towerops/accounts/scope.ex, lib/towerops/accounts/user.ex,
|
|
lib/towerops_web/helpers/time_helpers.ex,
|
|
lib/towerops_web/live/user_settings_live/helpers.ex,
|
|
lib/towerops_web/live/user_settings_live.ex,
|
|
lib/towerops_web/live/user_settings_live.html.heex,
|
|
lib/towerops_web/live/account_live/my_data.ex,
|
|
lib/towerops_web/live/account_live/activity.ex,
|
|
lib/towerops_web/live/admin/audit_live/index.ex,
|
|
lib/towerops_web/live/device_live/show.html.heex,
|
|
lib/towerops_web/live/mikrotik_backup_live/compare.html.heex,
|
|
lib/towerops_web/live/org/preseem_insights_live.html.heex,
|
|
lib/towerops_web/live/org/gaiia_reconciliation_live.html.heex,
|
|
lib/towerops_web/controllers/user_settings_html/edit.html.heex
|
|
|
|
2026-02-13
|
|
feat: command center dashboard with unified insights and contextual enrichment
|
|
- Stage 1: Unified insight system (schema + workers)
|
|
- Migration: add source, site_id, agent_token_id columns to preseem_insights
|
|
- Extended Insight schema with source field (preseem, snmp, gaiia, system) and new types
|
|
- Extended Insights context with source filter, count_active_by_urgency/1, site_id dedup
|
|
- New DeviceHealthInsightWorker: generates snmp_cpu_high, snmp_memory_high, device_poll_gap insights
|
|
- New SystemInsightWorker: generates agent_offline insights, auto-resolves when agent returns
|
|
- New GaiiaInsightWorker: generates reconciliation_finding insights from Gaiia reconciliation
|
|
- Oban cron config for all three workers
|
|
- Files: priv/repo/migrations/*_add_source_to_preseem_insights.exs,
|
|
lib/towerops/preseem/insight.ex, lib/towerops/preseem/insights.ex,
|
|
lib/towerops/workers/device_health_insight_worker.ex,
|
|
lib/towerops/workers/system_insight_worker.ex,
|
|
lib/towerops/workers/gaiia_insight_worker.ex, config/runtime.exs
|
|
- Stage 2: Dashboard context + health score
|
|
- New Towerops.Dashboard context aggregating data from Alerts, Devices, Sites, Gaiia, Insights
|
|
- Health score computation (weighted: uptime 50%, response 25%, alerts 25%)
|
|
- Site summaries with device counts, alerts, subscriber/MRR data
|
|
- Gaiia subscriber totals (get_org_subscriber_totals/1, get_site_subscriber_summary/1)
|
|
- Files: lib/towerops/dashboard.ex, lib/towerops/gaiia.ex
|
|
- Stage 3: Command center dashboard LiveView rewrite
|
|
- Health overview section: health score, active alerts, device counts (up/down/unknown),
|
|
subscribers/MRR (conditional), insights by urgency
|
|
- Two-column layout: alert feed (20 alerts) with acknowledge buttons and Gaiia impact badges,
|
|
insight feed with source filter pills (All/Preseem/SNMP/Gaiia/System) and dismiss buttons
|
|
- Site health grid: responsive cards with device counts, down indicators, subscriber data
|
|
- URL state management for insight source filter via push_patch/handle_params
|
|
- Real-time PubSub updates for alert new/resolved events
|
|
- Preserves empty state onboarding when no devices exist
|
|
- Files: lib/towerops_web/live/dashboard_live.ex, lib/towerops_web/live/dashboard_live.html.heex
|
|
- Stage 4: Site detail enrichment
|
|
- Metrics bar on site show page: device count, down count, alert count badges
|
|
- Conditional subscriber/MRR badges when Gaiia network site is mapped
|
|
- Added count_site_active_alerts/1 to Alerts context
|
|
- Extended Dashboard.get_site_summary/1 with alert_count
|
|
- Files: lib/towerops_web/live/site_live/show.ex, lib/towerops_web/live/site_live/show.html.heex,
|
|
lib/towerops/alerts.ex, lib/towerops/dashboard.ex
|
|
- Stage 5: Alert and device list enrichment
|
|
- Alert list: subscriber count and MRR context inline with site name links
|
|
- Device list: subscriber badge on site headers when Gaiia network site is mapped
|
|
- Batch-loads site subscriber data for efficient display
|
|
- Files: lib/towerops_web/live/alert_live/index.ex, lib/towerops_web/live/alert_live/index.html.heex,
|
|
lib/towerops_web/live/device_live/index.ex, lib/towerops_web/live/device_live/index.html.heex
|
|
- Tests: test/towerops/dashboard_test.exs, test/towerops/preseem/insight_test.exs,
|
|
test/towerops/preseem/insights_test.exs, test/towerops/gaiia_test.exs,
|
|
test/towerops/workers/device_health_insight_worker_test.exs,
|
|
test/towerops/workers/system_insight_worker_test.exs,
|
|
test/towerops/workers/gaiia_insight_worker_test.exs,
|
|
test/towerops_web/live/dashboard_live_test.exs,
|
|
test/towerops_web/live/site_live_test.exs,
|
|
test/towerops_web/live/alert_live_test.exs,
|
|
test/towerops_web/live/device_live/index_test.exs
|
|
|
|
feat: complete gaiia integration (stages 3-7)
|
|
- Stage 3: Webhook listener for real-time Gaiia events
|
|
- POST /api/v1/webhooks/gaiia/:organization_id
|
|
- HMAC-SHA256 per-org signature verification
|
|
- Handles account.*, billing_subscription.*, inventory_item.* events
|
|
- Files: lib/towerops/gaiia/webhooks.ex, lib/towerops_web/controllers/api/v1/gaiia_webhook_controller.ex
|
|
- Stage 4: Subscriber-aware device pages
|
|
- Gaiia tab on device detail showing inventory item, subscriber, billing subscriptions
|
|
- IP address mismatch indicator between Towerops and Gaiia
|
|
- Files: lib/towerops_web/live/device_live/show.ex, show.html.heex
|
|
- Stage 5: Outage impact analysis
|
|
- Two-layer analysis: device-level (inventory→subscriber) and site-level (network site→all subscribers)
|
|
- Impact auto-computed on device_down alerts, stored as JSONB on alert record
|
|
- Subscriber count and MRR badges on alert list page
|
|
- Files: lib/towerops/gaiia/impact_analysis.ex, lib/towerops/alerts.ex, lib/towerops/alerts/alert.ex
|
|
- Migration: add gaiia_impact column to alerts table
|
|
- Stage 6: Write-back actions (Towerops → Gaiia)
|
|
- Ticket creation from alerts via createExternalTicket mutation
|
|
- Subscriber notes during outages via createNote mutation
|
|
- Inventory item updates (IP, serial, MAC) via updateInventoryItem mutation
|
|
- Files: lib/towerops/gaiia/actions.ex, lib/towerops/gaiia/client.ex (mutations added)
|
|
- Stage 7: Inventory reconciliation
|
|
- Detects ghost devices, untracked devices, data mismatches, missing mappings
|
|
- Dedicated LiveView page with summary cards and tabbed discrepancy tables
|
|
- Files: lib/towerops/gaiia/reconciliation.ex, lib/towerops_web/live/org/gaiia_reconciliation_live.ex
|
|
|
|
fix: prevent agent channel graceful shutdowns from being logged as exceptions
|
|
- Changed Phoenix Channel stop reasons to use {:shutdown, reason} tuple instead
|
|
of bare atoms to signal graceful termination
|
|
- Updated heartbeat_timeout, token_disabled, and restart_requested handlers
|
|
- Prevents error tracking systems from incorrectly reporting normal agent
|
|
disconnections as ErlangError exceptions
|
|
- These events are expected operational occurrences (timeouts, admin actions)
|
|
- File: lib/towerops_web/channels/agent_channel.ex
|
|
|
|
2026-02-12
|
|
feat: complete migration from DevicePollerWorker to CheckExecutorWorker
|
|
- Removed all DevicePollerWorker scheduling from device lifecycle
|
|
- Checks now automatically scheduled via Monitoring.schedule_check when created
|
|
- Discovery creates checks and schedules them in a single transaction
|
|
- Added Monitoring.stop_device_checks/1 to cancel all check jobs for a device
|
|
- Added Monitoring.disable_device_checks/1 to disable checks when SNMP is turned off
|
|
- Device creation: removed polling start (checks created during discovery)
|
|
- Device deletion: replaced DevicePollerWorker.stop_polling with stop_device_checks
|
|
- SNMP enable/disable: replaced polling control with check enable/disable
|
|
- DevicePollerWorker no longer referenced in devices.ex (fully migrated)
|
|
- System now runs single unified polling mechanism via CheckExecutorWorker
|
|
- Files: lib/towerops/devices.ex, lib/towerops/monitoring.ex,
|
|
lib/towerops/snmp/discovery.ex
|
|
|
|
2026-02-12
|
|
feat: add check creation from SNMP discovery and backfill task (Phase 5)
|
|
- Implemented create_checks_from_discovery/2 in Discovery module to auto-create
|
|
checks for all discovered SNMP entities (sensors, interfaces, processors, storage)
|
|
- Discovery now creates check records enabling unified monitoring after completing
|
|
SNMP discovery, linking checks to source entities via source_id
|
|
- Added mix backfill.checks task to create checks for existing devices with
|
|
SNMP discovery data, includes dry-run mode and comprehensive error reporting
|
|
- Returns detailed results map with counts per entity type and any errors
|
|
- Private helper functions: create_sensor_check/2, create_interface_check/2,
|
|
create_processor_check/2, create_storage_check/2
|
|
- All checks default to 60-second intervals, enabled state, auto_discovery source
|
|
- Files: lib/towerops/snmp/discovery.ex, lib/mix/tasks/backfill_checks.ex
|
|
|
|
2026-02-12
|
|
docs: add Terraform provider documentation to public API docs
|
|
- Added comprehensive Terraform provider section to /docs/api page with navigation link
|
|
- Documented what Terraform is and how it integrates with Towerops API
|
|
- Included getting started guide, installation instructions, and example usage
|
|
- Added links to Terraform Registry documentation and GitHub repository
|
|
- Covers towerops_site and towerops_device resources with full examples
|
|
- Files: lib/towerops_web/controllers/api_docs_html/index.html.heex
|
|
|
|
2026-02-12
|
|
test: comprehensive test suite for unified checks system (Phase 4)
|
|
- Added SnmpSensorExecutor tests covering standardized response format, status codes,
|
|
limit-based thresholds, error handling, and Mox-based SNMP mocking
|
|
- Added CheckExecutorWorker tests for dispatcher routing, result recording, scheduling,
|
|
error handling, and check state management
|
|
- Verified create_checks_from_discovery integration with 6 comprehensive tests
|
|
- Verified graphing function (get_check_graph_data) handles both check_results and
|
|
legacy snmp_sensor_readings tables correctly - All 141 monitoring and SNMP tests passing
|
|
- Files: test/towerops/monitoring/executors/snmp_sensor_executor_test.exs,
|
|
test/towerops/workers/check_executor_worker_test.exs, test/towerops/snmp_test.exs
|
|
|
|
2026-02-12
|
|
fix: SNMP executor build_snmp_opts reading from wrong schema fields
|
|
- Fixed SnmpSensorExecutor, SnmpInterfaceExecutor, SnmpProcessorExecutor, and
|
|
SnmpStorageExecutor to read SNMP credentials from device.snmp_version,
|
|
device.snmp_community, device.snmpv3_* instead of incorrectly accessing
|
|
device.snmp_device.version (which doesn't exist on Snmp.Device schema)
|
|
- Issue discovered via TDD while writing comprehensive executor tests
|
|
- All executors now correctly build SNMP connection options matching the
|
|
pattern used by Snmp.Poller.build_client_opts/1
|
|
- Files: lib/towerops/monitoring/executors/snmp_sensor_executor.ex,
|
|
lib/towerops/monitoring/executors/snmp_interface_executor.ex,
|
|
lib/towerops/monitoring/executors/snmp_processor_executor.ex,
|
|
lib/towerops/monitoring/executors/snmp_storage_executor.ex,
|
|
test/towerops/monitoring/executors/snmp_sensor_executor_test.exs
|
|
- Removed outdated test/towerops/monitoring/check_test.exs (was testing CheckResult
|
|
fields on Check schema)
|
|
|
|
2026-02-12
|
|
feat: unified checks system for SNMP and service monitoring
|
|
- Implemented comprehensive unified checks architecture combining SNMP auto-discovery
|
|
with manual HTTP/TCP/DNS service checks
|
|
- Database: Added source_type and source_id fields to checks table, created check_results
|
|
TimescaleDB hypertable for unified time-series storage
|
|
- SNMP Executors: Created SnmpSensorExecutor, SnmpInterfaceExecutor, SnmpProcessorExecutor,
|
|
SnmpStorageExecutor with standardized {:ok, %{value:, status:, output:, response_time_ms:}} format
|
|
- Workers: Implemented CheckExecutorWorker with dispatcher pattern, replacing device-specific
|
|
polling for SNMP checks
|
|
- Discovery Integration: SNMP discovery now auto-creates checks for all sensors, interfaces,
|
|
processors, and storage with source tracking
|
|
- UI: Added checks tab to device detail page with grouped display, status badges, empty state,
|
|
and manual check creation modal
|
|
- Check Form: Built CheckLive.FormComponent modal for adding HTTP/TCP/DNS checks with
|
|
dynamic fields based on check type
|
|
- Graphing: Updated GraphLive.Show to support check-based graphs, query both check_results
|
|
and legacy snmp_sensor_readings tables for seamless historical data
|
|
- Testing: Added comprehensive test suite for create_checks_from_discovery covering sensors,
|
|
interfaces, processors, storage, and Oban job scheduling
|
|
- Files: lib/towerops/monitoring.ex, lib/towerops/snmp.ex,
|
|
lib/towerops/monitoring/executors/*.ex, lib/towerops/workers/check_executor_worker.ex,
|
|
lib/towerops_web/live/device_live/show.ex, lib/towerops_web/live/check_live/form_component.ex,
|
|
lib/towerops_web/live/graph_live/show.ex, lib/towerops_web/router.ex,
|
|
priv/repo/migrations/*_add_source_fields_to_checks.exs,
|
|
priv/repo/migrations/*_add_value_to_check_results.exs,
|
|
test/towerops/snmp_test.exs
|
|
|
|
2026-02-12
|
|
fix: prevent AlreadySentError in BruteForceProtection plug
|
|
- Fixed production exception where the plug attempted to register a before_send
|
|
callback after already sending a 403 response to banned IPs
|
|
- Modified call/2 to check conn.halted before calling maybe_track_404/2
|
|
- Updated test to verify proper behavior without AlreadySentError workaround
|
|
- Files: lib/towerops_web/plugs/brute_force_protection.ex,
|
|
test/towerops_web/plugs/brute_force_protection_test.exs
|
|
|
|
CHANGELOG - towerops-web
|
|
========================
|
|
|
|
2026-02-12 - fix: reload device stream when switching back to existing devices tab
|
|
- File: lib/towerops_web/live/device_live/index.ex (apply_action/4)
|
|
Fixed 60-second delay when navigating from "discovered devices" tab back to "existing devices" tab.
|
|
The device stream existed in LiveView assigns from mount/3, but when the DOM element with
|
|
phx-update="stream" was removed (viewing discovered tab) and re-added (switching back), LiveView
|
|
didn't automatically re-render the stream data. Users had to wait for the next PubSub update
|
|
(device_status_changed) or periodic :tick event (every 15 seconds) to trigger reload_device_stream,
|
|
which could take 60+ seconds.
|
|
|
|
Fix: Explicitly reload the device stream when switching to "existing" tab by calling
|
|
list_organization_devices and stream(:device_rows, build_device_rows(devices), reset: true),
|
|
matching the pattern used when loading the discovered tab. Now the table appears instantly.
|
|
|
|
2026-02-12 - fix: suppress benign shutdown errors during K8s pod rollouts
|
|
- Files: lib/towerops/honeybadger_notice_filter.ex, lib/towerops/honeybadger_filter.ex,
|
|
lib/towerops/logger_filters.ex, config/config.exs, config/runtime.exs,
|
|
lib/towerops/application.ex, test/towerops/honeybadger_notice_filter_test.exs,
|
|
test/towerops/honeybadger_filter_test.exs, test/towerops/logger_filters_test.exs
|
|
|
|
Filter port_died and write_failed/epipe errors from Honeybadger reports, email notifications,
|
|
and logger output. These are benign artifacts of BEAM shutdown inside containers. Added
|
|
shutdown_error? guard in HoneybadgerNoticeFilter (returns nil to drop notice entirely),
|
|
port_died matching in HoneybadgerFilter's normal_shutdown?, and drop_shutdown_errors logger
|
|
filter. Reordered supervision tree so Oban starts after SnmpKit/TaskSupervisor, ensuring
|
|
it shuts down first and can drain in-flight jobs. Added 40s Oban shutdown_grace_period
|
|
in production config.
|
|
|
|
2026-02-12 - feat: email raw stacktrace on every Honeybadger exception
|
|
- Files: lib/towerops/honeybadger_notice_filter.ex, config/config.exs,
|
|
test/towerops/honeybadger_notice_filter_test.exs
|
|
|
|
Added a Honeybadger NoticeFilter that sends an email with the full error class, message,
|
|
stacktrace, and server environment info to graham@mcintire.me whenever an exception is
|
|
reported. The notice passes through unchanged so Honeybadger still receives it. Uses the
|
|
existing Swoosh mailer (Amazon SES in production, local adapter in dev).
|
|
|
|
2026-02-12 - perf: performance improvements for scale (batch inserts, indexes, selective reloading)
|
|
- Files: lib/towerops/snmp.ex, lib/towerops/devices.ex, lib/towerops_web/channels/agent_channel.ex,
|
|
lib/towerops/workers/device_poller_worker.ex, lib/towerops_web/live/dashboard_live.ex,
|
|
lib/towerops_web/live/device_live/show.ex, lib/towerops_web/live/device_live/index.ex,
|
|
lib/towerops/agents.ex, priv/repo/migrations/20260212155105_add_performance_indexes.exs
|
|
|
|
Phase 1: Batch data ingestion - replaced individual Repo.insert() calls with Repo.insert_all()
|
|
for sensor readings, interface stats, processor readings, and storage readings in both
|
|
agent_channel.ex and device_poller_worker.ex. Added create_*_batch/1 functions to snmp.ex.
|
|
|
|
Phase 2: Database indexes - added partial indexes for monitored sensors/interfaces,
|
|
composite index for devices org+status, partial index for active alerts.
|
|
|
|
Phase 3: Dashboard aggregation - replaced loading all devices into memory with
|
|
Devices.get_device_status_counts/1 GROUP BY query.
|
|
|
|
Phase 4: DeviceLive.Show selective updates - split monolithic load_equipment_data into
|
|
tab-specific loaders (base, tab_nav, overview, ports, logs, backups). PubSub handlers
|
|
now only reload data relevant to the active tab.
|
|
|
|
Phase 5: DeviceLive.Index incremental updates - separated structural changes (create/delete)
|
|
from status changes. Added debouncing for rapid status changes. Skip reload when viewing
|
|
discovered tab.
|
|
|
|
Phase 6: Agent polling memory optimization - filtered preloads in list_agent_polling_targets
|
|
to only load monitored sensors and interfaces instead of all.
|
|
|
|
2026-02-12 - feat: complete WISP vendor coverage (ePMP, Raisecom, Netonix)
|
|
- Files: priv/profiles/os_discovery/epmp.yaml (enhanced), lib/towerops/snmp/profiles/vendors/raisecom.ex (new)
|
|
Completed LibreNMS parity for major WISP equipment vendors. Three improvements:
|
|
|
|
(1) Consolidated ePMP YAML profiles - merged cambium-epmp.yaml enhancements into epmp.yaml
|
|
(added GPS satellite count sensors, proper state_name fields, better field naming), deleted
|
|
duplicate file. ePMP now discovers 11 sensors via YAML + 4 wireless sensors via vendor module.
|
|
|
|
(2) Implemented Raisecom vendor module - fills major 0% coverage gap for Asia-Pacific WISP market.
|
|
Hardware detection via RAISECOM-SYSTEM-MIB with sysDescr fallback. Sensor discovery handled by
|
|
existing YAML (raisecom.yaml, raisecom-ros.yaml) covering 15+ sensors: CPU, memory pools, fan
|
|
speed/state, voltage with thresholds, power supply state, config load state. 8 comprehensive
|
|
tests all passing.
|
|
|
|
(3) Verified Netonix coverage - YAML profile matches LibreNMS 100% (PoE status, voltage,
|
|
temperature, fan, power, current). Vendor module provides additional scalar sensors beyond
|
|
LibreNMS baseline. Netonix coverage exceeds LibreNMS.
|
|
|
|
Tarana investigated: No SNMP support in LibreNMS (newer vendor, likely cloud-managed), would
|
|
require vendor MIBs and documentation to implement.
|
|
|
|
2026-02-12 - test: fix Cambium ePMP test Mox expectations
|
|
- File: test/towerops/snmp/profiles/vendors/cambium_test.exs
|
|
Changed expect() to stub() in all discover_wireless_sensors/1 tests to handle multiple SNMP
|
|
get calls. The implementation makes several calls: static sensor fetch (CPU), ePMP mode
|
|
detection (wirelessInterfaceMode OID), and individual sensor value fetches (RSSI, SNR,
|
|
Frequency, Clients). Using stub() allows unlimited calls vs expect() which enforces exactly
|
|
one call, fixing Mox.UnexpectedCallError in all 7 ePMP-related test cases. All 13 Cambium
|
|
tests now pass correctly.
|
|
|
|
2026-02-12 - fix: sync modal state to URL for browser back/forward navigation
|
|
- Files: lib/towerops_web/live/user_settings_live.ex, lib/towerops_web/live/agent_live/index.ex
|
|
Fixed browser back/forward button navigation by syncing modal state to URL parameters.
|
|
Implemented idiomatic Phoenix LiveView pattern using push_patch/2 and handle_params/3.
|
|
|
|
**UserSettingsLive (6 modals):**
|
|
- add_token, token_created, revoke_all, add_device, device_qr, recovery_codes
|
|
- Updated handle_params/3 to read ?modal= param and set all modal states
|
|
- Added build_settings_path/2 helper to preserve tab and page params
|
|
- Updated all show/close handlers to use push_patch instead of assign
|
|
|
|
**AgentLive.Index (1 modal):**
|
|
- setup modal (displays agent token after creation)
|
|
- Updated handle_params/3 to read ?modal=setup param
|
|
- Updated show_setup and close_token_modal handlers to use push_patch
|
|
|
|
**Result:** Browser back button now closes modals without navigating away from page.
|
|
URLs are bookmarkable and restore exact modal state. Tab and pagination state preserved.
|
|
|
|
**Documentation:** Updated CLAUDE.md with comprehensive browser navigation patterns.
|
|
Created design document: docs/plans/2026-02-12-browser-navigation-fix-design.md
|
|
|
|
2026-02-12 - feat: add comprehensive MikroTik wireless sensor discovery (11 sensor types across 4 MIB tables)
|
|
- Files: lib/towerops/snmp/profiles/vendors/mikrotik.ex (enhanced)
|
|
Implemented TIER 4 LARGE priority wireless sensor discovery for MikroTik RouterOS devices.
|
|
Achieves 100% LibreNMS parity for wireless monitoring (0% → 100% coverage).
|
|
Discovers 11 sensor types across 4 MIB tables:
|
|
|
|
**AP Sensors (mtxrWlApTable .1.3.6.1.4.1.14988.1.1.1.3):**
|
|
- Clients: Station count per AP interface
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.3.1.6 (mtxrWlApClientCount)
|
|
- CCQ: Connection quality percentage (skips when clients>0 && CCQ=0 for NV2)
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.3.1.10 (mtxrWlApOverallTxCCQ)
|
|
- Frequency: Operating frequency in MHz (skips if 0)
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.3.1.7 (mtxrWlApFreq)
|
|
- Noise Floor: Background noise level in dBm
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.3.1.9 (mtxrWlApNoiseFloor)
|
|
- TX Rate: Transmit data rate in bps
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.3.1.2 (mtxrWlApTxRate)
|
|
- RX Rate: Receive data rate in bps
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.3.1.3 (mtxrWlApRxRate)
|
|
|
|
**Station Sensors (mtxrWlStatTable .1.3.6.1.4.1.14988.1.1.1.1):**
|
|
- TX CCQ: Transmit connection quality percentage
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.1.1.9 (mtxrWlStatTxCCQ)
|
|
- RX CCQ: Receive connection quality percentage
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.1.1.10 (mtxrWlStatRxCCQ)
|
|
- Frequency: Operating frequency in MHz
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.1.1.7 (mtxrWlStatFreq)
|
|
- TX Rate: Transmit data rate in bps
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.1.1.2 (mtxrWlStatTxRate)
|
|
- RX Rate: Receive data rate in bps
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.1.1.3 (mtxrWlStatRxRate)
|
|
|
|
**60GHz Sensors (mtxrWl60GTable .1.3.6.1.4.1.14988.1.1.1.8):**
|
|
- Frequency: Operating frequency in MHz
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.8.1.6 (mtxrWl60GFreq)
|
|
- RSSI: Received signal strength in dBm
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.8.1.12 (mtxrWl60GRssi)
|
|
- Quality: Signal quality percentage
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.8.1.8 (mtxrWl60GSignal)
|
|
- PHY Rate: Physical layer rate in bps (divisor: 1,000,000)
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.8.1.13 (mtxrWl60GPhyRate)
|
|
|
|
**60GHz Station Sensors (mtxrWl60GStaTable .1.3.6.1.4.1.14988.1.1.1.9):**
|
|
- Distance: Link distance in km (divisor: 100,000)
|
|
OID: .1.3.6.1.4.1.14988.1.1.1.9.1.10 (mtxrWl60GStaDistance)
|
|
|
|
**LTE Modem Sensors (mtxrLTEModemTable .1.3.6.1.4.1.14988.1.1.16.1):**
|
|
- RSRQ: Reference Signal Received Quality in dB
|
|
OID: .1.3.6.1.4.1.14988.1.1.16.1.1.3 (mtxrLTEModemSignalRSRQ)
|
|
- RSRP: Reference Signal Received Power in dBm
|
|
OID: .1.3.6.1.4.1.14988.1.1.16.1.1.4 (mtxrLTEModemSignalRSRP)
|
|
- SINR: Signal-to-Interference-plus-Noise Ratio in dB
|
|
OID: .1.3.6.1.4.1.14988.1.1.16.1.1.7 (mtxrLTEModemSignalSINR)
|
|
|
|
- Implementation Details:
|
|
- discover_wireless_sensors/1: Calls 5 table-specific discovery functions
|
|
- discover_ap_sensors/1: Walks mtxrWlApTable, builds client/CCQ/freq/noise/rate sensors
|
|
- discover_stat_sensors/1: Walks mtxrWlStatTable, builds TX/RX CCQ and rate sensors
|
|
- discover_60g_sensors/1: Walks mtxrWl60GTable, builds 60GHz sensors
|
|
- discover_60g_sta_sensors/1: Walks mtxrWl60GStaTable, builds distance sensors
|
|
- discover_lte_sensors/1: Walks mtxrLTEModemTable, builds LTE signal sensors
|
|
- group_by_index/1: Groups SNMP walk results by interface index (last OID component)
|
|
- freq_to_label/2: Extracts frequency band label (2437 → "2G", 5180 → "5G")
|
|
- to_integer/1: Safe conversion handling both string and integer SNMP values
|
|
|
|
- Smart Skip Logic (matching LibreNMS):
|
|
- CCQ skipped when clients > 0 but CCQ = 0 (NV2 mode reports clients but no CCQ)
|
|
- Frequency skipped if value is 0
|
|
- TX/RX rate skipped if both are 0
|
|
- Empty CCQ sensors skipped (both TX and RX = 0)
|
|
|
|
- Files: test/towerops/snmp/profiles/vendors/mikrotik_test.exs (enhanced)
|
|
Added comprehensive test coverage with 13 test cases:
|
|
- Tests AP sensor discovery (7 sensors: clients, CCQ, freq, noise, TX/RX rate)
|
|
- Tests station sensor discovery (6 sensors: TX/RX CCQ, freq, TX/RX rate)
|
|
- Tests 60GHz sensor discovery (4 sensors: freq, RSSI, quality, PHY rate)
|
|
- Tests 60GHz station sensor discovery (1 sensor: distance)
|
|
- Tests LTE modem sensor discovery (3 sensors: RSRQ, RSRP, SINR)
|
|
- Tests skip logic for sensors with no data
|
|
- Tests graceful handling when SNMP tables are empty
|
|
All 13 tests passing with Mox-based SNMP adapter mocking.
|
|
|
|
- Impact: Complete wireless monitoring for MikroTik RouterOS devices including
|
|
standard Wi-Fi (2.4/5GHz), 60GHz point-to-point links, and LTE modems.
|
|
Enables detection of connection quality issues, frequency changes, link
|
|
distance problems, and cellular signal degradation.
|
|
|
|
- Source: LibreNMS LibreNMS/OS/Routeros.php (11 wireless discovery methods)
|
|
Matches exact OIDs, descriptions, divisors, and skip logic from LibreNMS.
|
|
|
|
- Priority: TIER 4 LARGE (12-16 hour effort, vendor module enhancement)
|
|
- Gap Status: MikroTik wireless coverage 0% → 100% (11 sensor types)
|
|
- Result: TIER 4 COMPLETE - MikroTik wireless monitoring at 100% LibreNMS parity
|
|
|
|
2026-02-12 - feat: add UniFi channel-to-frequency dynamic conversion for accurate frequency monitoring
|
|
- Files: lib/towerops/snmp/profiles/vendors/unifi.ex (enhanced)
|
|
Added TIER 3 MEDIUM priority dynamic frequency sensor discovery for Ubiquiti UniFi APs.
|
|
Implements channel-to-frequency conversion matching LibreNMS behavior exactly.
|
|
- Channel OID: .1.3.6.1.4.1.41112.1.6.1.2.1.4 (unifiVapChannel)
|
|
- Radio Name OID: .1.3.6.1.4.1.41112.1.6.1.2.1.1 (unifiVapRadio)
|
|
- Conversion: 2.4GHz channels 1-14 → 2412-2484 MHz
|
|
- Conversion: 5GHz channels 34-165 → 5170-5825 MHz
|
|
- Unknown channels (not in lookup table) are filtered out
|
|
- Implementation:
|
|
- discover_frequency_sensors/1: Walks channel OID, converts to frequency dynamically
|
|
- channel_to_frequency/1: Lookup table with 29 Wi-Fi channel mappings
|
|
- Frequency sensors added alongside static sensors (clients, CCQ, power, utilization)
|
|
- Per-radio frequency sensors with descriptive names (e.g., "Frequency (ng)")
|
|
- Files: test/towerops/snmp/profiles/vendors/unifi_test.exs (enhanced)
|
|
Added comprehensive test coverage for frequency conversion:
|
|
- Tests 2.4GHz channel conversion (channels 1, 6, 11)
|
|
- Tests 5GHz channel conversion (channels 36, 149, 165)
|
|
- Tests unknown channel filtering (channel 999 → filtered out)
|
|
- Tests integration with static sensors (12 total sensors: 10 static + 2 frequency)
|
|
- Tests graceful handling of channel walk failures
|
|
All 16 tests passing with Mox-based SNMP adapter mocking.
|
|
- Impact: Dynamic frequency monitoring enables accurate channel tracking when APs
|
|
change channels (auto-DFS, manual changes). Static OID approach was inaccurate.
|
|
- Source: LibreNMS LibreNMS/OS/Unifi.php discoverWirelessFrequency/pollWirelessFrequency
|
|
LibreNMS LibreNMS/Modules/Wireless.php channelToFrequency lookup table
|
|
- Priority: TIER 3 MEDIUM (3-5 hour effort, vendor module enhancement)
|
|
- Gap Status: UniFi parity 80% → 90%
|
|
- Result: TIER 3 COMPLETE - All Ubiquiti platform gaps resolved
|
|
|
|
2026-02-12 - feat: add AirFiber AF-LTU optical power sensors (per-chain RX power, TX EIRP)
|
|
- Files: priv/profiles/os_discovery/airos-af-ltu.yaml (enhanced)
|
|
Added TIER 3 MEDIUM priority optical power sensors for Ubiquiti AirFiber AF-LTU:
|
|
- RX Power Chain 0: Received optical power chain 0 in dBm
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.5
|
|
- RX Power Chain 1: Received optical power chain 1 in dBm
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.6
|
|
- RX Ideal Power Chain 0: Ideal received power chain 0 in dBm
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.7
|
|
- RX Ideal Power Chain 1: Ideal received power chain 1 in dBm
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.8
|
|
- TX EIRP: Transmit effective isotropic radiated power in dBm
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.2.6
|
|
- Impact: Per-chain optical power monitoring enables detection of imbalanced
|
|
signal levels, fiber issues, and link budget problems. Ideal power comparison
|
|
helps identify suboptimal alignment or hardware degradation.
|
|
- Source: LibreNMS LibreNMS/OS/AirosAfLtu.php
|
|
- Priority: TIER 3 MEDIUM (enhanced troubleshooting and diagnostics)
|
|
- Gap Status: AF-LTU parity 80% → 90%
|
|
- Remaining: UniFi channel-to-frequency conversion (requires vendor module work)
|
|
|
|
2026-02-12 - feat: add AirFiber wireless metrics (frequency, distance, capacity, RSSI, SNR)
|
|
- Files: priv/profiles/os_discovery/airos-af60.yaml (enhanced)
|
|
Added TIER 2 HIGH priority wireless metrics for Ubiquiti AirFiber AF60:
|
|
- Frequency: Operating frequency in MHz
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.1.2
|
|
- Distance: Link distance in km (divisor 1000)
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.15
|
|
- TX Capacity: Transmit capacity in Mbps (divisor 1000)
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.7
|
|
- RX Capacity: Receive capacity in Mbps (divisor 1000)
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.8
|
|
- Local RSSI: Local received signal strength in dBm
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.3
|
|
- Remote RSSI: Remote received signal strength in dBm
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.18
|
|
- Local SNR: Local signal-to-noise ratio in dB
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.4
|
|
- Remote SNR: Remote signal-to-noise ratio in dB
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.19
|
|
- Files: priv/profiles/os_discovery/airos-af-ltu.yaml (enhanced)
|
|
Added TIER 2 HIGH priority wireless metrics for Ubiquiti AirFiber AF-LTU:
|
|
- Frequency: Operating frequency in MHz
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.2.2
|
|
- Distance: Link distance in km (divisor 1000)
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.23
|
|
- TX Capacity: Transmit capacity in Mbps (divisor 1000)
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.3
|
|
- RX Capacity: Receive capacity in Mbps (divisor 1000)
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.4
|
|
- Impact: Essential wireless metrics for capacity planning and troubleshooting.
|
|
Distance enables link budget analysis. RSSI/SNR enable interference detection.
|
|
Capacity metrics enable throughput monitoring and bandwidth planning.
|
|
- Source: LibreNMS LibreNMS/OS/AirosAf60.php, LibreNMS/OS/AirosAfLtu.php
|
|
- Priority: TIER 2 HIGH (enhanced monitoring for capacity planning)
|
|
- Gap Status: AF60 parity 50% → 80%, AF-LTU parity 60% → 80%
|
|
- Next: TIER 3 - UniFi channel-to-frequency conversion, AF-LTU optical power
|
|
|
|
2026-02-12 - feat: add critical AirFiber MCS/modulation rate state sensors
|
|
- Files: priv/profiles/os_discovery/airos-af60.yaml (enhanced)
|
|
Added CRITICAL link quality state sensors for Ubiquiti AirFiber AF60:
|
|
- TX MCS Rate: 9 states (1X-9X) showing transmit modulation level
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.5 (states: 1-2 warning, 3-4 degraded, 5-9 ok)
|
|
- RX MCS Rate: 9 states (1X-9X) showing receive modulation level
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.6 (states: 1-2 warning, 3-4 degraded, 5-9 ok)
|
|
- Active Link: 2 states (Main/Backup) showing active link selection
|
|
OID: .1.3.6.1.4.1.41112.1.11.1.3.1.2 (states: 1=Main ok, 2=Backup degraded)
|
|
- Files: priv/profiles/os_discovery/airos-af-ltu.yaml (enhanced)
|
|
Added CRITICAL link quality state sensors for Ubiquiti AirFiber AF-LTU:
|
|
- TX Modulation Rate: 7 QAM states (1X QPSK+SFBC through 12X 4096QAM)
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.1 (states: 1-2 warning, 4-6 degraded, 8-12 ok)
|
|
- RX Modulation Rate: 7 QAM states (1X QPSK+SFBC through 12X 4096QAM)
|
|
OID: .1.3.6.1.4.1.41112.1.10.1.4.1.2 (states: 1-2 warning, 4-6 degraded, 8-12 ok)
|
|
- Impact: MCS/modulation rate is THE key indicator of point-to-point link health.
|
|
Without these sensors, operators cannot diagnose why throughput changed or when
|
|
links drop from high QAM to low QAM due to interference or alignment issues.
|
|
- Pattern: State sensors with discrete value mappings match LibreNMS exactly.
|
|
Uses generic values for alerting: 0=ok, 1=degraded/warning, 2=critical.
|
|
- Source: LibreNMS includes/discovery/sensors/state/airos-af*.inc.php
|
|
- Priority: TIER 1 CRITICAL (production monitoring gaps for PtP wireless)
|
|
- Gap Status: AF60 parity 35% → 50%, AF-LTU parity 40% → 60%
|
|
- Next: TIER 2 - Add RSSI, SNR, frequency, distance, capacity sensors
|
|
|
|
2026-02-12 - feat: add Dell PowerVault storage array text-based sensor parsing
|
|
- Files: lib/towerops/snmp/profiles/vendors/powervault.ex (created)
|
|
Created vendor post-processing module for Dell PowerVault storage arrays.
|
|
PowerVault devices report sensors as text messages in FCMGMT-MIB::connUnitSensorMessage
|
|
instead of structured SNMP tables, requiring regex-based parsing.
|
|
- Message format: "Sensor Name: Value Unit" (e.g., "Enclosure Temp: 25 C 77.0F")
|
|
- Temperature: Parses Celsius from "N C M.MF" format (e.g., "25 C 77.0F" → 25°C)
|
|
- Voltage: Parses "N.NV" format (e.g., "12.1V" → 12.1V)
|
|
- Current: Parses "N.NA" format (e.g., "0.5A" → 0.5A)
|
|
- Charge: Parses "N%" format (e.g., "95%" → 95% with battery thresholds)
|
|
Sensor index format: powervault_{type}.{oid_index} for unique identification.
|
|
- Files: lib/towerops/snmp/profiles/dynamic.ex (enhanced)
|
|
Integrated PowerVault vendor module into post-processing pipeline.
|
|
Added "dell-powervault" case to apply_vendor_post_processing/3 function.
|
|
- Files: test/towerops/snmp/profiles/vendors/powervault_test.exs (created)
|
|
Comprehensive test suite with 21 tests covering:
|
|
- All sensor types (temperature, voltage, current, charge/percent)
|
|
- Multi-sensor parsing (mixed message types in single walk)
|
|
- Error handling (invalid formats, non-string values, missing colons)
|
|
- Edge cases (empty results, SNMP timeouts, existing sensor preservation)
|
|
All tests passing with Mox-based SNMP adapter mocking.
|
|
- Pattern: Follows Arista vendor module architecture with post_process_sensors/2
|
|
callback. Client.walk returns map format, converted to list for message parsing.
|
|
- Result: Dell PowerVault storage arrays now support temperature/voltage/current/
|
|
battery monitoring via text message parsing. Gap: CRITICAL → RESOLVED.
|
|
Parity: 0% → 85% (limited by FCMGMT-MIB available sensors).
|
|
|
|
2026-02-11 - feat: add Dell UPS power sensor and HP BladeSystem/Moonshot complete monitoring
|
|
- Files: priv/profiles/os_discovery/dell-ups.yaml (enhanced)
|
|
Added Dell UPS power consumption sensor via DELL-SNMP-UPS-MIB:
|
|
- Power: physicalOutputPresentConsumption (OID .1.3.6.1.4.1.674.10902.2.120.2.6.0)
|
|
Enables capacity planning and load tracking for Dell UPS units.
|
|
Gap: MEDIUM (missing power sensor) → RESOLVED. Parity: 80% → 100%.
|
|
- Files: priv/profiles/os_discovery/hpblmos.yaml (enhanced)
|
|
Created comprehensive HP BladeSystem/Moonshot sensor profile:
|
|
- Temperature: Blade chassis component temperatures (OID .1.3.6.1.4.1.232.22.2.3.1.2.1.6)
|
|
- Power: PSU output wattage with max limit (OID .1.3.6.1.4.1.232.22.2.5.1.1.1.10)
|
|
- State: Fan operational status (OID .1.3.6.1.4.1.232.22.2.3.1.3.1.11)
|
|
- State: PSU condition status (OID .1.3.6.1.4.1.232.22.2.5.1.1.1.17)
|
|
Skip logic: Only monitors present fans/PSUs (presence check to avoid non-existent sensors)
|
|
Gap: CRITICAL (no sensor profile) → RESOLVED. Parity: 0% → 80%.
|
|
- Analysis Discovery: Dell Enterprise Servers (iDRAC) already have excellent coverage
|
|
The existing drac.yaml profile includes comprehensive sensor monitoring:
|
|
- Temperature: Multiple probes with thresholds (4 types)
|
|
- Voltage: PSU voltage monitoring (2 types)
|
|
- Current: Amperage probes (3 types, filtered for wattage type)
|
|
- Power: Chassis power (current, peak, potential, idle, max - 5 types)
|
|
- Fanspeed: Cooling device monitoring with thresholds
|
|
- State: Extensive state sensors (global system, IDSDM card, intrusion, IOM, etc.)
|
|
Previous gap analysis incorrectly reported 0% parity - actual parity is 95%+.
|
|
- Result: Tier 4 complete. Dell UPS now has full monitoring capability, HP BladeSystem
|
|
blade chassis fully supported with temperature/power/fan/PSU monitoring. Dell servers
|
|
confirmed to have excellent existing coverage via iDRAC/OpenManage MIBs.
|
|
|
|
2026-02-11 - feat: add Force10 FTOS and optical transceiver monitoring (ProCurve, Comware)
|
|
- Files: priv/profiles/os_discovery/ftos.yaml (enhanced)
|
|
Added Dell Force10 FTOS temperature monitoring for all 3 series:
|
|
- S-Series: chStackUnitTemp (OID .1.3.6.1.4.1.6027.3.10.1.2.2.1.14)
|
|
- C-Series: chSysCardTemp (OID .1.3.6.1.4.1.6027.3.8.1.2.1.1.5)
|
|
- E-Series: chSysCardUpperTemp + chSysCardLowerTemp (OIDs .1.3.6.1.4.1.6027.3.1.1.2.3.1.8-9)
|
|
Completes Tier 1 critical network switch monitoring. Parity: 0% → 90%.
|
|
- Files: priv/profiles/os_discovery/procurve.yaml (enhanced)
|
|
Added HP ProCurve transceiver optical monitoring via HP-ICF-TRANSCEIVER-MIB::hpicfXcvrInfoTable:
|
|
- Temperature: hpicfXcvrTemp (OID .1.3.6.1.4.1.11.2.14.11.5.1.82.1.1.1.1.11)
|
|
- Bias Current: hpicfXcvrBias (OID .1.3.6.1.4.1.11.2.14.11.5.1.82.1.1.1.1.13)
|
|
- Supply Voltage: hpicfXcvrVoltage (OID .1.3.6.1.4.1.11.2.14.11.5.1.82.1.1.1.1.12)
|
|
- RX Power (dBm): hpicfXcvrRxPower (OID .1.3.6.1.4.1.11.2.14.11.5.1.82.1.1.1.1.14)
|
|
- TX Power (dBm): hpicfXcvrTxPower (OID .1.3.6.1.4.1.11.2.14.11.5.1.82.1.1.1.1.15)
|
|
Enables optical SFP/SFP+ monitoring for fiber uplinks. Parity: 60% → 100%.
|
|
- Files: priv/profiles/os_discovery/comware.yaml (enhanced)
|
|
Added HP Comware transceiver optical monitoring via HH3C-TRANSCEIVER-INFO-MIB::hh3cTransceiverInfoTable:
|
|
- Temperature: hh3cTransceiverTemperature (OID .1.3.6.1.4.1.25506.2.70.1.1.1.15)
|
|
- Bias Current: hh3cTransceiverBiasCurrent (OID .1.3.6.1.4.1.25506.2.70.1.1.1.17)
|
|
- Supply Voltage: hh3cTransceiverVoltage (OID .1.3.6.1.4.1.25506.2.70.1.1.1.16)
|
|
- RX Power (dBm): hh3cTransceiverCurRXPower (OID .1.3.6.1.4.1.25506.2.70.1.1.1.9)
|
|
- TX Power (dBm): hh3cTransceiverCurTXPower (OID .1.3.6.1.4.1.25506.2.70.1.1.1.12)
|
|
Completes Comware sensor coverage. Parity: 60% → 95%.
|
|
- Result: Tier 1 + Tier 2 complete. All critical network switches have temperature monitoring,
|
|
and both ProCurve/Comware have complete optical transceiver diagnostics (temp, current, voltage,
|
|
RX/TX power). Force10 FTOS data center switches fully supported. Fiber link monitoring enabled.
|
|
|
|
2026-02-11 - feat: add critical network switch sensor support (HP Comware, Dell PowerConnect, Dell SONiC)
|
|
- Files: priv/profiles/os_discovery/comware.yaml (enhanced)
|
|
Added HP Comware chassis temperature monitoring via HH3C-ENTITY-EXT-MIB::hh3cEntityExtTemperature
|
|
(OID 1.3.6.1.4.1.25506.2.6.1.1.1.1.12). This restores fundamental temperature monitoring capability
|
|
for HP Comware switches, enabling overheating alerts. Gap identified as CRITICAL in Phase 3 analysis.
|
|
- Files: priv/profiles/os_discovery/powerconnect.yaml (enhanced)
|
|
Added Dell PowerConnect/DNOS CPU temperature monitoring via FASTPATH-BOXSERVICES-PRIVATE-MIB
|
|
(OID 1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.8.1.5). Enables temperature monitoring for
|
|
common enterprise access switches.
|
|
- Files: priv/profiles/os_discovery/dell-sonic.yaml (new)
|
|
Created comprehensive sensor profile for Dell SONiC switches using NETGEAR-BOXSERVICES-PRIVATE-MIB
|
|
(Quanta-based platform). Sensors: temperature (boxServicesTempSensorState), fan speed
|
|
(boxServicesFanSpeed), PSU state (boxServicesPowSupplyItemState with 8 states). Enables hardware
|
|
monitoring for modern data center switches.
|
|
- Result: Top 3 critical network switch monitoring gaps resolved. HP Comware gains fundamental
|
|
temperature capability (40% → 60% parity), Dell PowerConnect gains first sensor support
|
|
(0% → 80% parity), Dell SONiC gains complete hardware monitoring (0% → 95% parity).
|
|
|
|
2026-02-11 - audit: Phase 3 - HP/Aruba and Dell sensor analysis complete
|
|
- Files: docs/librenms-audit/sensors/hp-aruba-comparison.md (new)
|
|
Analyzed 6 HP/Aruba platforms: ProCurve (60%), Comware (40%), hpblmos (0%), ArubaOS (100%),
|
|
ArubaOS-CX (100%), Instant On (100%). Identified critical gaps in Comware temperature and
|
|
transceiver support.
|
|
- Files: docs/librenms-audit/sensors/dell-comparison.md (new)
|
|
Analyzed 11 Dell platforms: OS10 (100%), rPDU (100%), UPS (80%), OME-M (100%), Compellent (100%),
|
|
PowerVault (20%), PowerConnect (0%), Force10 (0%), SONiC (0%), Quanta (40%), Servers (0%).
|
|
Found network switches severely underserved compared to storage/infrastructure.
|
|
- Files: docs/librenms-audit/PHASE3-VENDOR-EXPANSION.md (new)
|
|
Executive summary with implementation priorities. Tier 1 critical: Network switch sensor gaps
|
|
(8-12 hours). Tier 2 high: Optical transceiver monitoring (4-6 hours). Tier 3: Storage/compute
|
|
(7-10 hours). Total effort: 26-38 hours for full parity.
|
|
- Key Finding: Modern platforms excellent (Aruba CX, Dell OS10), but legacy network switches
|
|
missing fundamental monitoring. HP Comware temperature gap BLOCKING (breaks alerts).
|
|
Dell PowerConnect/FTOS/SONiC missing all sensors (CRITICAL for enterprise deployments).
|
|
|
|
2026-02-11 - feat: implement Arista EOS sensor enhancements (DOM power, thresholds, grouping)
|
|
- Files: lib/towerops/snmp/profiles/vendors/arista.ex (enhanced)
|
|
Implemented all critical and nice-to-have Arista sensor improvements identified in audit:
|
|
1. DOM power conversion (watts→dBm): Detects optical power sensors via regex, converts
|
|
using formula dBm = 10*log10(watts*1000), preserves original value in metadata
|
|
2. Arista threshold discovery: Walks ARISTA-ENTITY-SENSOR-MIB::aristaEntSensorThresholdTable,
|
|
applies 4 threshold types (low_critical, low_warn, high_warn, high_critical), converts
|
|
thresholds to dBm for optical sensors
|
|
3. Smart grouping: Organizes sensors by SFPs, PSUs, Platform (chipsets), Power Connectors, System
|
|
4. Description cleanup: Removes redundant "sensor" text, simplifies PSU naming, cleans whitespace
|
|
- Files: lib/towerops/snmp/profiles/dynamic.ex (integration)
|
|
Added apply_vendor_post_processing/3 to call Arista enhancements after sensor discovery.
|
|
Applies to both arista_eos and arista-mos profiles.
|
|
- Files: test/towerops/snmp/profiles/vendors/arista_test.exs (comprehensive tests)
|
|
Added 23 new tests covering DOM conversion (6 tests), threshold discovery (4 tests),
|
|
smart grouping (6 tests), description cleanup (5 tests), and end-to-end post-processing (1 test).
|
|
All tests passing (30/30 in arista_test.exs, 6367/6367 total).
|
|
- Result: Arista EOS support upgraded from 85% to 100% LibreNMS parity. All critical gaps closed:
|
|
optical power now displayed correctly in dBm, alerting enabled via thresholds, sensors
|
|
organized for better UX, descriptions cleaned up.
|
|
|
|
2026-02-11 - audit: Phase 2 - complete top vendor sensor analysis (Cisco, Juniper, Arista)
|
|
- Files: docs/librenms-audit/sensors/*.md, PHASE2-VENDOR-ANALYSIS.md (new)
|
|
Completed comprehensive sensor discovery analysis for top 3 enterprise vendors:
|
|
- cisco-ios-comparison.md: Cisco IOS/XE/XR/NX-OS analysis (95% parity, production ready)
|
|
- juniper-junos-comparison.md: JunOS analysis (100% IDENTICAL - perfect parity)
|
|
- arista-eos-comparison.md: Arista EOS analysis (85% parity, gaps identified)
|
|
- PHASE2-VENDOR-ANALYSIS.md: Comprehensive summary and recommendations
|
|
- Key findings:
|
|
- Cisco: All critical sensors covered, YAML-based discovery, minor cellular gaps (rare devices)
|
|
- Juniper: junos.yaml byte-for-byte identical (30+ sensor types, 38+ OIDs, 10 MIBs)
|
|
- Arista: Missing DOM power conversion (watts→dBm) and ARISTA-ENTITY-SENSOR-MIB thresholds
|
|
- Identified actionable fixes for Arista (2 critical, 2 minor):
|
|
1. DOM Rx/Tx power conversion (2-3 hours, enables proper optical monitoring)
|
|
2. Arista threshold discovery (4-6 hours, enables alerting)
|
|
3. Smart grouping (2-3 hours, UX improvement)
|
|
4. Description cleanup (1-2 hours, cosmetic)
|
|
- Towerops advantages: CPU/Memory/Uptime sensors (Arista), PSU/Fan state (Arista),
|
|
cleaner YAML architecture, index templates, pre-resolved MIB cache
|
|
|
|
2026-02-11 - audit: complete LibreNMS parity audit and add missing OS detection profiles
|
|
- Files: docs/librenms-audit/*.md (new)
|
|
Completed comprehensive audit comparing Towerops device detection and sensor discovery
|
|
against LibreNMS. Created detailed documentation:
|
|
- detection-algorithm.md: LibreNMS 2-pass detection system analysis
|
|
- towerops-detection.md: Towerops 4-phase detection system analysis
|
|
- vendor-detection-comparison.csv: Priority vendor comparison (MikroTik, Ubiquiti)
|
|
- librenms-sensors.md: LibreNMS sensor discovery architecture (360+ modules, 24 types)
|
|
- EXECUTIVE-SUMMARY.md: Overall findings (99.5% detection parity, 95%+ sensor parity)
|
|
- IMPLEMENTATION-STATUS.md: Phase 1 completion status
|
|
- Files: priv/profiles/os_detection/conteg-pdu.yaml, microsens-g6.yaml (new)
|
|
Added 2 missing OS detection profiles from LibreNMS to achieve 100% profile parity
|
|
(786 profiles total). Conteg PDU for power monitoring devices, MICROSENS G6 for
|
|
network switches.
|
|
- Key findings: Towerops has full detection parity with LibreNMS plus architectural
|
|
enhancements (4-phase matching, Rust NIF MIB resolution, ETS caching, index templates).
|
|
MikroTik coverage verified: all 22 sensor tables discovered identically. Ubiquiti
|
|
coverage: 8 of 9 profiles identical (airos-af has additional fallback in Towerops).
|
|
|
|
2026-02-11 - test: add 100% coverage for ExpiredBanCleanupWorker
|
|
- File: test/towerops/workers/expired_ban_cleanup_worker_test.exs (new)
|
|
Added 7 tests covering perform/1: expired ban deletion, active ban preservation,
|
|
permanent ban preservation, mixed scenarios, empty database, PubSub broadcast
|
|
on deletion, and no broadcast when nothing deleted.
|
|
|
|
2026-02-11 - fix: handle "null" string values in SNMP parsing
|
|
- File: lib/towerops/snmp/profiles/base.ex (parse_integer/1, parse_float/1)
|
|
Added explicit handling for "null" string values before attempting integer/float
|
|
conversion. Some devices (e.g., AirOS 8.7.14) return the literal string "null"
|
|
for unavailable metrics like UCD CPU stats, which caused ArgumentError when
|
|
parse_integer/parse_float tried to convert them. Now returns nil, which gets
|
|
coerced to 0 by the || 0 fallback in the calling code.
|
|
|
|
2026-02-11 - fix: deduplicate sensors with leading-dot OID differences
|
|
- File: lib/towerops/snmp/profiles/dynamic.ex (deduplicate_by_oid/1)
|
|
Normalized OIDs by stripping leading dots when grouping for deduplication.
|
|
gosnmp (agent) returns OIDs with leading dots (.1.3.6.1...) but vendor
|
|
modules and YAML profiles define them without. Without normalization,
|
|
the same sensor appeared twice (e.g. "DHCP Leases" and "DHCP Lease Count").
|
|
- File: lib/towerops/snmp/discovery.ex (deduplicate_sensors_by_oid/1)
|
|
Same leading-dot normalization applied to the discovery-level deduplication.
|
|
- File: lib/towerops/snmp/profiles/vendors/routeros.ex (wireless_oid_defs/0)
|
|
Removed DHCP Leases entry (mtxrDHCPLeaseCount) since the routeros.yaml
|
|
YAML profile already defines it in count_sensor_oids. Eliminates the
|
|
source of duplication for MikroTik devices.
|
|
- Tests updated in dynamic_test.exs and routeros_test.exs
|
|
|
|
2026-02-11 - fix: agent discovery and polling improvements
|
|
- File: lib/towerops_web/channels/agent_channel.ex (build_polling_queries/1, process_interface_stats/3)
|
|
Changed interface traffic OIDs from 32-bit counters (ifInOctets/ifOutOctets) to 64-bit
|
|
HC counters (ifHCInOctets/ifHCOutOctets). 32-bit counters wrap at ~4.3GB which causes
|
|
wildly inaccurate readings on gigabit+ links.
|
|
- File: lib/towerops/snmp/adapters/replay.ex (parse_value/1)
|
|
Fixed negative integer parsing regex from ^\d+$ to ^-?\d+$ so values like
|
|
entPhySensorScale=-3 are parsed as integers. Previously fell through to string,
|
|
causing sensor divisor calculation to silently return 1 instead of 1000.
|
|
- File: lib/towerops_web/channels/agent_channel.ex (build_discovery_queries/0)
|
|
Replaced walking entire Cisco enterprise tree (1.3.6.1.4.1.9) with targeted subtrees
|
|
for CPU, ENVMON, CDP, and WAP to avoid 50k+ OID responses and timeouts. Added Juniper,
|
|
HP/H3C, Fortinet, and Cambium vendor OIDs for broader device support.
|
|
- File: lib/towerops_web/channels/agent_channel.ex (build_discovery_queries/0)
|
|
Added missing discovery OIDs: ENTITY-STATE-MIB for state sensors, HOST-RESOURCES-MIB
|
|
tables for processors/storage/devices, and UCD-SNMP-MIB for Linux CPU stats fallback.
|
|
- Tests added in replay_test.exs and agent_channel_test.exs
|
|
|
|
2026-02-11 - fix: handle RouterOS version returned as list of integers
|
|
- File: lib/towerops/snmp/profiles/vendors/routeros.ex (detect_version/1)
|
|
Added pattern match to handle case where SNMP version OID returns list
|
|
of integers [7, 20, 6] instead of binary string "7.20.6". Converts list
|
|
to dotted string format using Enum.join/2.
|
|
- File: test/towerops/snmp/profiles/vendors/routeros_test.exs
|
|
Added two test cases for list-formatted versions with and without license level.
|
|
- Bug: Warning logged "Failed to detect version: {:ok, [7, 20, 6]}" even though
|
|
version was successfully retrieved, just in wrong format.
|
|
|
|
2026-02-11 - fix: normalize OIDs so agent-polled sensors match regardless of leading dot
|
|
- File: lib/towerops_web/channels/agent_channel.ex
|
|
Agent (gosnmp) returns OIDs with leading dots (e.g. ".1.3.6.1.4.1.41112...")
|
|
but sensor OIDs stored in DB may omit the dot. process_sensor_reading used
|
|
direct Map.get which silently missed wireless/vendor sensors on Ubiquiti airOS.
|
|
- Fix: Added normalize_oid_keys/1 to strip leading dots from all oid_values keys,
|
|
and normalize sensor.sensor_oid too. Both sides now match without leading dot.
|
|
- File: test/towerops/snmp/sensor_change_detector_test.exs
|
|
Fixed flaky refute_receive tests that subscribed to global "device:events" topic
|
|
and caught unrelated device_discovered events from concurrent async tests.
|
|
Changed to device-specific topic "device:#{device.id}" instead.
|
|
|
|
2026-02-11 - feat: add sensor value change events for all sensor types
|
|
- New file: lib/towerops/snmp/sensor_change_detector.ex
|
|
Extracted shared sensor change detection logic from DevicePollerWorker.
|
|
Detects threshold violations, spike/drop for % sensors, and new
|
|
sensor_value_changed events for all non-% sensors when value changes.
|
|
- File: lib/towerops/devices/event.ex
|
|
Added "sensor_value_changed" to allowed event types.
|
|
- File: lib/towerops/workers/device_poller_worker.ex
|
|
Replaced inline detect_sensor_changes with SensorChangeDetector module.
|
|
Removed ~240 lines of private functions now in shared module.
|
|
- File: lib/towerops_web/channels/agent_channel.ex
|
|
Added change detection and last_value/last_checked_at update to
|
|
process_sensor_reading/3 so agent-polled devices get same events
|
|
as Phoenix-polled devices.
|
|
- New file: test/towerops/snmp/sensor_change_detector_test.exs
|
|
11 tests covering value changes, spike/drop, thresholds, nil handling.
|
|
|
|
2026-02-11 - fix: live polling uses effective agent from site/org cascade
|
|
- File: lib/towerops_web/live/graph_live/show.ex
|
|
- Bug: Live poll mode used Agents.get_device_assignment/1 which only checks
|
|
direct device-level assignments. Devices with agent assigned at site or
|
|
org level fell through to direct Phoenix SNMP instead of routing to agent.
|
|
- Fix: Replaced with Agents.get_effective_agent_token/1 which walks the
|
|
device → site → org cascade, matching how regular polling resolves agents.
|
|
Also simplified request_agent_live_poll_and_wait to accept token_id directly.
|
|
|
|
2026-02-11 - fix: round sensor values to 1 decimal place
|
|
- Files: lib/towerops/workers/device_poller_worker.ex (poll_simple_sensor/2),
|
|
lib/towerops_web/channels/agent_channel.ex (process_sensor_reading/3)
|
|
- Bug: Division by sensor_divisor produced full float precision (e.g. 34.09999999)
|
|
- Fix: Wrap division result with Float.round(..., 1) in both Phoenix and agent paths
|
|
|
|
2026-02-11 - fix: update device status from agent monitoring checks
|
|
- File: lib/towerops_web/channels/agent_channel.ex (store_monitoring_check/2)
|
|
- Bug: Devices polled by remote agents stayed in "unknown" state because
|
|
store_monitoring_check saved the ping result but never called
|
|
Devices.update_device_status/2. The DeviceMonitorWorker (Phoenix-side)
|
|
skips agent-assigned devices entirely, so nothing ever updated status.
|
|
- Fix: Added update_device_status_from_check/2 and handle_agent_status_change/3
|
|
to derive :up/:down from check status, update device, create alerts on
|
|
transitions, and broadcast via PubSub — matching DeviceMonitorWorker behavior
|
|
- Also added alias Towerops.Alerts to the channel module
|
|
|
|
2026-02-11 - fix: update last_snmp_poll_at for agent-polled devices
|
|
- File: lib/towerops_web/channels/agent_channel.ex (process_polling_result/3)
|
|
- Bug: Devices polled by remote agents showed "Last Polled: Never" because
|
|
process_polling_result never called Devices.update_snmp_poll_time/1
|
|
- The Phoenix-side DevicePollerWorker already had this call (line 172),
|
|
but the agent channel path was missing it
|
|
- Fix: Added Devices.update_snmp_poll_time(device) at the top of
|
|
process_polling_result/3, matching the DevicePollerWorker pattern
|