* feat: add Site Magic site-to-site VPN metrics (closes#926)
Bump github.com/unpoller/unifi/v5 to v5.25.0 which adds:
- GetMagicSiteToSiteVPN / GetMagicSiteToSiteVPNSite API methods
- MagicSiteToSiteVPN types with mesh, connection, device, and status structs
- Missing VPN health fields on Site.Health (SiteToSiteNumActive/Inactive,
SiteToSiteRxBytes/TxBytes/RxPackets/TxPackets)
Implement VPN metrics collection across all output plugins:
- Collect Site Magic VPN mesh data per-site in inputunifi pollController
- Propagate VPNMeshes through poller.Metrics / AppendMetrics
- Apply DefaultSiteNameOverride for VPN meshes in augmentMetrics /
applySiteNameOverride
- influxunifi: vpn_mesh, vpn_mesh_connection, vpn_mesh_status tables
- promunifi: vpn_mesh_*, vpn_tunnel_*, vpn_mesh_status_* gauges
- datadogunifi: unifi.vpn_mesh.*, unifi.vpn_tunnel.*, unifi.vpn_mesh_status.*
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* feat(otelunifi): add Site Magic VPN metrics to OpenTelemetry output
Adds exportVPNMeshes to the otel output plugin, emitting the same
unifi_vpn_mesh_*, unifi_vpn_tunnel_*, and unifi_vpn_mesh_status_*
gauges as the other output plugins.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Collect port anomalies from the UniFi v2 API endpoint
/proxy/network/v2/api/site/{site}/ports/port-anomalies and export
them to all output plugins (Prometheus, InfluxDB, DataDog, OpenTelemetry).
Metrics exported per port:
- port_anomaly_count – number of anomaly events
- port_anomaly_last_seen – unix timestamp of last event
Labels: site_name, source, device_mac, port_idx, anomaly_type
Bumps github.com/unpoller/unifi/v5 to v5.24.0 which adds GetPortAnomalies.
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Bumps github.com/unpoller/unifi/v5 to v5.23.0 which adds
GetTopology() fetching vertices (devices/clients) and edges
(wired/wireless connections) from /proxy/network/v2/api/site/{site}/topology.
Changes across the stack:
- poller.Metrics: add Topologies []any field + AppendMetrics support
- inputunifi: collect topology per-site (non-fatal on older controllers),
pass through augmentMetrics with site name override support
- promunifi: new topology.go with summary, connection-type, link-quality,
and band-distribution gauges
- influxunifi: new topology.go with topology_summary and topology_edge
measurements
- datadogunifi: new topology.go with equivalent Datadog gauges
- otelunifi: new topology.go with OpenTelemetry gauge observations
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
save_rogue = true collected data from the controller but never wrote
any of it to the output backends. All three exporters (InfluxDB, Datadog,
Prometheus) had the same guard:
if s.Age.Val == 0 { return }
The intent was to drop stale entries, but the logic is inverted: Age==0
means brand-new or (more commonly) that the UniFi controller did not
include an "age" field in the JSON response, causing FlexInt to default
to 0. This silently discarded every rogue AP record.
Remove the guard entirely. The data was just fetched on-demand from the
controller; if the user opted in to save_rogue, they want all of it.
Fixes#405
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Adds metrics export for UDB devices (UDB-Switch, UDB-Pro, UDB-Pro-Sector)
to all output backends. UDB-Switch is a hybrid device combining PoE switch
ports with WiFi 7 wireless bridge capability (5GHz + 6GHz radios).
- pkg/promunifi/udb.go: Prometheus metrics exporter for UDB
- pkg/influxunifi/udb.go: InfluxDB batch exporter for UDB
- pkg/datadogunifi/udb.go: Datadog batch exporter for UDB
- Wire UDB into switchExport in all three output plugins
- Add UDB to inputunifi device collection and site name override
- Update integration test expectations for InfluxDB and Datadog
- Fix addUBB() bug: was incorrectly incrementing UCI counter
Resolves#947
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add comprehensive WAN metrics support to InfluxDB and Datadog exporters:
InfluxDB Metrics (measurement: wan):
- Configuration: failover_priority, load_balance_weight, provider_download_kbps,
provider_upload_kbps, smartq_enabled, magic_enabled, vlan_enabled
- Statistics: uptime_percentage, peak_download_percent, peak_upload_percent,
max_rx_bytes_rate, max_tx_bytes_rate
- Service Provider: service_provider_asn
- Metadata: creation_timestamp
Tags: wan_id, wan_name, wan_networkgroup, wan_type, wan_load_balance_type,
isp_name, isp_city
Datadog Metrics (namespace: unpoller.wan.*):
- Same metrics as InfluxDB with gauge type
- All metrics tagged with WAN and ISP information
Changes:
- pkg/influxunifi/wan.go: New WAN exporter for InfluxDB
- pkg/influxunifi/influxdb.go: Add WAN to loopPoints and switchExport
- pkg/datadogunifi/wan.go: New WAN exporter for Datadog
- pkg/datadogunifi/datadog.go: Add WAN to loopPoints and switchExport
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add 'tag' label to all device metric descriptors
- Update exportWithTags helper to create separate metric series per tag
- Update all device export functions (UAP, USW, UDM, USG, UXG, PDU, UBB, UCI) to include tags
- Update all label arrays (VAP, Radio, Port, etc.) to include tag label
- Devices with multiple tags create multiple metric series (one per tag)
- Devices without tags export with tag=""
Requires unpoller/unifi#92
Fixes#417
UniFi controllers populate RemoteUserNumActive for VPN connections but
leave NumUser at 0 for the VPN subsystem. This caused dashboard queries
looking for num_user in the VPN subsystem to always show 0 active users,
even when VPN connections were active.
Root Cause:
For most subsystems (wlan, lan, www), the controller populates NumUser
directly. However, for the VPN subsystem, the controller uses the
RemoteUserNumActive field instead, leaving NumUser at 0.
The Prometheus exporter had special handling for VPN (lines 148-156 in
pkg/promunifi/site.go) and exported RemoteUserNumActive, but did not
export NumUser. The InfluxDB and Datadog exporters exported all fields
for all subsystems without special handling, resulting in num_user
always being 0 for VPN.
Existing Grafana dashboards query:
SELECT "num_user" FROM "subsystems" WHERE subsystem='vpn'
This always returned 0 even with active VPN users.
Solution:
For all three exporters (InfluxDB, Datadog, Prometheus), when the
subsystem is 'vpn' and NumUser is 0 but RemoteUserNumActive has a
value, populate num_user with RemoteUserNumActive.
Changes:
- pkg/influxunifi/site.go: Add VPN-specific num_user fallback logic
- pkg/datadogunifi/site.go: Add VPN-specific num_user fallback logic
- pkg/promunifi/site.go: Add NumUser metric to VPN case with fallback
This maintains backward compatibility - existing queries for num_user
will now work correctly, and the remote_user_num_active field is still
available for those who updated their dashboards.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Ports providing PoE power are no longer considered "dead" even when
disabled or down. This allows users to collect PoE metrics from ports
that are disabled for security reasons but still providing power.
Fixes#910
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Speed tests were not being reported correctly for multi-WAN setups
because the device-level speedtest-status field was returning zeros.
The data has moved to a new aggregated dashboard API endpoint.
Changes:
- Add GetSpeedTests() and GetSiteSpeedTests() methods to fetch from
/v2/api/site/{site}/aggregated-dashboard endpoint
- Create SpeedTestResult data structures to capture per-WAN metrics
- Update Prometheus exporter with new speedtest_* metrics per interface
- Update InfluxDB exporter to write speedtest measurements per WAN
- Update Datadog exporter with unifi.speedtest.* metrics per WAN
- Update metrics collection to include speed test data for all sites
Metrics now include labels/tags for:
- wan_interface: Physical interface (eth8, eth9, etc.)
- wan_group: Logical WAN name (WAN, WAN2, etc.)
- site_name: Site identifier
- source: Controller URL
Gracefully handles older controllers without the new API endpoint.
Fixes#841🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This change significantly expands the metrics exported for UBB devices
to InfluxDB and Datadog, matching the comprehensive coverage added to
the Prometheus output.
Changes to InfluxDB (pkg/influxunifi/ubb.go):
- Added batchUBBstats() to export comprehensive statistics separated
by radio (total, wifi0, terra2, user-wifi0, user-terra2)
- Added VAP table export via processVAPTable()
- Added Radio table export via processRadTable()
- Added P2P stats (rx_rate, tx_rate, throughput)
- Added link quality metrics (link_quality, link_quality_current,
link_capacity)
- Comprehensive stats exported to new "ubb_stats" table with full
breakdown of traffic per radio
Changes to Datadog (pkg/datadogunifi/ubb.go):
- Added batchUBBstats() to export comprehensive statistics separated
by radio (total, wifi0, terra2, user-wifi0, user-terra2)
- Added VAP table export via processVAPTable()
- Added Radio table export via processRadTable()
- Added P2P stats (rx_rate, tx_rate, throughput)
- Added link quality metrics (link_quality, link_quality_current,
link_capacity)
- Comprehensive stats exported with namespace "ubb.stats"
All implementations now fully support:
- 5GHz radio (wifi0) metrics
- 60GHz radio (terra2/ad) metrics - Full 802.11ad support!
- Per-radio RX/TX packets, bytes, errors, dropped, retries
- User-specific metrics for each radio
- Interface-specific metrics (ath0 for 5GHz, wlan0 for 60GHz)
- Point-to-point link statistics and quality metrics
Fixes: #409🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>