Files
unpoller-unpoller-4/pkg/influxunifi/vpn.go
Cody Lee 18c6e66a8e feat: add Site Magic site-to-site VPN metrics (closes #926) (#983)
* 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>
2026-03-23 21:08:09 -05:00

76 lines
1.6 KiB
Go

package influxunifi
import (
"github.com/unpoller/unifi/v5"
)
// batchMagicSiteToSiteVPN generates Site Magic VPN datapoints for InfluxDB.
func (u *InfluxUnifi) batchMagicSiteToSiteVPN(r report, m *unifi.MagicSiteToSiteVPN) {
if m == nil {
return
}
meshTags := map[string]string{
"site_name": m.SiteName,
"source": m.SourceName,
"mesh_id": m.ID,
"mesh_name": m.Name,
}
paused := 0.0
if m.Pause.Val {
paused = 1.0
}
meshFields := map[string]any{
"paused": paused,
"connections_total": len(m.Connections),
"devices_total": len(m.Devices),
}
r.send(&metric{Table: "vpn_mesh", Tags: meshTags, Fields: meshFields})
for i := range m.Status {
s := &m.Status[i]
for j := range s.Connections {
conn := &s.Connections[j]
connected := 0.0
if conn.Connected.Val {
connected = 1.0
}
connTags := map[string]string{
"site_name": m.SiteName,
"source": m.SourceName,
"mesh_name": m.Name,
"connection_id": conn.ConnectionID,
"status_site": s.SiteID,
}
connFields := map[string]any{
"connected": connected,
"association_time": conn.AssociationTime.Val,
"errors": len(conn.Errors),
}
r.send(&metric{Table: "vpn_mesh_connection", Tags: connTags, Fields: connFields})
}
statusTags := map[string]string{
"site_name": m.SiteName,
"source": m.SourceName,
"mesh_name": m.Name,
"status_site": s.SiteID,
}
statusFields := map[string]any{
"errors": len(s.Errors),
"warnings": len(s.Warnings),
}
r.send(&metric{Table: "vpn_mesh_status", Tags: statusTags, Fields: statusFields})
}
}