diff --git a/go.mod b/go.mod index 1a1fb466..6932c018 100644 --- a/go.mod +++ b/go.mod @@ -47,4 +47,4 @@ require ( google.golang.org/protobuf v1.36.11 // indirect ) -replace github.com/unpoller/unifi/v5 => ../unifi +// replace github.com/unpoller/unifi/v5 => ../unifi diff --git a/pkg/datadogunifi/datadog.go b/pkg/datadogunifi/datadog.go index 1c53d9a1..3eb511db 100644 --- a/pkg/datadogunifi/datadog.go +++ b/pkg/datadogunifi/datadog.go @@ -317,6 +317,10 @@ func (u *DatadogUnifi) loopPoints(r report) { } reportClientDPItotals(r, appTotal, catTotal) + + for _, w := range m.WANConfigs { + u.switchExport(r, w) + } } func (u *DatadogUnifi) switchExport(r report, v any) { //nolint:cyclop @@ -353,6 +357,8 @@ func (u *DatadogUnifi) switchExport(r report, v any) { //nolint:cyclop u.batchAnomaly(r, v) case *unifi.SpeedTestResult: u.batchSpeedTest(r, v) + case *unifi.WANEnrichedConfiguration: + u.batchWAN(r, v) default: if u.Collector != nil && u.Collector.Poller().LogUnknownTypes { u.LogDebugf("unknown export type: %T", v) diff --git a/pkg/datadogunifi/ubb.go b/pkg/datadogunifi/ubb.go index 119e3cd3..ee39ba9b 100644 --- a/pkg/datadogunifi/ubb.go +++ b/pkg/datadogunifi/ubb.go @@ -70,6 +70,7 @@ func (u *DatadogUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen data["p2p_tx_rate"] = s.P2PStats.TXRate.Val data["p2p_throughput"] = s.P2PStats.Throughput.Val } + data["link_quality"] = s.LinkQuality.Val data["link_quality_current"] = s.LinkQualityCurrent.Val data["link_capacity"] = s.LinkCapacity.Val @@ -97,52 +98,52 @@ func (u *DatadogUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]float64 { // Total aggregated stats across both radios return map[string]float64{ - "stat_bytes": bb.Bytes.Val, - "stat_duration": bb.Duration.Val, - "stat_rx_packets": bb.RxPackets.Val, - "stat_rx_bytes": bb.RxBytes.Val, - "stat_rx_errors": bb.RxErrors.Val, - "stat_rx_dropped": bb.RxDropped.Val, - "stat_rx_crypts": bb.RxCrypts.Val, - "stat_rx_frags": bb.RxFrags.Val, - "stat_tx_packets": bb.TxPackets.Val, - "stat_tx_bytes": bb.TxBytes.Val, - "stat_tx_errors": bb.TxErrors.Val, - "stat_tx_dropped": bb.TxDropped.Val, - "stat_tx_retries": bb.TxRetries.Val, - "stat_mac_filter_rejections": bb.MacFilterRejections.Val, - "stat_wifi_tx_attempts": bb.WifiTxAttempts.Val, - "stat_wifi_tx_dropped": bb.WifiTxDropped.Val, + "stat_bytes": bb.Bytes.Val, + "stat_duration": bb.Duration.Val, + "stat_rx_packets": bb.RxPackets.Val, + "stat_rx_bytes": bb.RxBytes.Val, + "stat_rx_errors": bb.RxErrors.Val, + "stat_rx_dropped": bb.RxDropped.Val, + "stat_rx_crypts": bb.RxCrypts.Val, + "stat_rx_frags": bb.RxFrags.Val, + "stat_tx_packets": bb.TxPackets.Val, + "stat_tx_bytes": bb.TxBytes.Val, + "stat_tx_errors": bb.TxErrors.Val, + "stat_tx_dropped": bb.TxDropped.Val, + "stat_tx_retries": bb.TxRetries.Val, + "stat_mac_filter_rejections": bb.MacFilterRejections.Val, + "stat_wifi_tx_attempts": bb.WifiTxAttempts.Val, + "stat_wifi_tx_dropped": bb.WifiTxDropped.Val, // User aggregated stats - "stat_user_rx_packets": bb.UserRxPackets.Val, - "stat_user_rx_bytes": bb.UserRxBytes.Val, - "stat_user_rx_errors": bb.UserRxErrors.Val, - "stat_user_rx_dropped": bb.UserRxDropped.Val, - "stat_user_rx_crypts": bb.UserRxCrypts.Val, - "stat_user_rx_frags": bb.UserRxFrags.Val, - "stat_user_tx_packets": bb.UserTxPackets.Val, - "stat_user_tx_bytes": bb.UserTxBytes.Val, - "stat_user_tx_errors": bb.UserTxErrors.Val, - "stat_user_tx_dropped": bb.UserTxDropped.Val, - "stat_user_tx_retries": bb.UserTxRetries.Val, + "stat_user_rx_packets": bb.UserRxPackets.Val, + "stat_user_rx_bytes": bb.UserRxBytes.Val, + "stat_user_rx_errors": bb.UserRxErrors.Val, + "stat_user_rx_dropped": bb.UserRxDropped.Val, + "stat_user_rx_crypts": bb.UserRxCrypts.Val, + "stat_user_rx_frags": bb.UserRxFrags.Val, + "stat_user_tx_packets": bb.UserTxPackets.Val, + "stat_user_tx_bytes": bb.UserTxBytes.Val, + "stat_user_tx_errors": bb.UserTxErrors.Val, + "stat_user_tx_dropped": bb.UserTxDropped.Val, + "stat_user_tx_retries": bb.UserTxRetries.Val, "stat_user_mac_filter_rejections": bb.UserMacFilterRejections.Val, "stat_user_wifi_tx_attempts": bb.UserWifiTxAttempts.Val, "stat_user_wifi_tx_dropped": bb.UserWifiTxDropped.Val, // wifi0 radio stats (5GHz) - "stat_wifi0_rx_packets": bb.Wifi0RxPackets.Val, - "stat_wifi0_rx_bytes": bb.Wifi0RxBytes.Val, - "stat_wifi0_rx_errors": bb.Wifi0RxErrors.Val, - "stat_wifi0_rx_dropped": bb.Wifi0RxDropped.Val, - "stat_wifi0_rx_crypts": bb.Wifi0RxCrypts.Val, - "stat_wifi0_rx_frags": bb.Wifi0RxFrags.Val, - "stat_wifi0_tx_packets": bb.Wifi0TxPackets.Val, - "stat_wifi0_tx_bytes": bb.Wifi0TxBytes.Val, - "stat_wifi0_tx_errors": bb.Wifi0TxErrors.Val, - "stat_wifi0_tx_dropped": bb.Wifi0TxDropped.Val, - "stat_wifi0_tx_retries": bb.Wifi0TxRetries.Val, - "stat_wifi0_mac_filter_rejections": bb.Wifi0MacFilterRejections.Val, - "stat_wifi0_wifi_tx_attempts": bb.Wifi0WifiTxAttempts.Val, - "stat_wifi0_wifi_tx_dropped": bb.Wifi0WifiTxDropped.Val, + "stat_wifi0_rx_packets": bb.Wifi0RxPackets.Val, + "stat_wifi0_rx_bytes": bb.Wifi0RxBytes.Val, + "stat_wifi0_rx_errors": bb.Wifi0RxErrors.Val, + "stat_wifi0_rx_dropped": bb.Wifi0RxDropped.Val, + "stat_wifi0_rx_crypts": bb.Wifi0RxCrypts.Val, + "stat_wifi0_rx_frags": bb.Wifi0RxFrags.Val, + "stat_wifi0_tx_packets": bb.Wifi0TxPackets.Val, + "stat_wifi0_tx_bytes": bb.Wifi0TxBytes.Val, + "stat_wifi0_tx_errors": bb.Wifi0TxErrors.Val, + "stat_wifi0_tx_dropped": bb.Wifi0TxDropped.Val, + "stat_wifi0_tx_retries": bb.Wifi0TxRetries.Val, + "stat_wifi0_mac_filter_rejections": bb.Wifi0MacFilterRejections.Val, + "stat_wifi0_wifi_tx_attempts": bb.Wifi0WifiTxAttempts.Val, + "stat_wifi0_wifi_tx_dropped": bb.Wifi0WifiTxDropped.Val, // terra2 radio stats (60GHz - 802.11ad) "stat_terra2_rx_packets": bb.Terra2RxPackets.Val, "stat_terra2_rx_bytes": bb.Terra2RxBytes.Val, @@ -159,20 +160,20 @@ func (u *DatadogUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]float64 { "stat_terra2_wifi_tx_attempts": bb.Terra2WifiTxAttempts.Val, "stat_terra2_wifi_tx_dropped": bb.Terra2WifiTxDropped.Val, // User wifi0 stats - "stat_user_wifi0_rx_packets": bb.UserWifi0RxPackets.Val, - "stat_user_wifi0_rx_bytes": bb.UserWifi0RxBytes.Val, - "stat_user_wifi0_rx_errors": bb.UserWifi0RxErrors.Val, - "stat_user_wifi0_rx_dropped": bb.UserWifi0RxDropped.Val, - "stat_user_wifi0_rx_crypts": bb.UserWifi0RxCrypts.Val, - "stat_user_wifi0_rx_frags": bb.UserWifi0RxFrags.Val, - "stat_user_wifi0_tx_packets": bb.UserWifi0TxPackets.Val, - "stat_user_wifi0_tx_bytes": bb.UserWifi0TxBytes.Val, - "stat_user_wifi0_tx_errors": bb.UserWifi0TxErrors.Val, - "stat_user_wifi0_tx_dropped": bb.UserWifi0TxDropped.Val, - "stat_user_wifi0_tx_retries": bb.UserWifi0TxRetries.Val, - "stat_user_wifi0_mac_filter_rejections": bb.UserWifi0MacFilterRejections.Val, - "stat_user_wifi0_wifi_tx_attempts": bb.UserWifi0WifiTxAttempts.Val, - "stat_user_wifi0_wifi_tx_dropped": bb.UserWifi0WifiTxDropped.Val, + "stat_user_wifi0_rx_packets": bb.UserWifi0RxPackets.Val, + "stat_user_wifi0_rx_bytes": bb.UserWifi0RxBytes.Val, + "stat_user_wifi0_rx_errors": bb.UserWifi0RxErrors.Val, + "stat_user_wifi0_rx_dropped": bb.UserWifi0RxDropped.Val, + "stat_user_wifi0_rx_crypts": bb.UserWifi0RxCrypts.Val, + "stat_user_wifi0_rx_frags": bb.UserWifi0RxFrags.Val, + "stat_user_wifi0_tx_packets": bb.UserWifi0TxPackets.Val, + "stat_user_wifi0_tx_bytes": bb.UserWifi0TxBytes.Val, + "stat_user_wifi0_tx_errors": bb.UserWifi0TxErrors.Val, + "stat_user_wifi0_tx_dropped": bb.UserWifi0TxDropped.Val, + "stat_user_wifi0_tx_retries": bb.UserWifi0TxRetries.Val, + "stat_user_wifi0_mac_filter_rejections": bb.UserWifi0MacFilterRejections.Val, + "stat_user_wifi0_wifi_tx_attempts": bb.UserWifi0WifiTxAttempts.Val, + "stat_user_wifi0_wifi_tx_dropped": bb.UserWifi0WifiTxDropped.Val, // User terra2 stats (60GHz) "stat_user_terra2_rx_packets": bb.UserTerra2RxPackets.Val, "stat_user_terra2_rx_bytes": bb.UserTerra2RxBytes.Val, @@ -189,10 +190,10 @@ func (u *DatadogUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]float64 { "stat_user_terra2_wifi_tx_attempts": bb.UserTerra2WifiTxAttempts.Val, "stat_user_terra2_wifi_tx_dropped": bb.UserTerra2WifiTxDropped.Val, // Interface-specific stats - "stat_user_wifi0_ath0_rx_packets": bb.UserWifi0Ath0RxPackets.Val, - "stat_user_wifi0_ath0_rx_bytes": bb.UserWifi0Ath0RxBytes.Val, - "stat_user_wifi0_ath0_tx_packets": bb.UserWifi0Ath0TxPackets.Val, - "stat_user_wifi0_ath0_tx_bytes": bb.UserWifi0Ath0TxBytes.Val, + "stat_user_wifi0_ath0_rx_packets": bb.UserWifi0Ath0RxPackets.Val, + "stat_user_wifi0_ath0_rx_bytes": bb.UserWifi0Ath0RxBytes.Val, + "stat_user_wifi0_ath0_tx_packets": bb.UserWifi0Ath0TxPackets.Val, + "stat_user_wifi0_ath0_tx_bytes": bb.UserWifi0Ath0TxBytes.Val, "stat_user_terra2_wlan0_rx_packets": bb.UserTerra2Wlan0RxPackets.Val, "stat_user_terra2_wlan0_rx_bytes": bb.UserTerra2Wlan0RxBytes.Val, "stat_user_terra2_wlan0_tx_packets": bb.UserTerra2Wlan0TxPackets.Val, diff --git a/pkg/datadogunifi/wan.go b/pkg/datadogunifi/wan.go new file mode 100644 index 00000000..0b9dd516 --- /dev/null +++ b/pkg/datadogunifi/wan.go @@ -0,0 +1,70 @@ +package datadogunifi + +import ( + "github.com/unpoller/unifi/v5" +) + +// batchWAN generates WAN configuration datapoints for Datadog. +// These points can be passed directly to Datadog. +func (u *DatadogUnifi) batchWAN(r report, w *unifi.WANEnrichedConfiguration) { + if w == nil { + return + } + + metricName := metricNamespace("wan") + + cfg := w.Configuration + stats := w.Statistics + details := w.Details + + tags := []string{ + tag("wan_id", cfg.ID), + tag("wan_name", cfg.Name), + tag("wan_networkgroup", cfg.WANNetworkgroup), + tag("wan_type", cfg.WANType), + tag("wan_load_balance_type", cfg.WANLoadBalanceType), + tag("isp_name", details.ServiceProvider.Name), + tag("isp_city", details.ServiceProvider.City), + } + + // Convert boolean FlexBool values to float64 for Datadog + smartQEnabled := 0.0 + if cfg.WANSmartqEnabled.Val { + smartQEnabled = 1.0 + } + + magicEnabled := 0.0 + if cfg.WANMagicEnabled.Val { + magicEnabled = 1.0 + } + + vlanEnabled := 0.0 + if cfg.WANVlanEnabled.Val { + vlanEnabled = 1.0 + } + + data := map[string]float64{ + // Configuration + "failover_priority": cfg.WANFailoverPriority.Val, + "load_balance_weight": cfg.WANLoadBalanceWeight.Val, + "provider_download_kbps": cfg.WANProviderCapabilities.DownloadKbps.Val, + "provider_upload_kbps": cfg.WANProviderCapabilities.UploadKbps.Val, + "smartq_enabled": smartQEnabled, + "magic_enabled": magicEnabled, + "vlan_enabled": vlanEnabled, + // Statistics + "uptime_percentage": stats.UptimePercentage, + "peak_download_percent": stats.PeakUsage.DownloadPercentage, + "peak_upload_percent": stats.PeakUsage.UploadPercentage, + "max_rx_bytes_rate": stats.PeakUsage.MaxRxBytesR.Val, + "max_tx_bytes_rate": stats.PeakUsage.MaxTxBytesR.Val, + // Service Provider + "service_provider_asn": details.ServiceProvider.ASN.Val, + // Metadata + "creation_timestamp": details.CreationTimestamp.Val, + } + + for name, value := range data { + _ = r.reportGauge(metricName(name), value, tags) + } +} diff --git a/pkg/influxunifi/influxdb.go b/pkg/influxunifi/influxdb.go index d5c4c2a5..7cf1ce3f 100644 --- a/pkg/influxunifi/influxdb.go +++ b/pkg/influxunifi/influxdb.go @@ -430,6 +430,10 @@ func (u *InfluxUnifi) loopPoints(r report) { } reportClientDPItotals(r, appTotal, catTotal) + + for _, w := range m.WANConfigs { + u.switchExport(r, w) + } } func (u *InfluxUnifi) switchExport(r report, v any) { //nolint:cyclop @@ -466,6 +470,8 @@ func (u *InfluxUnifi) switchExport(r report, v any) { //nolint:cyclop u.batchAnomaly(r, v) case *unifi.SpeedTestResult: u.batchSpeedTest(r, v) + case *unifi.WANEnrichedConfiguration: + u.batchWAN(r, v) default: if u.Collector.Poller().LogUnknownTypes { u.LogDebugf("unknown export type: %T", v) diff --git a/pkg/influxunifi/ubb.go b/pkg/influxunifi/ubb.go index 4c379bbc..17ac6d90 100644 --- a/pkg/influxunifi/ubb.go +++ b/pkg/influxunifi/ubb.go @@ -66,6 +66,7 @@ func (u *InfluxUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen fields["p2p_tx_rate"] = s.P2PStats.TXRate.Val fields["p2p_throughput"] = s.P2PStats.Throughput.Val } + fields["link_quality"] = s.LinkQuality.Val fields["link_quality_current"] = s.LinkQualityCurrent.Val fields["link_capacity"] = s.LinkCapacity.Val @@ -91,52 +92,52 @@ func (u *InfluxUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]any { // Total aggregated stats across both radios return map[string]any{ - "stat_bytes": bb.Bytes.Val, - "stat_duration": bb.Duration.Val, - "stat_rx_packets": bb.RxPackets.Val, - "stat_rx_bytes": bb.RxBytes.Val, - "stat_rx_errors": bb.RxErrors.Val, - "stat_rx_dropped": bb.RxDropped.Val, - "stat_rx_crypts": bb.RxCrypts.Val, - "stat_rx_frags": bb.RxFrags.Val, - "stat_tx_packets": bb.TxPackets.Val, - "stat_tx_bytes": bb.TxBytes.Val, - "stat_tx_errors": bb.TxErrors.Val, - "stat_tx_dropped": bb.TxDropped.Val, - "stat_tx_retries": bb.TxRetries.Val, - "stat_mac_filter_rejections": bb.MacFilterRejections.Val, - "stat_wifi_tx_attempts": bb.WifiTxAttempts.Val, - "stat_wifi_tx_dropped": bb.WifiTxDropped.Val, + "stat_bytes": bb.Bytes.Val, + "stat_duration": bb.Duration.Val, + "stat_rx_packets": bb.RxPackets.Val, + "stat_rx_bytes": bb.RxBytes.Val, + "stat_rx_errors": bb.RxErrors.Val, + "stat_rx_dropped": bb.RxDropped.Val, + "stat_rx_crypts": bb.RxCrypts.Val, + "stat_rx_frags": bb.RxFrags.Val, + "stat_tx_packets": bb.TxPackets.Val, + "stat_tx_bytes": bb.TxBytes.Val, + "stat_tx_errors": bb.TxErrors.Val, + "stat_tx_dropped": bb.TxDropped.Val, + "stat_tx_retries": bb.TxRetries.Val, + "stat_mac_filter_rejections": bb.MacFilterRejections.Val, + "stat_wifi_tx_attempts": bb.WifiTxAttempts.Val, + "stat_wifi_tx_dropped": bb.WifiTxDropped.Val, // User aggregated stats - "stat_user-rx_packets": bb.UserRxPackets.Val, - "stat_user-rx_bytes": bb.UserRxBytes.Val, - "stat_user-rx_errors": bb.UserRxErrors.Val, - "stat_user-rx_dropped": bb.UserRxDropped.Val, - "stat_user-rx_crypts": bb.UserRxCrypts.Val, - "stat_user-rx_frags": bb.UserRxFrags.Val, - "stat_user-tx_packets": bb.UserTxPackets.Val, - "stat_user-tx_bytes": bb.UserTxBytes.Val, - "stat_user-tx_errors": bb.UserTxErrors.Val, - "stat_user-tx_dropped": bb.UserTxDropped.Val, - "stat_user-tx_retries": bb.UserTxRetries.Val, + "stat_user-rx_packets": bb.UserRxPackets.Val, + "stat_user-rx_bytes": bb.UserRxBytes.Val, + "stat_user-rx_errors": bb.UserRxErrors.Val, + "stat_user-rx_dropped": bb.UserRxDropped.Val, + "stat_user-rx_crypts": bb.UserRxCrypts.Val, + "stat_user-rx_frags": bb.UserRxFrags.Val, + "stat_user-tx_packets": bb.UserTxPackets.Val, + "stat_user-tx_bytes": bb.UserTxBytes.Val, + "stat_user-tx_errors": bb.UserTxErrors.Val, + "stat_user-tx_dropped": bb.UserTxDropped.Val, + "stat_user-tx_retries": bb.UserTxRetries.Val, "stat_user-mac_filter_rejections": bb.UserMacFilterRejections.Val, "stat_user-wifi_tx_attempts": bb.UserWifiTxAttempts.Val, "stat_user-wifi_tx_dropped": bb.UserWifiTxDropped.Val, // wifi0 radio stats (5GHz) - "stat_wifi0-rx_packets": bb.Wifi0RxPackets.Val, - "stat_wifi0-rx_bytes": bb.Wifi0RxBytes.Val, - "stat_wifi0-rx_errors": bb.Wifi0RxErrors.Val, - "stat_wifi0-rx_dropped": bb.Wifi0RxDropped.Val, - "stat_wifi0-rx_crypts": bb.Wifi0RxCrypts.Val, - "stat_wifi0-rx_frags": bb.Wifi0RxFrags.Val, - "stat_wifi0-tx_packets": bb.Wifi0TxPackets.Val, - "stat_wifi0-tx_bytes": bb.Wifi0TxBytes.Val, - "stat_wifi0-tx_errors": bb.Wifi0TxErrors.Val, - "stat_wifi0-tx_dropped": bb.Wifi0TxDropped.Val, - "stat_wifi0-tx_retries": bb.Wifi0TxRetries.Val, - "stat_wifi0-mac_filter_rejections": bb.Wifi0MacFilterRejections.Val, - "stat_wifi0-wifi_tx_attempts": bb.Wifi0WifiTxAttempts.Val, - "stat_wifi0-wifi_tx_dropped": bb.Wifi0WifiTxDropped.Val, + "stat_wifi0-rx_packets": bb.Wifi0RxPackets.Val, + "stat_wifi0-rx_bytes": bb.Wifi0RxBytes.Val, + "stat_wifi0-rx_errors": bb.Wifi0RxErrors.Val, + "stat_wifi0-rx_dropped": bb.Wifi0RxDropped.Val, + "stat_wifi0-rx_crypts": bb.Wifi0RxCrypts.Val, + "stat_wifi0-rx_frags": bb.Wifi0RxFrags.Val, + "stat_wifi0-tx_packets": bb.Wifi0TxPackets.Val, + "stat_wifi0-tx_bytes": bb.Wifi0TxBytes.Val, + "stat_wifi0-tx_errors": bb.Wifi0TxErrors.Val, + "stat_wifi0-tx_dropped": bb.Wifi0TxDropped.Val, + "stat_wifi0-tx_retries": bb.Wifi0TxRetries.Val, + "stat_wifi0-mac_filter_rejections": bb.Wifi0MacFilterRejections.Val, + "stat_wifi0-wifi_tx_attempts": bb.Wifi0WifiTxAttempts.Val, + "stat_wifi0-wifi_tx_dropped": bb.Wifi0WifiTxDropped.Val, // terra2 radio stats (60GHz - 802.11ad) "stat_terra2-rx_packets": bb.Terra2RxPackets.Val, "stat_terra2-rx_bytes": bb.Terra2RxBytes.Val, @@ -153,20 +154,20 @@ func (u *InfluxUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]any { "stat_terra2-wifi_tx_attempts": bb.Terra2WifiTxAttempts.Val, "stat_terra2-wifi_tx_dropped": bb.Terra2WifiTxDropped.Val, // User wifi0 stats - "stat_user-wifi0-rx_packets": bb.UserWifi0RxPackets.Val, - "stat_user-wifi0-rx_bytes": bb.UserWifi0RxBytes.Val, - "stat_user-wifi0-rx_errors": bb.UserWifi0RxErrors.Val, - "stat_user-wifi0-rx_dropped": bb.UserWifi0RxDropped.Val, - "stat_user-wifi0-rx_crypts": bb.UserWifi0RxCrypts.Val, - "stat_user-wifi0-rx_frags": bb.UserWifi0RxFrags.Val, - "stat_user-wifi0-tx_packets": bb.UserWifi0TxPackets.Val, - "stat_user-wifi0-tx_bytes": bb.UserWifi0TxBytes.Val, - "stat_user-wifi0-tx_errors": bb.UserWifi0TxErrors.Val, - "stat_user-wifi0-tx_dropped": bb.UserWifi0TxDropped.Val, - "stat_user-wifi0-tx_retries": bb.UserWifi0TxRetries.Val, - "stat_user-wifi0-mac_filter_rejections": bb.UserWifi0MacFilterRejections.Val, - "stat_user-wifi0-wifi_tx_attempts": bb.UserWifi0WifiTxAttempts.Val, - "stat_user-wifi0-wifi_tx_dropped": bb.UserWifi0WifiTxDropped.Val, + "stat_user-wifi0-rx_packets": bb.UserWifi0RxPackets.Val, + "stat_user-wifi0-rx_bytes": bb.UserWifi0RxBytes.Val, + "stat_user-wifi0-rx_errors": bb.UserWifi0RxErrors.Val, + "stat_user-wifi0-rx_dropped": bb.UserWifi0RxDropped.Val, + "stat_user-wifi0-rx_crypts": bb.UserWifi0RxCrypts.Val, + "stat_user-wifi0-rx_frags": bb.UserWifi0RxFrags.Val, + "stat_user-wifi0-tx_packets": bb.UserWifi0TxPackets.Val, + "stat_user-wifi0-tx_bytes": bb.UserWifi0TxBytes.Val, + "stat_user-wifi0-tx_errors": bb.UserWifi0TxErrors.Val, + "stat_user-wifi0-tx_dropped": bb.UserWifi0TxDropped.Val, + "stat_user-wifi0-tx_retries": bb.UserWifi0TxRetries.Val, + "stat_user-wifi0-mac_filter_rejections": bb.UserWifi0MacFilterRejections.Val, + "stat_user-wifi0-wifi_tx_attempts": bb.UserWifi0WifiTxAttempts.Val, + "stat_user-wifi0-wifi_tx_dropped": bb.UserWifi0WifiTxDropped.Val, // User terra2 stats (60GHz) "stat_user-terra2-rx_packets": bb.UserTerra2RxPackets.Val, "stat_user-terra2-rx_bytes": bb.UserTerra2RxBytes.Val, @@ -183,10 +184,10 @@ func (u *InfluxUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]any { "stat_user-terra2-wifi_tx_attempts": bb.UserTerra2WifiTxAttempts.Val, "stat_user-terra2-wifi_tx_dropped": bb.UserTerra2WifiTxDropped.Val, // Interface-specific stats - "stat_user-wifi0-ath0-rx_packets": bb.UserWifi0Ath0RxPackets.Val, - "stat_user-wifi0-ath0-rx_bytes": bb.UserWifi0Ath0RxBytes.Val, - "stat_user-wifi0-ath0-tx_packets": bb.UserWifi0Ath0TxPackets.Val, - "stat_user-wifi0-ath0-tx_bytes": bb.UserWifi0Ath0TxBytes.Val, + "stat_user-wifi0-ath0-rx_packets": bb.UserWifi0Ath0RxPackets.Val, + "stat_user-wifi0-ath0-rx_bytes": bb.UserWifi0Ath0RxBytes.Val, + "stat_user-wifi0-ath0-tx_packets": bb.UserWifi0Ath0TxPackets.Val, + "stat_user-wifi0-ath0-tx_bytes": bb.UserWifi0Ath0TxBytes.Val, "stat_user-terra2-wlan0-rx_packets": bb.UserTerra2Wlan0RxPackets.Val, "stat_user-terra2-wlan0-rx_bytes": bb.UserTerra2Wlan0RxBytes.Val, "stat_user-terra2-wlan0-tx_packets": bb.UserTerra2Wlan0TxPackets.Val, diff --git a/pkg/influxunifi/wan.go b/pkg/influxunifi/wan.go new file mode 100644 index 00000000..890f4bf0 --- /dev/null +++ b/pkg/influxunifi/wan.go @@ -0,0 +1,66 @@ +package influxunifi + +import ( + "github.com/unpoller/unifi/v5" +) + +// batchWAN generates WAN configuration datapoints for InfluxDB. +// These points can be passed directly to influx. +func (u *InfluxUnifi) batchWAN(r report, w *unifi.WANEnrichedConfiguration) { + if w == nil { + return + } + + cfg := w.Configuration + stats := w.Statistics + details := w.Details + + tags := map[string]string{ + "wan_id": cfg.ID, + "wan_name": cfg.Name, + "wan_networkgroup": cfg.WANNetworkgroup, + "wan_type": cfg.WANType, + "wan_load_balance_type": cfg.WANLoadBalanceType, + "isp_name": details.ServiceProvider.Name, + "isp_city": details.ServiceProvider.City, + } + + // Convert boolean FlexBool values to int for InfluxDB + smartQEnabled := 0 + if cfg.WANSmartqEnabled.Val { + smartQEnabled = 1 + } + + magicEnabled := 0 + if cfg.WANMagicEnabled.Val { + magicEnabled = 1 + } + + vlanEnabled := 0 + if cfg.WANVlanEnabled.Val { + vlanEnabled = 1 + } + + fields := map[string]any{ + // Configuration + "failover_priority": cfg.WANFailoverPriority.Val, + "load_balance_weight": cfg.WANLoadBalanceWeight.Val, + "provider_download_kbps": cfg.WANProviderCapabilities.DownloadKbps.Val, + "provider_upload_kbps": cfg.WANProviderCapabilities.UploadKbps.Val, + "smartq_enabled": smartQEnabled, + "magic_enabled": magicEnabled, + "vlan_enabled": vlanEnabled, + // Statistics + "uptime_percentage": stats.UptimePercentage, + "peak_download_percent": stats.PeakUsage.DownloadPercentage, + "peak_upload_percent": stats.PeakUsage.UploadPercentage, + "max_rx_bytes_rate": stats.PeakUsage.MaxRxBytesR.Val, + "max_tx_bytes_rate": stats.PeakUsage.MaxTxBytesR.Val, + // Service Provider + "service_provider_asn": details.ServiceProvider.ASN.Val, + // Metadata + "creation_timestamp": details.CreationTimestamp.Val, + } + + r.send(&metric{Table: "wan", Tags: tags, Fields: fields}) +} diff --git a/pkg/promunifi/wan.go b/pkg/promunifi/wan.go index 917aa441..aef4cde8 100644 --- a/pkg/promunifi/wan.go +++ b/pkg/promunifi/wan.go @@ -15,15 +15,15 @@ type wan struct { MagicEnabled *prometheus.Desc VlanEnabled *prometheus.Desc // WAN Statistics metrics - UptimePercentage *prometheus.Desc - PeakDownloadPercent *prometheus.Desc - PeakUploadPercent *prometheus.Desc - MaxRxBytesR *prometheus.Desc - MaxTxBytesR *prometheus.Desc + UptimePercentage *prometheus.Desc + PeakDownloadPercent *prometheus.Desc + PeakUploadPercent *prometheus.Desc + MaxRxBytesR *prometheus.Desc + MaxTxBytesR *prometheus.Desc // WAN Service Provider metrics - ServiceProviderASN *prometheus.Desc + ServiceProviderASN *prometheus.Desc // WAN Creation timestamp - CreationTimestamp *prometheus.Desc + CreationTimestamp *prometheus.Desc } func descWAN(ns string) *wan { @@ -36,7 +36,7 @@ func descWAN(ns string) *wan { "site_name", "source", } - + providerLabels := []string{ "wan_id", "wan_name", @@ -59,15 +59,15 @@ func descWAN(ns string) *wan { MagicEnabled: nd(ns+"wan_magic_enabled", "Magic WAN enabled (1) or disabled (0)", labels, nil), VlanEnabled: nd(ns+"wan_vlan_enabled", "VLAN enabled for WAN (1) or disabled (0)", labels, nil), // Statistics - UptimePercentage: nd(ns+"wan_uptime_percentage", "WAN uptime percentage", labels, nil), - PeakDownloadPercent: nd(ns+"wan_peak_download_percent", "Peak download usage as percentage of configured capacity", labels, nil), - PeakUploadPercent: nd(ns+"wan_peak_upload_percent", "Peak upload usage as percentage of configured capacity", labels, nil), - MaxRxBytesR: nd(ns+"wan_max_rx_bytes_rate", "Maximum receive bytes rate", labels, nil), - MaxTxBytesR: nd(ns+"wan_max_tx_bytes_rate", "Maximum transmit bytes rate", labels, nil), + UptimePercentage: nd(ns+"wan_uptime_percentage", "WAN uptime percentage", labels, nil), + PeakDownloadPercent: nd(ns+"wan_peak_download_percent", "Peak download usage as percentage of configured capacity", labels, nil), + PeakUploadPercent: nd(ns+"wan_peak_upload_percent", "Peak upload usage as percentage of configured capacity", labels, nil), + MaxRxBytesR: nd(ns+"wan_max_rx_bytes_rate", "Maximum receive bytes rate", labels, nil), + MaxTxBytesR: nd(ns+"wan_max_tx_bytes_rate", "Maximum transmit bytes rate", labels, nil), // Service Provider - ServiceProviderASN: nd(ns+"wan_service_provider_asn", "Service provider autonomous system number", providerLabels, nil), + ServiceProviderASN: nd(ns+"wan_service_provider_asn", "Service provider autonomous system number", providerLabels, nil), // Creation - CreationTimestamp: nd(ns+"wan_creation_timestamp", "WAN configuration creation timestamp", labels, nil), + CreationTimestamp: nd(ns+"wan_creation_timestamp", "WAN configuration creation timestamp", labels, nil), } } @@ -87,8 +87,8 @@ func (u *promUnifi) exportWAN(r report, w *unifi.WANEnrichedConfiguration) { cfg.WANNetworkgroup, cfg.WANType, cfg.WANLoadBalanceType, - "", // site_name - will be set by caller if available - "", // source - will be set by caller if available + "", // site_name - will be set by caller if available + "", // source - will be set by caller if available } // Convert boolean FlexBool values to float64 @@ -130,8 +130,8 @@ func (u *promUnifi) exportWAN(r report, w *unifi.WANEnrichedConfiguration) { cfg.WANNetworkgroup, details.ServiceProvider.Name, details.ServiceProvider.City, - "", // site_name - "", // source + "", // site_name + "", // source } metrics = append(metrics, &metric{u.WAN.ServiceProviderASN, gauge, details.ServiceProvider.ASN.Val, providerLabels})