Merge pull request #894 from unpoller/enhance-ubb-support-409

Enhance ubb support 409
This commit is contained in:
Cody Lee 2025-12-09 11:14:26 -06:00 committed by GitHub
commit 9b5dbef869
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 608 additions and 114 deletions

14
go.mod
View File

@ -1,8 +1,6 @@
module github.com/unpoller/unpoller
go 1.24.0
toolchain go1.24.2
go 1.25.5
require (
github.com/DataDog/datadog-go/v5 v5.8.1
@ -13,9 +11,9 @@ require (
github.com/prometheus/common v0.67.4
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
github.com/unpoller/unifi/v5 v5.2.0
golang.org/x/crypto v0.45.0
golang.org/x/term v0.37.0
github.com/unpoller/unifi/v5 v5.2.1
golang.org/x/crypto v0.46.0
golang.org/x/term v0.38.0
golift.io/cnfg v0.2.3
golift.io/cnfgfile v0.0.0-20240713024420-a5436d84eb48
golift.io/version v0.0.2
@ -24,7 +22,7 @@ require (
require (
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/net v0.48.0 // indirect
)
require (
@ -44,7 +42,7 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/sys v0.39.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
)

20
go.sum
View File

@ -75,8 +75,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/unpoller/unifi/v5 v5.2.0 h1:qw0fWRHjzabfYSXxV1ViJeRL+L6oILSBMqPcZyLzmO4=
github.com/unpoller/unifi/v5 v5.2.0/go.mod h1:zQwa4J4qM0ybv9EO51jHt78GsJdS2ySLzy8b5IHUQaY=
github.com/unpoller/unifi/v5 v5.2.1 h1:clcF0/UKYQm4ycWlM0Pe6f+NbmGGpky3KkfuGBBmsR0=
github.com/unpoller/unifi/v5 v5.2.1/go.mod h1:a9Hl1hBnDuaJDIvHswpW8/QUQgk3gQ5U9c5EnpZXMUg=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
@ -84,14 +84,14 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -101,11 +101,11 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

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,
}
}

View File

@ -4,33 +4,164 @@ import (
"github.com/unpoller/unifi/v5"
)
// exportUBB is a collection of stats from UBB.
// exportUBB is a collection of stats from UBB (UniFi Building Bridge).
// 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 *promUnifi) exportUBB(r report, d *unifi.UBB) {
if !d.Adopted.Val || d.Locating.Val {
return
}
//var sw *unifi.Bb
//if d.Stat != nil {
// sw = d.Stat.Bb
//}
// unsure of what to do with this yet.
labels := []string{d.Type, d.SiteName, d.Name, d.SourceName}
infoLabels := []string{d.Version, d.Model, d.Serial, d.Mac, d.IP, d.ID}
// Shared data (all devices do this).
// Export UBB-specific stats if available
u.exportUBBstats(r, labels, d.Stat)
// Export VAP table (Virtual Access Point table - wireless interface stats)
u.exportVAPtable(r, labels, d.VapTable)
// Export Radio tables (includes 5GHz wifi0 and 60GHz terra2/ad radios)
u.exportRADtable(r, labels, d.RadioTable, d.RadioTableStats)
// Shared device stats
u.exportBYTstats(r, labels, d.TxBytes, d.RxBytes)
if d.SysStats != nil && d.SystemStats != nil {
u.exportSYSstats(r, labels, *d.SysStats, *d.SystemStats)
}
// Dream Machine System Data.
// Device info, uptime, and temperature
r.send([]*metric{
{u.Device.Info, gauge, 1.0, append(labels, infoLabels...)},
{u.Device.Uptime, gauge, d.Uptime, labels},
{u.Device.Temperature, gauge, d.GeneralTemperature.Val, append(labels, d.Name, "general")},
})
// temperature
r.send([]*metric{{u.Device.Temperature, gauge, d.GeneralTemperature.Val, append(labels, d.Name, "general")}})
// UBB-specific metrics
if d.P2PStats != nil {
u.exportP2Pstats(r, labels, d.P2PStats)
}
// Link quality metrics for point-to-point links
r.send([]*metric{
{u.Device.Counter, gauge, d.LinkQuality.Val, append(labels, "link_quality")},
{u.Device.Counter, gauge, d.LinkQualityCurrent.Val, append(labels, "link_quality_current")},
{u.Device.Counter, gauge, d.LinkCapacity.Val, append(labels, "link_capacity")},
})
}
// exportUBBstats exports UBB-specific stats from the Bb structure.
// This includes separate metrics for wifi0 (5GHz) and terra2 (60GHz) radios.
func (u *promUnifi) exportUBBstats(r report, labels []string, stat *unifi.UBBStat) {
if stat == nil || stat.Bb == nil {
return
}
bb := stat.Bb
// Export aggregated stats (total across both radios)
labelTotal := append([]string{"total"}, labels[1:]...)
r.send([]*metric{
{u.UAP.ApRxPackets, counter, bb.RxPackets, labelTotal},
{u.UAP.ApRxBytes, counter, bb.RxBytes, labelTotal},
{u.UAP.ApRxErrors, counter, bb.RxErrors, labelTotal},
{u.UAP.ApRxDropped, counter, bb.RxDropped, labelTotal},
{u.UAP.ApRxCrypts, counter, bb.RxCrypts, labelTotal},
{u.UAP.ApRxFrags, counter, bb.RxFrags, labelTotal},
{u.UAP.ApTxPackets, counter, bb.TxPackets, labelTotal},
{u.UAP.ApTxBytes, counter, bb.TxBytes, labelTotal},
{u.UAP.ApTxErrors, counter, bb.TxErrors, labelTotal},
{u.UAP.ApTxDropped, counter, bb.TxDropped, labelTotal},
{u.UAP.ApTxRetries, counter, bb.TxRetries, labelTotal},
{u.UAP.WifiTxAttempts, counter, bb.WifiTxAttempts, labelTotal},
{u.UAP.MacFilterRejections, counter, bb.MacFilterRejections, labelTotal},
{u.UAP.ApWifiTxDropped, counter, bb.WifiTxDropped, labelTotal},
})
// Export wifi0 radio stats (5GHz)
labelWifi0 := append([]string{"wifi0"}, labels[1:]...)
r.send([]*metric{
{u.UAP.ApRxPackets, counter, bb.Wifi0RxPackets, labelWifi0},
{u.UAP.ApRxBytes, counter, bb.Wifi0RxBytes, labelWifi0},
{u.UAP.ApRxErrors, counter, bb.Wifi0RxErrors, labelWifi0},
{u.UAP.ApRxDropped, counter, bb.Wifi0RxDropped, labelWifi0},
{u.UAP.ApRxCrypts, counter, bb.Wifi0RxCrypts, labelWifi0},
{u.UAP.ApRxFrags, counter, bb.Wifi0RxFrags, labelWifi0},
{u.UAP.ApTxPackets, counter, bb.Wifi0TxPackets, labelWifi0},
{u.UAP.ApTxBytes, counter, bb.Wifi0TxBytes, labelWifi0},
{u.UAP.ApTxErrors, counter, bb.Wifi0TxErrors, labelWifi0},
{u.UAP.ApTxDropped, counter, bb.Wifi0TxDropped, labelWifi0},
{u.UAP.ApTxRetries, counter, bb.Wifi0TxRetries, labelWifi0},
{u.UAP.WifiTxAttempts, counter, bb.Wifi0WifiTxAttempts, labelWifi0},
{u.UAP.MacFilterRejections, counter, bb.Wifi0MacFilterRejections, labelWifi0},
{u.UAP.ApWifiTxDropped, counter, bb.Wifi0WifiTxDropped, labelWifi0},
})
// Export terra2 radio stats (60GHz - 802.11ad)
labelTerra2 := append([]string{"terra2"}, labels[1:]...)
r.send([]*metric{
{u.UAP.ApRxPackets, counter, bb.Terra2RxPackets, labelTerra2},
{u.UAP.ApRxBytes, counter, bb.Terra2RxBytes, labelTerra2},
{u.UAP.ApRxErrors, counter, bb.Terra2RxErrors, labelTerra2},
{u.UAP.ApRxDropped, counter, bb.Terra2RxDropped, labelTerra2},
{u.UAP.ApRxCrypts, counter, bb.Terra2RxCrypts, labelTerra2},
{u.UAP.ApRxFrags, counter, bb.Terra2RxFrags, labelTerra2},
{u.UAP.ApTxPackets, counter, bb.Terra2TxPackets, labelTerra2},
{u.UAP.ApTxBytes, counter, bb.Terra2TxBytes, labelTerra2},
{u.UAP.ApTxErrors, counter, bb.Terra2TxErrors, labelTerra2},
{u.UAP.ApTxDropped, counter, bb.Terra2TxDropped, labelTerra2},
{u.UAP.ApTxRetries, counter, bb.Terra2TxRetries, labelTerra2},
{u.UAP.WifiTxAttempts, counter, bb.Terra2WifiTxAttempts, labelTerra2},
{u.UAP.MacFilterRejections, counter, bb.Terra2MacFilterRejections, labelTerra2},
{u.UAP.ApWifiTxDropped, counter, bb.Terra2WifiTxDropped, labelTerra2},
})
// Export user stats for wifi0
labelUserWifi0 := append([]string{"user-wifi0"}, labels[1:]...)
r.send([]*metric{
{u.UAP.ApRxPackets, counter, bb.UserWifi0RxPackets, labelUserWifi0},
{u.UAP.ApRxBytes, counter, bb.UserWifi0RxBytes, labelUserWifi0},
{u.UAP.ApRxErrors, counter, bb.UserWifi0RxErrors, labelUserWifi0},
{u.UAP.ApRxDropped, counter, bb.UserWifi0RxDropped, labelUserWifi0},
{u.UAP.ApRxCrypts, counter, bb.UserWifi0RxCrypts, labelUserWifi0},
{u.UAP.ApRxFrags, counter, bb.UserWifi0RxFrags, labelUserWifi0},
{u.UAP.ApTxPackets, counter, bb.UserWifi0TxPackets, labelUserWifi0},
{u.UAP.ApTxBytes, counter, bb.UserWifi0TxBytes, labelUserWifi0},
{u.UAP.ApTxErrors, counter, bb.UserWifi0TxErrors, labelUserWifi0},
{u.UAP.ApTxDropped, counter, bb.UserWifi0TxDropped, labelUserWifi0},
{u.UAP.ApTxRetries, counter, bb.UserWifi0TxRetries, labelUserWifi0},
{u.UAP.WifiTxAttempts, counter, bb.UserWifi0WifiTxAttempts, labelUserWifi0},
{u.UAP.MacFilterRejections, counter, bb.UserWifi0MacFilterRejections, labelUserWifi0},
{u.UAP.ApWifiTxDropped, counter, bb.UserWifi0WifiTxDropped, labelUserWifi0},
})
// Export user stats for terra2 (60GHz)
labelUserTerra2 := append([]string{"user-terra2"}, labels[1:]...)
r.send([]*metric{
{u.UAP.ApRxPackets, counter, bb.UserTerra2RxPackets, labelUserTerra2},
{u.UAP.ApRxBytes, counter, bb.UserTerra2RxBytes, labelUserTerra2},
{u.UAP.ApRxErrors, counter, bb.UserTerra2RxErrors, labelUserTerra2},
{u.UAP.ApRxDropped, counter, bb.UserTerra2RxDropped, labelUserTerra2},
{u.UAP.ApRxCrypts, counter, bb.UserTerra2RxCrypts, labelUserTerra2},
{u.UAP.ApRxFrags, counter, bb.UserTerra2RxFrags, labelUserTerra2},
{u.UAP.ApTxPackets, counter, bb.UserTerra2TxPackets, labelUserTerra2},
{u.UAP.ApTxBytes, counter, bb.UserTerra2TxBytes, labelUserTerra2},
{u.UAP.ApTxErrors, counter, bb.UserTerra2TxErrors, labelUserTerra2},
{u.UAP.ApTxDropped, counter, bb.UserTerra2TxDropped, labelUserTerra2},
{u.UAP.ApTxRetries, counter, bb.UserTerra2TxRetries, labelUserTerra2},
{u.UAP.WifiTxAttempts, counter, bb.UserTerra2WifiTxAttempts, labelUserTerra2},
{u.UAP.MacFilterRejections, counter, bb.UserTerra2MacFilterRejections, labelUserTerra2},
{u.UAP.ApWifiTxDropped, counter, bb.UserTerra2WifiTxDropped, labelUserTerra2},
})
}
// exportP2Pstats exports point-to-point link statistics for UBB devices.
func (u *promUnifi) exportP2Pstats(r report, labels []string, p2p *unifi.P2PStats) {
r.send([]*metric{
{u.Device.Counter, gauge, p2p.RXRate.Val, append(labels, "p2p_rx_rate")},
{u.Device.Counter, gauge, p2p.TXRate.Val, append(labels, "p2p_tx_rate")},
{u.Device.Counter, gauge, p2p.Throughput.Val, append(labels, "p2p_throughput")},
})
}