Add device tag support to Prometheus metrics

- Add 'tag' label to all device metric descriptors
- Update exportWithTags helper to create separate metric series per tag
- Update all device export functions (UAP, USW, UDM, USG, UXG, PDU, UBB, UCI) to include tags
- Update all label arrays (VAP, Radio, Port, etc.) to include tag label
- Devices with multiple tags create multiple metric series (one per tag)
- Devices without tags export with tag=""

Requires unpoller/unifi#92
This commit is contained in:
brngates98
2026-01-28 20:48:10 -05:00
parent 2a44b2f0be
commit 6d85ea76ab
14 changed files with 462 additions and 245 deletions

View File

@@ -64,14 +64,14 @@ func descPDU(ns string) *pdu {
outlet := ns + "outlet_"
pns := ns + "port_"
sfp := pns + "sfp_"
labelS := []string{"site_name", "name", "source"}
labelP := []string{"port_id", "port_num", "port_name", "port_mac", "port_ip", "site_name", "name", "source"}
labelS := []string{"site_name", "name", "source", "tag"}
labelP := []string{"port_id", "port_num", "port_name", "port_mac", "port_ip", "site_name", "name", "source", "tag"}
labelF := []string{
"sfp_part", "sfp_vendor", "sfp_serial", "sfp_compliance",
"port_id", "port_num", "port_name", "port_mac", "port_ip", "site_name", "name", "source",
"port_id", "port_num", "port_name", "port_mac", "port_ip", "site_name", "name", "source", "tag",
}
labelO := []string{
"outlet_description", "outlet_index", "outlet_name", "site_name", "name", "source",
"outlet_description", "outlet_index", "outlet_name", "site_name", "name", "source", "tag",
}
nd := prometheus.NewDesc
@@ -136,33 +136,39 @@ func (u *promUnifi) exportPDU(r report, d *unifi.PDU) {
return
}
labels := []string{d.Type, d.SiteName, d.Name, d.SourceName}
infoLabels := []string{d.Version, d.Model, d.Serial, d.Mac, d.IP, d.ID}
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.exportPDUstats(r, labels, d.Stat.Sw)
u.exportPDUPrtTable(r, labels, d.PortTable)
u.exportPDUOutletTable(r, labels, d.OutletTable, d.OutletOverrides)
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(labels, infoLabels...)},
{u.Device.Uptime, gauge, d.Uptime, labels},
{u.Device.Upgradeable, gauge, d.Upgradeable.Val, labels},
u.exportWithTags(r, d.Tags, func(tagLabels []string) {
tag := tagLabels[0]
labels := append(baseLabels, tag)
infoLabels := append(baseInfoLabels, tag)
u.exportPDUstats(r, labels, d.Stat.Sw)
u.exportPDUPrtTable(r, labels, d.PortTable)
u.exportPDUOutletTable(r, labels, d.OutletTable, d.OutletOverrides)
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.Upgradeable.Val, labels},
})
// Switch System Data.
if d.OutletACPowerConsumption.Txt != "" {
r.send([]*metric{{u.Device.OutletACPowerConsumption, gauge, d.OutletACPowerConsumption, labels}})
}
if d.PowerSource.Txt != "" {
r.send([]*metric{{u.Device.PowerSource, gauge, d.PowerSource, labels}})
}
if d.TotalMaxPower.Txt != "" {
r.send([]*metric{{u.Device.TotalMaxPower, gauge, d.TotalMaxPower, labels}})
}
})
// Switch System Data.
if d.OutletACPowerConsumption.Txt != "" {
r.send([]*metric{{u.Device.OutletACPowerConsumption, gauge, d.OutletACPowerConsumption, labels}})
}
if d.PowerSource.Txt != "" {
r.send([]*metric{{u.Device.PowerSource, gauge, d.PowerSource, labels}})
}
if d.TotalMaxPower.Txt != "" {
r.send([]*metric{{u.Device.TotalMaxPower, gauge, d.TotalMaxPower, labels}})
}
}
// Switch Stats.
@@ -204,7 +210,7 @@ func (u *promUnifi) exportPDUPrtTable(r report, labels []string, pt []unifi.Port
// Copy labels, and add four new ones.
labelP := []string{
labels[2] + " Port " + p.PortIdx.Txt, p.PortIdx.Txt,
p.Name, p.Mac, p.IP, labels[1], labels[2], labels[3],
p.Name, p.Mac, p.IP, labels[1], labels[2], labels[3], labels[4],
}
if p.PoeEnable.Val && p.PortPoe.Val {
@@ -218,7 +224,7 @@ func (u *promUnifi) exportPDUPrtTable(r report, labels []string, pt []unifi.Port
if p.SFPFound.Val {
labelF := []string{
p.SFPPart, p.SFPVendor, p.SFPSerial, p.SFPCompliance,
labelP[0], labelP[1], labelP[2], labelP[3], labelP[4], labelP[5], labelP[6], labelP[7],
labelP[0], labelP[1], labelP[2], labelP[3], labelP[4], labelP[5], labelP[6], labelP[7], labelP[8],
}
r.send([]*metric{
@@ -258,7 +264,7 @@ func (u *promUnifi) exportPDUOutletTable(r report, labels []string, ot []unifi.O
// Copy labels, and add four new ones.
labelOutlet := []string{
labels[2] + " Outlet " + o.Index.Txt, o.Index.Txt,
o.Name, labels[1], labels[2], labels[3],
o.Name, labels[1], labels[2], labels[3], labels[4],
}
r.send([]*metric{
@@ -277,7 +283,7 @@ func (u *promUnifi) exportPDUOutletTable(r report, labels []string, ot []unifi.O
// Copy labels, and add four new ones.
labelOutlet := []string{
labels[2] + " Outlet Override " + o.Index.Txt, o.Index.Txt,
o.Name, labels[1], labels[2], labels[3],
o.Name, labels[1], labels[2], labels[3], labels[4],
}
r.send([]*metric{