Enhance InfluxDB and Datadog UBB outputs with comprehensive metrics

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>
This commit is contained in:
Cody Lee
2025-12-09 10:53:39 -06:00
parent ab2c677f30
commit c61d2651a2
4 changed files with 450 additions and 85 deletions

View File

@@ -370,6 +370,98 @@ gauges:
- unifi.ubb.uplink_latency
- unifi.ubb.uplink_max_speed
- unifi.ubb.uplink_uptime
- unifi.ubb.upgradeable
- unifi.ubb.link_capacity
- unifi.ubb.link_quality
- unifi.ubb.link_quality_current
- unifi.ubb.p2p_rx_rate
- unifi.ubb.p2p_throughput
- unifi.ubb.p2p_tx_rate
- unifi.ubb.stat_duration
- unifi.ubb.stat_mac_filter_rejections
- unifi.ubb.stat_terra2_mac_filter_rejections
- unifi.ubb.stat_terra2_rx_bytes
- unifi.ubb.stat_terra2_rx_crypts
- unifi.ubb.stat_terra2_rx_dropped
- unifi.ubb.stat_terra2_rx_errors
- unifi.ubb.stat_terra2_rx_frags
- unifi.ubb.stat_terra2_rx_packets
- unifi.ubb.stat_terra2_tx_bytes
- unifi.ubb.stat_terra2_tx_dropped
- unifi.ubb.stat_terra2_tx_errors
- unifi.ubb.stat_terra2_tx_packets
- unifi.ubb.stat_terra2_tx_retries
- unifi.ubb.stat_terra2_wifi_tx_attempts
- unifi.ubb.stat_terra2_wifi_tx_dropped
- unifi.ubb.stat_user_mac_filter_rejections
- unifi.ubb.stat_user_rx_bytes
- unifi.ubb.stat_user_rx_crypts
- unifi.ubb.stat_user_rx_dropped
- unifi.ubb.stat_user_rx_errors
- unifi.ubb.stat_user_rx_frags
- unifi.ubb.stat_user_rx_packets
- unifi.ubb.stat_user_terra2_mac_filter_rejections
- unifi.ubb.stat_user_terra2_rx_bytes
- unifi.ubb.stat_user_terra2_rx_crypts
- unifi.ubb.stat_user_terra2_rx_dropped
- unifi.ubb.stat_user_terra2_rx_errors
- unifi.ubb.stat_user_terra2_rx_frags
- unifi.ubb.stat_user_terra2_rx_packets
- unifi.ubb.stat_user_terra2_tx_bytes
- unifi.ubb.stat_user_terra2_tx_dropped
- unifi.ubb.stat_user_terra2_tx_errors
- unifi.ubb.stat_user_terra2_tx_packets
- unifi.ubb.stat_user_terra2_tx_retries
- unifi.ubb.stat_user_terra2_wifi_tx_attempts
- unifi.ubb.stat_user_terra2_wifi_tx_dropped
- unifi.ubb.stat_user_terra2_wlan0_rx_bytes
- unifi.ubb.stat_user_terra2_wlan0_rx_errors
- unifi.ubb.stat_user_terra2_wlan0_rx_packets
- unifi.ubb.stat_user_terra2_wlan0_tx_bytes
- unifi.ubb.stat_user_terra2_wlan0_tx_dropped
- unifi.ubb.stat_user_terra2_wlan0_tx_errors
- unifi.ubb.stat_user_terra2_wlan0_tx_packets
- unifi.ubb.stat_user_tx_bytes
- unifi.ubb.stat_user_tx_dropped
- unifi.ubb.stat_user_tx_errors
- unifi.ubb.stat_user_tx_packets
- unifi.ubb.stat_user_tx_retries
- unifi.ubb.stat_user_wifi0_ath0_rx_bytes
- unifi.ubb.stat_user_wifi0_ath0_rx_packets
- unifi.ubb.stat_user_wifi0_ath0_tx_bytes
- unifi.ubb.stat_user_wifi0_ath0_tx_packets
- unifi.ubb.stat_user_wifi0_mac_filter_rejections
- unifi.ubb.stat_user_wifi0_rx_bytes
- unifi.ubb.stat_user_wifi0_rx_crypts
- unifi.ubb.stat_user_wifi0_rx_dropped
- unifi.ubb.stat_user_wifi0_rx_errors
- unifi.ubb.stat_user_wifi0_rx_frags
- unifi.ubb.stat_user_wifi0_rx_packets
- unifi.ubb.stat_user_wifi0_tx_bytes
- unifi.ubb.stat_user_wifi0_tx_dropped
- unifi.ubb.stat_user_wifi0_tx_errors
- unifi.ubb.stat_user_wifi0_tx_packets
- unifi.ubb.stat_user_wifi0_tx_retries
- unifi.ubb.stat_user_wifi0_wifi_tx_attempts
- unifi.ubb.stat_user_wifi0_wifi_tx_dropped
- unifi.ubb.stat_user_wifi_tx_attempts
- unifi.ubb.stat_user_wifi_tx_dropped
- unifi.ubb.stat_wifi0_mac_filter_rejections
- unifi.ubb.stat_wifi0_rx_bytes
- unifi.ubb.stat_wifi0_rx_crypts
- unifi.ubb.stat_wifi0_rx_dropped
- unifi.ubb.stat_wifi0_rx_errors
- unifi.ubb.stat_wifi0_rx_frags
- unifi.ubb.stat_wifi0_rx_packets
- unifi.ubb.stat_wifi0_tx_bytes
- unifi.ubb.stat_wifi0_tx_dropped
- unifi.ubb.stat_wifi0_tx_errors
- unifi.ubb.stat_wifi0_tx_packets
- unifi.ubb.stat_wifi0_tx_retries
- unifi.ubb.stat_wifi0_wifi_tx_attempts
- unifi.ubb.stat_wifi0_wifi_tx_dropped
- unifi.ubb.stat_wifi_tx_attempts
- unifi.ubb.stat_wifi_tx_dropped
- unifi.usg.uplink_max_speed
- unifi.usg.uplink_uptime
- unifi.ubb.stat_rx_frags

View File

@@ -7,8 +7,10 @@ import (
// ubbT is used as a name for printed/logged counters.
const ubbT = item("UBB")
// batchUBB generates UBB datapoints for Datadog.
// These points can be passed directly to datadog.
// batchUBB generates UBB (UniFi Building Bridge) datapoints for Datadog.
// UBB devices are point-to-point wireless bridges with dual radios:
// - wifi0: 5GHz radio (802.11ac)
// - terra2/wlan0/ad: 60GHz radio (802.11ad - Terragraph/WiGig)
func (u *DatadogUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
if !s.Adopted.Val || s.Locating.Val {
return
@@ -27,11 +29,6 @@ func (u *DatadogUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
"license_state": s.LicenseState,
})
var sw *unifi.Bb
if s.Stat != nil {
sw = s.Stat.Bb
}
sysStats := unifi.SysStats{}
if s.SysStats != nil {
sysStats = *s.SysStats
@@ -44,6 +41,7 @@ func (u *DatadogUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
data := CombineFloat64(
u.batchSysStats(sysStats, systemStats),
u.batchUBBstats(s.Stat),
map[string]float64{
"bytes": s.Bytes.Val,
"last_seen": s.LastSeen.Val,
@@ -59,53 +57,148 @@ func (u *DatadogUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
},
)
// Add upgradeable as a float64 (0 or 1)
if s.Upgradable.Val {
data["upgradeable"] = 1.0
} else {
data["upgradeable"] = 0.0
}
// Add UBB-specific P2P and link quality metrics
if s.P2PStats != nil {
data["p2p_rx_rate"] = s.P2PStats.RXRate.Val
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
r.addCount(ubbT)
metricName := metricNamespace("ubb")
reportGaugeForFloat64Map(r, metricName, data, tags)
tags = cleanTags(map[string]string{
"mac": s.Mac,
"site_name": s.SiteName,
"source": s.SourceName,
"name": s.Name,
"version": s.Version,
"model": s.Model,
"serial": s.Serial,
"type": s.Type,
"ip": s.IP,
})
data = CombineFloat64(
u.batchUBBstat(sw),
map[string]float64{
"bytes": s.Bytes.Val,
"last_seen": s.LastSeen.Val,
"rx_bytes": s.RxBytes.Val,
"tx_bytes": s.TxBytes.Val,
"uptime": s.Uptime.Val,
})
// Export VAP table (Virtual Access Point table - wireless interface stats)
u.processVAPTable(r, tags, s.VapTable)
metricName = metricNamespace("ubb")
reportGaugeForFloat64Map(r, metricName, data, tags)
// Export Radio tables (includes 5GHz wifi0 and 60GHz terra2/ad radios)
u.processRadTable(r, tags, s.RadioTable, s.RadioTableStats)
}
func (u *DatadogUnifi) batchUBBstat(sw *unifi.Bb) map[string]float64 {
if sw == nil {
// batchUBBstats generates UBB-specific statistics separated by radio.
// This includes metrics for total, wifi0 (5GHz), terra2 (60GHz), and user-specific stats.
func (u *DatadogUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]float64 {
if stat == nil || stat.Bb == nil {
return map[string]float64{}
}
bb := stat.Bb
// Total aggregated stats across both radios
return map[string]float64{
"stat_bytes": sw.Bytes.Val,
"stat_rx_bytes": sw.RxBytes.Val,
"stat_rx_crypts": sw.RxCrypts.Val,
"stat_rx_dropped": sw.RxDropped.Val,
"stat_rx_errors": sw.RxErrors.Val,
"stat_rx_frags": sw.RxFrags.Val,
"stat_rx_packets": sw.TxPackets.Val,
"stat_tx_bytes": sw.TxBytes.Val,
"stat_tx_dropped": sw.TxDropped.Val,
"stat_tx_errors": sw.TxErrors.Val,
"stat_tx_packets": sw.TxPackets.Val,
"stat_tx_retries": sw.TxRetries.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_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,
// terra2 radio stats (60GHz - 802.11ad)
"stat_terra2_rx_packets": bb.Terra2RxPackets.Val,
"stat_terra2_rx_bytes": bb.Terra2RxBytes.Val,
"stat_terra2_rx_errors": bb.Terra2RxErrors.Val,
"stat_terra2_rx_dropped": bb.Terra2RxDropped.Val,
"stat_terra2_rx_crypts": bb.Terra2RxCrypts.Val,
"stat_terra2_rx_frags": bb.Terra2RxFrags.Val,
"stat_terra2_tx_packets": bb.Terra2TxPackets.Val,
"stat_terra2_tx_bytes": bb.Terra2TxBytes.Val,
"stat_terra2_tx_errors": bb.Terra2TxErrors.Val,
"stat_terra2_tx_dropped": bb.Terra2TxDropped.Val,
"stat_terra2_tx_retries": bb.Terra2TxRetries.Val,
"stat_terra2_mac_filter_rejections": bb.Terra2MacFilterRejections.Val,
"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,
// User terra2 stats (60GHz)
"stat_user_terra2_rx_packets": bb.UserTerra2RxPackets.Val,
"stat_user_terra2_rx_bytes": bb.UserTerra2RxBytes.Val,
"stat_user_terra2_rx_errors": bb.UserTerra2RxErrors.Val,
"stat_user_terra2_rx_dropped": bb.UserTerra2RxDropped.Val,
"stat_user_terra2_rx_crypts": bb.UserTerra2RxCrypts.Val,
"stat_user_terra2_rx_frags": bb.UserTerra2RxFrags.Val,
"stat_user_terra2_tx_packets": bb.UserTerra2TxPackets.Val,
"stat_user_terra2_tx_bytes": bb.UserTerra2TxBytes.Val,
"stat_user_terra2_tx_errors": bb.UserTerra2TxErrors.Val,
"stat_user_terra2_tx_dropped": bb.UserTerra2TxDropped.Val,
"stat_user_terra2_tx_retries": bb.UserTerra2TxRetries.Val,
"stat_user_terra2_mac_filter_rejections": bb.UserTerra2MacFilterRejections.Val,
"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_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,
"stat_user_terra2_wlan0_tx_bytes": bb.UserTerra2Wlan0TxBytes.Val,
"stat_user_terra2_wlan0_tx_dropped": bb.UserTerra2Wlan0TxDropped.Val,
"stat_user_terra2_wlan0_rx_errors": bb.UserTerra2Wlan0RxErrors.Val,
"stat_user_terra2_wlan0_tx_errors": bb.UserTerra2Wlan0TxErrors.Val,
}
}

View File

@@ -406,6 +406,9 @@ points:
ip: string
last_seen: float
license_state: string
link_capacity: float
link_quality: float
link_quality_current: float
loadavg_1: float
loadavg_5: float
loadavg_15: float
@@ -413,20 +416,108 @@ points:
mem_buffer: float
mem_total: float
mem_used: float
p2p_rx_rate: float
p2p_throughput: float
p2p_tx_rate: float
rx_bytes: float
source: string
stat_bytes: float
stat_duration: float
stat_mac_filter_rejections: float
stat_rx_bytes: float
stat_rx_crypts: float
stat_rx_dropped: float
stat_rx_errors: float
stat_rx_frags: float
stat_rx_packets: float
stat_terra2-mac_filter_rejections: float
stat_terra2-rx_bytes: float
stat_terra2-rx_crypts: float
stat_terra2-rx_dropped: float
stat_terra2-rx_errors: float
stat_terra2-rx_frags: float
stat_terra2-rx_packets: float
stat_terra2-tx_bytes: float
stat_terra2-tx_dropped: float
stat_terra2-tx_errors: float
stat_terra2-tx_packets: float
stat_terra2-tx_retries: float
stat_terra2-wifi_tx_attempts: float
stat_terra2-wifi_tx_dropped: float
stat_tx_bytes: float
stat_tx_dropped: float
stat_tx_errors: float
stat_tx_packets: float
stat_tx_retries: float
stat_user-mac_filter_rejections: float
stat_user-rx_bytes: float
stat_user-rx_crypts: float
stat_user-rx_dropped: float
stat_user-rx_errors: float
stat_user-rx_frags: float
stat_user-rx_packets: float
stat_user-terra2-mac_filter_rejections: float
stat_user-terra2-rx_bytes: float
stat_user-terra2-rx_crypts: float
stat_user-terra2-rx_dropped: float
stat_user-terra2-rx_errors: float
stat_user-terra2-rx_frags: float
stat_user-terra2-rx_packets: float
stat_user-terra2-tx_bytes: float
stat_user-terra2-tx_dropped: float
stat_user-terra2-tx_errors: float
stat_user-terra2-tx_packets: float
stat_user-terra2-tx_retries: float
stat_user-terra2-wifi_tx_attempts: float
stat_user-terra2-wifi_tx_dropped: float
stat_user-terra2-wlan0-rx_bytes: float
stat_user-terra2-wlan0-rx_errors: float
stat_user-terra2-wlan0-rx_packets: float
stat_user-terra2-wlan0-tx_bytes: float
stat_user-terra2-wlan0-tx_dropped: float
stat_user-terra2-wlan0-tx_errors: float
stat_user-terra2-wlan0-tx_packets: float
stat_user-tx_bytes: float
stat_user-tx_dropped: float
stat_user-tx_errors: float
stat_user-tx_packets: float
stat_user-tx_retries: float
stat_user-wifi0-ath0-rx_bytes: float
stat_user-wifi0-ath0-rx_packets: float
stat_user-wifi0-ath0-tx_bytes: float
stat_user-wifi0-ath0-tx_packets: float
stat_user-wifi0-mac_filter_rejections: float
stat_user-wifi0-rx_bytes: float
stat_user-wifi0-rx_crypts: float
stat_user-wifi0-rx_dropped: float
stat_user-wifi0-rx_errors: float
stat_user-wifi0-rx_frags: float
stat_user-wifi0-rx_packets: float
stat_user-wifi0-tx_bytes: float
stat_user-wifi0-tx_dropped: float
stat_user-wifi0-tx_errors: float
stat_user-wifi0-tx_packets: float
stat_user-wifi0-tx_retries: float
stat_user-wifi0-wifi_tx_attempts: float
stat_user-wifi0-wifi_tx_dropped: float
stat_user-wifi_tx_attempts: float
stat_user-wifi_tx_dropped: float
stat_wifi0-mac_filter_rejections: float
stat_wifi0-rx_bytes: float
stat_wifi0-rx_crypts: float
stat_wifi0-rx_dropped: float
stat_wifi0-rx_errors: float
stat_wifi0-rx_frags: float
stat_wifi0-rx_packets: float
stat_wifi0-tx_bytes: float
stat_wifi0-tx_dropped: float
stat_wifi0-tx_errors: float
stat_wifi0-tx_packets: float
stat_wifi0-tx_retries: float
stat_wifi0-wifi_tx_attempts: float
stat_wifi0-wifi_tx_dropped: float
stat_wifi_tx_attempts: float
stat_wifi_tx_dropped: float
state: float
system_uptime: float
temp_cpu: int
@@ -439,6 +530,7 @@ points:
uplink_max_speed: float
uplink_speed: float
uplink_uptime: float
upgradeable: bool
uptime: float
user-num_sta: float
version: string

View File

@@ -7,8 +7,10 @@ import (
// ubbT is used as a name for printed/logged counters.
const ubbT = item("UBB")
// batchUXG generates UBB datapoints for InfluxDB.
// These points can be passed directly to influx.
// batchUBB generates UBB (UniFi Building Bridge) datapoints for InfluxDB.
// UBB devices are point-to-point wireless bridges with dual radios:
// - wifi0: 5GHz radio (802.11ac)
// - terra2/wlan0/ad: 60GHz radio (802.11ad - Terragraph/WiGig)
func (u *InfluxUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
if !s.Adopted.Val || s.Locating.Val {
return
@@ -25,11 +27,6 @@ func (u *InfluxUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
"type": s.Type,
}
var sw *unifi.Bb
if s.Stat != nil {
sw = s.Stat.Bb
}
sysStats := unifi.SysStats{}
if s.SysStats != nil {
sysStats = *s.SysStats
@@ -42,6 +39,7 @@ func (u *InfluxUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
fields := Combine(
u.batchSysStats(sysStats, systemStats),
u.batchUBBstats(s.Stat),
map[string]any{
"source": s.SourceName,
"ip": s.IP,
@@ -58,53 +56,143 @@ func (u *InfluxUnifi) batchUBB(r report, s *unifi.UBB) { // nolint: funlen
"uplink_max_speed": s.Uplink.MaxSpeed.Val,
"uplink_latency": s.Uplink.Latency.Val,
"uplink_uptime": s.Uplink.Uptime.Val,
"upgradeable": s.Upgradable.Val,
},
)
// Add UBB-specific P2P and link quality metrics
if s.P2PStats != nil {
fields["p2p_rx_rate"] = s.P2PStats.RXRate.Val
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
r.addCount(ubbT)
r.send(&metric{Table: "ubb", Tags: tags, Fields: fields})
tags = map[string]string{
"mac": s.Mac,
"site_name": s.SiteName,
"source": s.SourceName,
"name": s.Name,
"version": s.Version,
"model": s.Model,
"serial": s.Serial,
"type": s.Type,
}
fields = Combine(
u.batchUBBstat(sw),
map[string]any{
"ip": s.IP,
"bytes": s.Bytes.Val,
"last_seen": s.LastSeen.Val,
"rx_bytes": s.RxBytes.Val,
"tx_bytes": s.TxBytes.Val,
"uptime": s.Uptime.Val,
})
// Export VAP table (Virtual Access Point table - wireless interface stats)
u.processVAPTable(r, tags, s.VapTable)
r.send(&metric{Table: "ubb", Tags: tags, Fields: fields})
// Export Radio tables (includes 5GHz wifi0 and 60GHz terra2/ad radios)
u.processRadTable(r, tags, s.RadioTable, s.RadioTableStats)
}
func (u *InfluxUnifi) batchUBBstat(sw *unifi.Bb) map[string]any {
if sw == nil {
// batchUBBstats generates UBB-specific statistics separated by radio.
// This includes metrics for total, wifi0 (5GHz), terra2 (60GHz), and user-specific stats.
func (u *InfluxUnifi) batchUBBstats(stat *unifi.UBBStat) map[string]any {
if stat == nil || stat.Bb == nil {
return map[string]any{}
}
bb := stat.Bb
// Total aggregated stats across both radios
return map[string]any{
"stat_bytes": sw.Bytes.Val,
"stat_rx_bytes": sw.RxBytes.Val,
"stat_rx_crypts": sw.RxCrypts.Val,
"stat_rx_dropped": sw.RxDropped.Val,
"stat_rx_errors": sw.RxErrors.Val,
"stat_rx_frags": sw.RxFrags.Val,
"stat_rx_packets": sw.TxPackets.Val,
"stat_tx_bytes": sw.TxBytes.Val,
"stat_tx_dropped": sw.TxDropped.Val,
"stat_tx_errors": sw.TxErrors.Val,
"stat_tx_packets": sw.TxPackets.Val,
"stat_tx_retries": sw.TxRetries.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-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,
// terra2 radio stats (60GHz - 802.11ad)
"stat_terra2-rx_packets": bb.Terra2RxPackets.Val,
"stat_terra2-rx_bytes": bb.Terra2RxBytes.Val,
"stat_terra2-rx_errors": bb.Terra2RxErrors.Val,
"stat_terra2-rx_dropped": bb.Terra2RxDropped.Val,
"stat_terra2-rx_crypts": bb.Terra2RxCrypts.Val,
"stat_terra2-rx_frags": bb.Terra2RxFrags.Val,
"stat_terra2-tx_packets": bb.Terra2TxPackets.Val,
"stat_terra2-tx_bytes": bb.Terra2TxBytes.Val,
"stat_terra2-tx_errors": bb.Terra2TxErrors.Val,
"stat_terra2-tx_dropped": bb.Terra2TxDropped.Val,
"stat_terra2-tx_retries": bb.Terra2TxRetries.Val,
"stat_terra2-mac_filter_rejections": bb.Terra2MacFilterRejections.Val,
"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,
// User terra2 stats (60GHz)
"stat_user-terra2-rx_packets": bb.UserTerra2RxPackets.Val,
"stat_user-terra2-rx_bytes": bb.UserTerra2RxBytes.Val,
"stat_user-terra2-rx_errors": bb.UserTerra2RxErrors.Val,
"stat_user-terra2-rx_dropped": bb.UserTerra2RxDropped.Val,
"stat_user-terra2-rx_crypts": bb.UserTerra2RxCrypts.Val,
"stat_user-terra2-rx_frags": bb.UserTerra2RxFrags.Val,
"stat_user-terra2-tx_packets": bb.UserTerra2TxPackets.Val,
"stat_user-terra2-tx_bytes": bb.UserTerra2TxBytes.Val,
"stat_user-terra2-tx_errors": bb.UserTerra2TxErrors.Val,
"stat_user-terra2-tx_dropped": bb.UserTerra2TxDropped.Val,
"stat_user-terra2-tx_retries": bb.UserTerra2TxRetries.Val,
"stat_user-terra2-mac_filter_rejections": bb.UserTerra2MacFilterRejections.Val,
"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-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,
"stat_user-terra2-wlan0-tx_bytes": bb.UserTerra2Wlan0TxBytes.Val,
"stat_user-terra2-wlan0-tx_dropped": bb.UserTerra2Wlan0TxDropped.Val,
"stat_user-terra2-wlan0-rx_errors": bb.UserTerra2Wlan0RxErrors.Val,
"stat_user-terra2-wlan0-tx_errors": bb.UserTerra2Wlan0TxErrors.Val,
}
}