mirror of
https://github.com/unpoller/unpoller.git
synced 2026-04-05 00:44:09 -04:00
feat(devices): add UDB (UniFi Device Bridge) support (#968)
Adds metrics export for UDB devices (UDB-Switch, UDB-Pro, UDB-Pro-Sector) to all output backends. UDB-Switch is a hybrid device combining PoE switch ports with WiFi 7 wireless bridge capability (5GHz + 6GHz radios). - pkg/promunifi/udb.go: Prometheus metrics exporter for UDB - pkg/influxunifi/udb.go: InfluxDB batch exporter for UDB - pkg/datadogunifi/udb.go: Datadog batch exporter for UDB - Wire UDB into switchExport in all three output plugins - Add UDB to inputunifi device collection and site name override - Update integration test expectations for InfluxDB and Datadog - Fix addUBB() bug: was incorrectly incrementing UCI counter Resolves #947 Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -343,6 +343,8 @@ func (u *DatadogUnifi) switchExport(r report, v any) { //nolint:cyclop
|
|||||||
u.batchUBB(r, v)
|
u.batchUBB(r, v)
|
||||||
case *unifi.UCI:
|
case *unifi.UCI:
|
||||||
u.batchUCI(r, v)
|
u.batchUCI(r, v)
|
||||||
|
case *unifi.UDB:
|
||||||
|
u.batchUDB(r, v)
|
||||||
case *unifi.Site:
|
case *unifi.Site:
|
||||||
u.reportSite(r, v)
|
u.reportSite(r, v)
|
||||||
case *unifi.Client:
|
case *unifi.Client:
|
||||||
|
|||||||
@@ -507,6 +507,51 @@ gauges:
|
|||||||
- unifi.uci.stat_rx_packets
|
- unifi.uci.stat_rx_packets
|
||||||
- unifi.uci.stat_tx_dropped
|
- unifi.uci.stat_tx_dropped
|
||||||
- unifi.uci.state
|
- unifi.uci.state
|
||||||
|
- unifi.udb.bytes
|
||||||
|
- unifi.udb.cpu
|
||||||
|
- unifi.udb.fan_level
|
||||||
|
- unifi.udb.general_temperature
|
||||||
|
- unifi.udb.guest_num_sta
|
||||||
|
- unifi.udb.guest_wlan_num_sta
|
||||||
|
- unifi.udb.last_seen
|
||||||
|
- unifi.udb.loadavg_1
|
||||||
|
- unifi.udb.loadavg_5
|
||||||
|
- unifi.udb.loadavg_15
|
||||||
|
- unifi.udb.mem
|
||||||
|
- unifi.udb.mem_buffer
|
||||||
|
- unifi.udb.mem_total
|
||||||
|
- unifi.udb.mem_used
|
||||||
|
- unifi.udb.memory
|
||||||
|
- unifi.udb.network
|
||||||
|
- unifi.udb.num_sta
|
||||||
|
- unifi.udb.probe
|
||||||
|
- unifi.udb.rx_bytes
|
||||||
|
- unifi.udb.satisfaction
|
||||||
|
- unifi.udb.stat_bytes
|
||||||
|
- unifi.udb.stat_rx_bytes
|
||||||
|
- unifi.udb.stat_rx_crypts
|
||||||
|
- unifi.udb.stat_rx_dropped
|
||||||
|
- unifi.udb.stat_rx_errors
|
||||||
|
- unifi.udb.stat_rx_frags
|
||||||
|
- unifi.udb.stat_rx_packets
|
||||||
|
- unifi.udb.stat_tx_bytes
|
||||||
|
- unifi.udb.stat_tx_dropped
|
||||||
|
- unifi.udb.stat_tx_errors
|
||||||
|
- unifi.udb.stat_tx_packets
|
||||||
|
- unifi.udb.stat_tx_retries
|
||||||
|
- unifi.udb.state
|
||||||
|
- unifi.udb.sys
|
||||||
|
- unifi.udb.system_uptime
|
||||||
|
- unifi.udb.total_max_power
|
||||||
|
- unifi.udb.tx_bytes
|
||||||
|
- unifi.udb.upgradeable
|
||||||
|
- unifi.udb.uplink_latency
|
||||||
|
- unifi.udb.uplink_max_speed
|
||||||
|
- unifi.udb.uplink_speed
|
||||||
|
- unifi.udb.uplink_uptime
|
||||||
|
- unifi.udb.uptime
|
||||||
|
- unifi.udb.user_num_sta
|
||||||
|
- unifi.udb.user_wlan_num_sta
|
||||||
counts:
|
counts:
|
||||||
- unifi.collector.num_devices
|
- unifi.collector.num_devices
|
||||||
- unifi.collector.num_errors
|
- unifi.collector.num_errors
|
||||||
|
|||||||
68
pkg/datadogunifi/udb.go
Normal file
68
pkg/datadogunifi/udb.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package datadogunifi
|
||||||
|
|
||||||
|
import "github.com/unpoller/unifi/v5"
|
||||||
|
|
||||||
|
// udbT is used as a name for printed/logged counters.
|
||||||
|
const udbT = item("UDB")
|
||||||
|
|
||||||
|
// batchUDB generates datapoints for UDB (UniFi Device Bridge) devices.
|
||||||
|
// UDB-Switch is a hybrid device combining switch ports with WiFi 7
|
||||||
|
// wireless bridge capability.
|
||||||
|
func (u *DatadogUnifi) batchUDB(r report, s *unifi.UDB) {
|
||||||
|
if !s.Adopted.Val || s.Locating.Val {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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.batchUSWstat(s.Stat.Sw),
|
||||||
|
u.batchSysStats(s.SysStats, s.SystemStats),
|
||||||
|
map[string]float64{
|
||||||
|
"guest_num_sta": s.GuestNumSta.Val,
|
||||||
|
"bytes": s.Bytes.Val,
|
||||||
|
"fan_level": s.FanLevel.Val,
|
||||||
|
"general_temperature": s.GeneralTemperature.Val,
|
||||||
|
"last_seen": s.LastSeen.Val,
|
||||||
|
"rx_bytes": s.RxBytes.Val,
|
||||||
|
"tx_bytes": s.TxBytes.Val,
|
||||||
|
"uptime": s.Uptime.Val,
|
||||||
|
"state": s.State.Val,
|
||||||
|
"user_num_sta": s.UserNumSta.Val,
|
||||||
|
"num_sta": s.NumSta.Val,
|
||||||
|
"upgradeable": boolToFloat64(s.Upgradable.Val),
|
||||||
|
"guest_wlan_num_sta": s.GuestWlanNumSta.Val,
|
||||||
|
"user_wlan_num_sta": s.UserWlanNumSta.Val,
|
||||||
|
"satisfaction": s.Satisfaction.Val,
|
||||||
|
"total_max_power": s.TotalMaxPower.Val,
|
||||||
|
"uplink_speed": s.Uplink.Speed.Val,
|
||||||
|
"uplink_max_speed": s.Uplink.MaxSpeed.Val,
|
||||||
|
"uplink_latency": s.Uplink.Latency.Val,
|
||||||
|
"uplink_uptime": s.Uplink.Uptime.Val,
|
||||||
|
})
|
||||||
|
|
||||||
|
r.addCount(udbT)
|
||||||
|
|
||||||
|
metricName := metricNamespace("udb")
|
||||||
|
|
||||||
|
reportGaugeForFloat64Map(r, metricName, data, tags)
|
||||||
|
|
||||||
|
// Port table (reuse USW function)
|
||||||
|
u.batchPortTable(r, tags, s.PortTable)
|
||||||
|
|
||||||
|
// Radio table (reuse UAP functions)
|
||||||
|
u.processRadTable(r, tags, s.RadioTable, s.RadioTableStats)
|
||||||
|
|
||||||
|
// VAP table (reuse UAP function)
|
||||||
|
u.processVAPTable(r, tags, s.VapTable)
|
||||||
|
}
|
||||||
@@ -454,6 +454,8 @@ func (u *InfluxUnifi) switchExport(r report, v any) { //nolint:cyclop
|
|||||||
u.batchUBB(r, v)
|
u.batchUBB(r, v)
|
||||||
case *unifi.UCI:
|
case *unifi.UCI:
|
||||||
u.batchUCI(r, v)
|
u.batchUCI(r, v)
|
||||||
|
case *unifi.UDB:
|
||||||
|
u.batchUDB(r, v)
|
||||||
case *unifi.UDM:
|
case *unifi.UDM:
|
||||||
u.batchUDM(r, v)
|
u.batchUDM(r, v)
|
||||||
case *unifi.Site:
|
case *unifi.Site:
|
||||||
|
|||||||
@@ -581,6 +581,64 @@ points:
|
|||||||
tx_bytes: float
|
tx_bytes: float
|
||||||
uptime: float
|
uptime: float
|
||||||
version: string
|
version: string
|
||||||
|
udb:
|
||||||
|
tags:
|
||||||
|
- mac
|
||||||
|
- model
|
||||||
|
- name
|
||||||
|
- serial
|
||||||
|
- site_name
|
||||||
|
- source
|
||||||
|
- type
|
||||||
|
- version
|
||||||
|
fields:
|
||||||
|
bytes: float
|
||||||
|
cpu: float
|
||||||
|
fan_level: float
|
||||||
|
general_temperature: float
|
||||||
|
guest-num_sta: float
|
||||||
|
guest-wlan-num_sta: float
|
||||||
|
ip: string
|
||||||
|
last_seen: float
|
||||||
|
loadavg_1: float
|
||||||
|
loadavg_5: float
|
||||||
|
loadavg_15: float
|
||||||
|
mem: float
|
||||||
|
mem_buffer: float
|
||||||
|
mem_total: float
|
||||||
|
mem_used: float
|
||||||
|
num_sta: float
|
||||||
|
rx_bytes: float
|
||||||
|
satisfaction: float
|
||||||
|
stat_bytes: 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_tx_bytes: float
|
||||||
|
stat_tx_dropped: float
|
||||||
|
stat_tx_errors: float
|
||||||
|
stat_tx_packets: float
|
||||||
|
stat_tx_retries: float
|
||||||
|
state: float
|
||||||
|
system_uptime: float
|
||||||
|
temp_cpu: float
|
||||||
|
temp_memory: float
|
||||||
|
temp_network: float
|
||||||
|
temp_probe: float
|
||||||
|
temp_sys: float
|
||||||
|
total_max_power: float
|
||||||
|
tx_bytes: float
|
||||||
|
upgradeable: bool
|
||||||
|
uplink_latency: float
|
||||||
|
uplink_max_speed: float
|
||||||
|
uplink_speed: float
|
||||||
|
uplink_uptime: float
|
||||||
|
uptime: float
|
||||||
|
user-num_sta: float
|
||||||
|
user-wlan-num_sta: float
|
||||||
unifi_alarm:
|
unifi_alarm:
|
||||||
tags:
|
tags:
|
||||||
- action
|
- action
|
||||||
|
|||||||
65
pkg/influxunifi/udb.go
Normal file
65
pkg/influxunifi/udb.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package influxunifi
|
||||||
|
|
||||||
|
import "github.com/unpoller/unifi/v5"
|
||||||
|
|
||||||
|
// udbT is used as a name for printed/logged counters.
|
||||||
|
const udbT = item("UDB")
|
||||||
|
|
||||||
|
// batchUDB generates datapoints for UDB (UniFi Device Bridge) devices.
|
||||||
|
// UDB-Switch is a hybrid device combining switch ports with WiFi 7
|
||||||
|
// wireless bridge capability.
|
||||||
|
func (u *InfluxUnifi) batchUDB(r report, s *unifi.UDB) {
|
||||||
|
if !s.Adopted.Val || s.Locating.Val {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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.batchUSWstat(s.Stat.Sw),
|
||||||
|
u.batchSysStats(s.SysStats, s.SystemStats),
|
||||||
|
map[string]any{
|
||||||
|
"guest-num_sta": s.GuestNumSta.Val,
|
||||||
|
"ip": s.IP,
|
||||||
|
"bytes": s.Bytes.Val,
|
||||||
|
"fan_level": s.FanLevel.Val,
|
||||||
|
"general_temperature": s.GeneralTemperature.Val,
|
||||||
|
"last_seen": s.LastSeen.Val,
|
||||||
|
"rx_bytes": s.RxBytes.Val,
|
||||||
|
"tx_bytes": s.TxBytes.Val,
|
||||||
|
"uptime": s.Uptime.Val,
|
||||||
|
"state": s.State.Val,
|
||||||
|
"user-num_sta": s.UserNumSta.Val,
|
||||||
|
"num_sta": s.NumSta.Val,
|
||||||
|
"upgradeable": s.Upgradable.Val,
|
||||||
|
"guest-wlan-num_sta": s.GuestWlanNumSta.Val,
|
||||||
|
"user-wlan-num_sta": s.UserWlanNumSta.Val,
|
||||||
|
"satisfaction": s.Satisfaction.Val,
|
||||||
|
"total_max_power": s.TotalMaxPower.Val,
|
||||||
|
"uplink_speed": s.Uplink.Speed.Val,
|
||||||
|
"uplink_max_speed": s.Uplink.MaxSpeed.Val,
|
||||||
|
"uplink_latency": s.Uplink.Latency.Val,
|
||||||
|
"uplink_uptime": s.Uplink.Uptime.Val,
|
||||||
|
})
|
||||||
|
|
||||||
|
r.addCount(udbT)
|
||||||
|
r.send(&metric{Table: "udb", Tags: tags, Fields: fields})
|
||||||
|
|
||||||
|
// Port table (reuse USW function)
|
||||||
|
u.batchPortTable(r, tags, s.PortTable)
|
||||||
|
|
||||||
|
// Radio table (reuse UAP functions)
|
||||||
|
u.processRadTable(r, tags, s.RadioTable, s.RadioTableStats)
|
||||||
|
|
||||||
|
// VAP table (reuse UAP function)
|
||||||
|
u.processVAPTable(r, tags, s.VapTable)
|
||||||
|
}
|
||||||
@@ -174,10 +174,10 @@ func (u *InputUnifi) pollController(c *Controller) (*poller.Metrics, error) {
|
|||||||
return nil, fmt.Errorf("unifi.GetDevices(%s): %w", c.URL, err)
|
return nil, fmt.Errorf("unifi.GetDevices(%s): %w", c.URL, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
u.LogDebugf("Found %d UBB, %d UXG, %d PDU, %d UCI, %d UAP %d USG %d USW %d UDM devices",
|
u.LogDebugf("Found %d UBB, %d UXG, %d PDU, %d UCI, %d UDB, %d UAP %d USG %d USW %d UDM devices",
|
||||||
len(m.Devices.UBBs), len(m.Devices.UXGs),
|
len(m.Devices.UBBs), len(m.Devices.UXGs),
|
||||||
len(m.Devices.PDUs), len(m.Devices.UCIs),
|
len(m.Devices.PDUs), len(m.Devices.UCIs),
|
||||||
len(m.Devices.UAPs), len(m.Devices.USGs),
|
len(m.Devices.UDBs), len(m.Devices.UAPs), len(m.Devices.USGs),
|
||||||
len(m.Devices.USWs), len(m.Devices.UDMs))
|
len(m.Devices.USWs), len(m.Devices.UDMs))
|
||||||
|
|
||||||
// Get speed test results for all WANs
|
// Get speed test results for all WANs
|
||||||
@@ -486,6 +486,10 @@ func applySiteNameOverride(m *poller.Metrics, overrideName string) {
|
|||||||
if isDefaultSiteName(d.SiteName) {
|
if isDefaultSiteName(d.SiteName) {
|
||||||
d.SiteName = overrideName
|
d.SiteName = overrideName
|
||||||
}
|
}
|
||||||
|
case *unifi.UDB:
|
||||||
|
if isDefaultSiteName(d.SiteName) {
|
||||||
|
d.SiteName = overrideName
|
||||||
|
}
|
||||||
case *unifi.PDU:
|
case *unifi.PDU:
|
||||||
if isDefaultSiteName(d.SiteName) {
|
if isDefaultSiteName(d.SiteName) {
|
||||||
d.SiteName = overrideName
|
d.SiteName = overrideName
|
||||||
@@ -595,6 +599,15 @@ func extractDevices(metrics *Metrics) (*poller.Metrics, map[string]string, map[s
|
|||||||
m.Devices = append(m.Devices, r)
|
m.Devices = append(m.Devices, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, r := range metrics.Devices.UDBs {
|
||||||
|
devices[r.Mac] = r.Name
|
||||||
|
m.Devices = append(m.Devices, r)
|
||||||
|
|
||||||
|
for _, v := range r.VapTable {
|
||||||
|
bssdIDs[v.Bssid] = fmt.Sprintf("%s %s %s:", r.Name, v.Radio, v.RadioName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, r := range metrics.Devices.PDUs {
|
for _, r := range metrics.Devices.PDUs {
|
||||||
devices[r.Mac] = r.Name
|
devices[r.Mac] = r.Name
|
||||||
m.Devices = append(m.Devices, r)
|
m.Devices = append(m.Devices, r)
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ type Report struct {
|
|||||||
UXG int // Total count of UXG devices.
|
UXG int // Total count of UXG devices.
|
||||||
UBB int // Total count of UBB devices.
|
UBB int // Total count of UBB devices.
|
||||||
UCI int // Total count of UCI devices.
|
UCI int // Total count of UCI devices.
|
||||||
|
UDB int // Total count of UDB devices.
|
||||||
Metrics *poller.Metrics // Metrics collected and recorded.
|
Metrics *poller.Metrics // Metrics collected and recorded.
|
||||||
Elapsed time.Duration // Duration elapsed collecting and exporting.
|
Elapsed time.Duration // Duration elapsed collecting and exporting.
|
||||||
Fetch time.Duration // Duration elapsed making controller requests.
|
Fetch time.Duration // Duration elapsed making controller requests.
|
||||||
@@ -479,6 +480,9 @@ func (u *promUnifi) switchExport(r report, v any) {
|
|||||||
case *unifi.UCI:
|
case *unifi.UCI:
|
||||||
r.addUCI()
|
r.addUCI()
|
||||||
u.exportUCI(r, v)
|
u.exportUCI(r, v)
|
||||||
|
case *unifi.UDB:
|
||||||
|
r.addUDB()
|
||||||
|
u.exportUDB(r, v)
|
||||||
case *unifi.UDM:
|
case *unifi.UDM:
|
||||||
r.addUDM()
|
r.addUDM()
|
||||||
u.exportUDM(r, v)
|
u.exportUDM(r, v)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type report interface {
|
|||||||
addUXG()
|
addUXG()
|
||||||
addUBB()
|
addUBB()
|
||||||
addUCI()
|
addUCI()
|
||||||
|
addUDB()
|
||||||
addUSG()
|
addUSG()
|
||||||
addUAP()
|
addUAP()
|
||||||
addUSW()
|
addUSW()
|
||||||
@@ -111,13 +112,17 @@ func (r *Report) addUXG() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Report) addUBB() {
|
func (r *Report) addUBB() {
|
||||||
r.UCI++
|
r.UBB++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Report) addUCI() {
|
func (r *Report) addUCI() {
|
||||||
r.UCI++
|
r.UCI++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Report) addUDB() {
|
||||||
|
r.UDB++
|
||||||
|
}
|
||||||
|
|
||||||
// close is not part of the interface.
|
// close is not part of the interface.
|
||||||
func (r *Report) close() {
|
func (r *Report) close() {
|
||||||
r.wg.Wait()
|
r.wg.Wait()
|
||||||
|
|||||||
53
pkg/promunifi/udb.go
Normal file
53
pkg/promunifi/udb.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package promunifi
|
||||||
|
|
||||||
|
import "github.com/unpoller/unifi/v5"
|
||||||
|
|
||||||
|
// exportUDB exports metrics for UDB (UniFi Device Bridge) devices.
|
||||||
|
// The UDB range includes UDB-Switch, UDB-Pro, UDB-Pro-Sector.
|
||||||
|
// UDB-Switch is a hybrid device combining switch ports (8 PoE ports)
|
||||||
|
// with WiFi 7 wireless bridge capability (5GHz + 6GHz radios).
|
||||||
|
func (u *promUnifi) exportUDB(r report, d *unifi.UDB) {
|
||||||
|
if !d.Adopted.Val || d.Locating.Val {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
baseLabels := []string{d.Type, d.SiteName, d.Name, d.SourceName}
|
||||||
|
baseInfoLabels := []string{d.Version, d.Model, d.Serial, d.Mac, d.IP, d.ID}
|
||||||
|
|
||||||
|
u.exportWithTags(r, d.Tags, func(tagLabels []string) {
|
||||||
|
tag := tagLabels[0]
|
||||||
|
labels := append(baseLabels, tag)
|
||||||
|
infoLabels := append(baseInfoLabels, tag)
|
||||||
|
|
||||||
|
// Export switch stats (reuse USW functions)
|
||||||
|
u.exportUSWstats(r, labels, d.Stat.Sw)
|
||||||
|
u.exportPRTtable(r, labels, d.PortTable)
|
||||||
|
|
||||||
|
// Export wireless stats (reuse UAP functions)
|
||||||
|
u.exportVAPtable(r, labels, d.VapTable)
|
||||||
|
u.exportRADtable(r, labels, d.RadioTable, d.RadioTableStats)
|
||||||
|
|
||||||
|
// Common device stats
|
||||||
|
u.exportBYTstats(r, labels, d.TxBytes, d.RxBytes)
|
||||||
|
u.exportSYSstats(r, labels, d.SysStats, d.SystemStats)
|
||||||
|
u.exportSTAcount(r, labels, d.UserNumSta, d.GuestNumSta)
|
||||||
|
|
||||||
|
r.send([]*metric{
|
||||||
|
{u.Device.Info, gauge, 1.0, append(baseLabels, infoLabels...)},
|
||||||
|
{u.Device.Uptime, gauge, d.Uptime, labels},
|
||||||
|
{u.Device.Upgradeable, gauge, d.Upgradable.Val, labels},
|
||||||
|
})
|
||||||
|
|
||||||
|
if d.HasTemperature.Val {
|
||||||
|
r.send([]*metric{{u.Device.Temperature, gauge, d.GeneralTemperature, append(labels, "general", "board")}})
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasFan.Val {
|
||||||
|
r.send([]*metric{{u.Device.FanLevel, gauge, d.FanLevel, labels}})
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.TotalMaxPower.Txt != "" {
|
||||||
|
r.send([]*metric{{u.Device.TotalMaxPower, gauge, d.TotalMaxPower, labels}})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user