add an interface for testing
This commit is contained in:
parent
70aae28723
commit
f91ececd63
|
|
@ -87,20 +87,20 @@ func descClient(ns string) *uclient {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportClients(r *Report) {
|
||||
if r.Metrics == nil || len(r.Metrics.Clients) < 1 {
|
||||
func (u *unifiCollector) exportClients(r report) {
|
||||
if r.metrics() == nil || len(r.metrics().Clients) < 1 {
|
||||
return
|
||||
}
|
||||
r.wg.Add(one)
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.wg.Done()
|
||||
for _, c := range r.Metrics.Clients {
|
||||
defer r.done()
|
||||
for _, c := range r.metrics().Clients {
|
||||
u.exportClient(r, c)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportClient(r *Report, c *unifi.Client) {
|
||||
func (u *unifiCollector) exportClient(r report, c *unifi.Client) {
|
||||
labels := []string{c.Name, c.Mac, c.SiteName, c.GwMac, c.GwName, c.SwMac, c.SwName, c.Vlan.Txt, c.IP, c.Oui, c.Network}
|
||||
labelWired := append([]string{c.SwPort.Txt}, labels...)
|
||||
labelWireless := append([]string{c.ApMac, c.ApName, c.RadioName, c.Radio, c.RadioProto, c.Channel.Txt, c.Essid, c.Bssid, c.RadioDescription}, labels...)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package promunifi
|
|||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -12,9 +13,6 @@ import (
|
|||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// satisfy gomnd
|
||||
const one = 1
|
||||
|
||||
// channel buffer, fits at least one batch.
|
||||
const buffer = 50
|
||||
|
||||
|
|
@ -65,13 +63,21 @@ type Report struct {
|
|||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// internal interface used to "process metrics" - can be mocked and overridden for tests.
|
||||
type report interface {
|
||||
send([]*metricExports)
|
||||
add()
|
||||
done()
|
||||
metrics() *metrics.Metrics
|
||||
}
|
||||
|
||||
// NewUnifiCollector returns a prometheus collector that will export any available
|
||||
// UniFi metrics. You must provide a collection function in the opts.
|
||||
func NewUnifiCollector(opts UnifiCollectorCnfg) prometheus.Collector {
|
||||
if opts.CollectFn == nil {
|
||||
panic("nil collector function")
|
||||
}
|
||||
if opts.Namespace += "_"; opts.Namespace == "_" {
|
||||
if opts.Namespace = strings.Trim(opts.Namespace, "_") + "_"; opts.Namespace == "_" {
|
||||
opts.Namespace = ""
|
||||
}
|
||||
return &unifiCollector{
|
||||
|
|
@ -175,6 +181,21 @@ func (u *unifiCollector) exportMetrics(r *Report, ch chan<- prometheus.Metric) {
|
|||
u.Config.LoggingFn(r)
|
||||
}
|
||||
|
||||
func (r *Report) metrics() *metrics.Metrics {
|
||||
return r.Metrics
|
||||
}
|
||||
|
||||
// satisfy gomnd
|
||||
const one = 1
|
||||
|
||||
func (r *Report) add() {
|
||||
r.wg.Add(one)
|
||||
}
|
||||
|
||||
func (r *Report) done() {
|
||||
r.wg.Done()
|
||||
}
|
||||
|
||||
func (r *Report) send(m []*metricExports) {
|
||||
r.wg.Add(one)
|
||||
r.ch <- m
|
||||
|
|
|
|||
|
|
@ -64,20 +64,20 @@ func descSite(ns string) *site {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportSites(r *Report) {
|
||||
if r.Metrics == nil || len(r.Metrics.Sites) < 1 {
|
||||
func (u *unifiCollector) exportSites(r report) {
|
||||
if r.metrics() == nil || len(r.metrics().Sites) < 1 {
|
||||
return
|
||||
}
|
||||
r.wg.Add(one)
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.wg.Done()
|
||||
for _, s := range r.Metrics.Sites {
|
||||
defer r.done()
|
||||
for _, s := range r.metrics().Sites {
|
||||
u.exportSite(r, s)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportSite(r *Report, s *unifi.Site) {
|
||||
func (u *unifiCollector) exportSite(r report, s *unifi.Site) {
|
||||
labels := []string{s.Name, s.Desc, s.SiteName}
|
||||
for _, h := range s.Health {
|
||||
l := append([]string{h.Subsystem, h.Status}, labels...)
|
||||
|
|
|
|||
|
|
@ -165,20 +165,20 @@ func descUAP(ns string) *uap {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUAPs(r *Report) {
|
||||
if r.Metrics == nil || r.Metrics.Devices == nil || len(r.Metrics.Devices.UAPs) < 1 {
|
||||
func (u *unifiCollector) exportUAPs(r report) {
|
||||
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.UAPs) < 1 {
|
||||
return
|
||||
}
|
||||
r.wg.Add(one)
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.wg.Done()
|
||||
for _, d := range r.Metrics.Devices.UAPs {
|
||||
defer r.done()
|
||||
for _, d := range r.metrics().Devices.UAPs {
|
||||
u.exportUAP(r, d)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUAP(r *Report, d *unifi.UAP) {
|
||||
func (u *unifiCollector) exportUAP(r report, d *unifi.UAP) {
|
||||
labels := []string{d.IP, d.Type, d.Version, d.SiteName, d.Mac, d.Model, d.Name, d.Serial}
|
||||
// AP data.
|
||||
r.send([]*metricExports{
|
||||
|
|
@ -202,15 +202,15 @@ func (u *unifiCollector) exportUAP(r *Report, d *unifi.UAP) {
|
|||
{u.Device.CPU, prometheus.GaugeValue, d.SystemStats.CPU, labels},
|
||||
{u.Device.Mem, prometheus.GaugeValue, d.SystemStats.Mem, labels},
|
||||
})
|
||||
u.exportUAPstats(r, labels[2:], d.Stat.Ap)
|
||||
u.exportVAPtable(r, labels[2:], d.VapTable)
|
||||
u.exportRadtable(r, labels[2:], d.RadioTable, d.RadioTableStats)
|
||||
u.exportUAPstats(r, labels, d.Stat.Ap)
|
||||
u.exportVAPtable(r, labels, d.VapTable)
|
||||
u.exportRadtable(r, labels, d.RadioTable, d.RadioTableStats)
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUAPstats(r *Report, labels []string, ap *unifi.Ap) {
|
||||
labelA := append([]string{"all"}, labels...)
|
||||
labelU := append([]string{"user"}, labels...)
|
||||
labelG := append([]string{"guest"}, labels...)
|
||||
func (u *unifiCollector) exportUAPstats(r report, labels []string, ap *unifi.Ap) {
|
||||
labelA := append([]string{"all"}, labels[2:]...)
|
||||
labelU := append([]string{"user"}, labels[2:]...)
|
||||
labelG := append([]string{"guest"}, labels[2:]...)
|
||||
r.send([]*metricExports{
|
||||
// all
|
||||
{u.UAP.ApWifiTxDropped, prometheus.CounterValue, ap.WifiTxDropped, labelA},
|
||||
|
|
@ -260,13 +260,13 @@ func (u *unifiCollector) exportUAPstats(r *Report, labels []string, ap *unifi.Ap
|
|||
})
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportVAPtable(r *Report, labels []string, vt unifi.VapTable) {
|
||||
func (u *unifiCollector) exportVAPtable(r report, labels []string, vt unifi.VapTable) {
|
||||
// vap table stats
|
||||
for _, v := range vt {
|
||||
if !v.Up.Val {
|
||||
continue
|
||||
}
|
||||
labelV := append([]string{v.Name, v.Bssid, v.RadioName, v.Essid, v.Usage}, labels...)
|
||||
labelV := append([]string{v.Name, v.Bssid, v.RadioName, v.Essid, v.Usage}, labels[2:]...)
|
||||
r.send([]*metricExports{
|
||||
{u.UAP.VAPCcq, prometheus.GaugeValue, v.Ccq, labelV},
|
||||
{u.UAP.VAPMacFilterRejections, prometheus.CounterValue, v.MacFilterRejections, labelV},
|
||||
|
|
@ -309,10 +309,10 @@ func (u *unifiCollector) exportVAPtable(r *Report, labels []string, vt unifi.Vap
|
|||
}
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportRadtable(r *Report, labels []string, rt unifi.RadioTable, rts unifi.RadioTableStats) {
|
||||
func (u *unifiCollector) exportRadtable(r report, labels []string, rt unifi.RadioTable, rts unifi.RadioTableStats) {
|
||||
// radio table
|
||||
for _, p := range rt {
|
||||
labelR := append([]string{p.Name, p.Radio}, labels...)
|
||||
labelR := append([]string{p.Name, p.Radio}, labels[2:]...)
|
||||
r.send([]*metricExports{
|
||||
{u.UAP.RadioCurrentAntennaGain, prometheus.GaugeValue, p.CurrentAntennaGain, labelR},
|
||||
{u.UAP.RadioHt, prometheus.GaugeValue, p.Ht, labelR},
|
||||
|
|
|
|||
|
|
@ -67,21 +67,21 @@ func descDevice(ns string) *unifiDevice {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUDMs(r *Report) {
|
||||
if r.Metrics == nil || r.Metrics.Devices == nil || len(r.Metrics.Devices.UDMs) < 1 {
|
||||
func (u *unifiCollector) exportUDMs(r report) {
|
||||
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.UDMs) < 1 {
|
||||
return
|
||||
}
|
||||
r.wg.Add(one)
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.wg.Done()
|
||||
for _, d := range r.Metrics.Devices.UDMs {
|
||||
defer r.done()
|
||||
for _, d := range r.metrics().Devices.UDMs {
|
||||
u.exportUDM(r, d)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// UDM is a collection of stats from USG, USW and UAP. It has no unique stats.
|
||||
func (u *unifiCollector) exportUDM(r *Report, d *unifi.UDM) {
|
||||
func (u *unifiCollector) exportUDM(r report, d *unifi.UDM) {
|
||||
labels := []string{d.IP, d.Type, d.Version, d.SiteName, d.Mac, d.Model, d.Name, d.Serial}
|
||||
// Gateway System Data.
|
||||
r.send([]*metricExports{
|
||||
|
|
@ -104,14 +104,14 @@ func (u *unifiCollector) exportUDM(r *Report, d *unifi.UDM) {
|
|||
{u.Device.CPU, prometheus.GaugeValue, d.SystemStats.CPU, labels},
|
||||
{u.Device.Mem, prometheus.GaugeValue, d.SystemStats.Mem, labels},
|
||||
})
|
||||
u.exportUSWstats(r, d.Stat.Sw, labels)
|
||||
u.exportUSGstats(r, d.Stat.Gw, d.SpeedtestStatus, labels)
|
||||
u.exportUSWstats(r, labels, d.Stat.Sw)
|
||||
u.exportUSGstats(r, labels, d.Stat.Gw, d.SpeedtestStatus)
|
||||
u.exportWANPorts(r, labels, d.Wan1, d.Wan2)
|
||||
u.exportPortTable(r, d.PortTable, labels[4:])
|
||||
u.exportPortTable(r, labels, d.PortTable)
|
||||
if d.Stat.Ap != nil && d.VapTable != nil {
|
||||
// UDM Pro does not have these. UDM non-Pro does.
|
||||
u.exportUAPstats(r, labels[2:], d.Stat.Ap)
|
||||
u.exportVAPtable(r, labels[2:], *d.VapTable)
|
||||
u.exportRadtable(r, labels[2:], *d.RadioTable, *d.RadioTableStats)
|
||||
u.exportUAPstats(r, labels, d.Stat.Ap)
|
||||
u.exportVAPtable(r, labels, *d.VapTable)
|
||||
u.exportRadtable(r, labels, *d.RadioTable, *d.RadioTableStats)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,20 +65,20 @@ func descUSG(ns string) *usg {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUSGs(r *Report) {
|
||||
if r.Metrics == nil || r.Metrics.Devices == nil || len(r.Metrics.Devices.USGs) < 1 {
|
||||
func (u *unifiCollector) exportUSGs(r report) {
|
||||
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.USGs) < 1 {
|
||||
return
|
||||
}
|
||||
r.wg.Add(one)
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.wg.Done()
|
||||
for _, d := range r.Metrics.Devices.USGs {
|
||||
defer r.done()
|
||||
for _, d := range r.metrics().Devices.USGs {
|
||||
u.exportUSG(r, d)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUSG(r *Report, d *unifi.USG) {
|
||||
func (u *unifiCollector) exportUSG(r report, d *unifi.USG) {
|
||||
labels := []string{d.IP, d.Type, d.Version, d.SiteName, d.Mac, d.Model, d.Name, d.Serial}
|
||||
// Gateway System Data.
|
||||
r.send([]*metricExports{
|
||||
|
|
@ -102,10 +102,10 @@ func (u *unifiCollector) exportUSG(r *Report, d *unifi.USG) {
|
|||
{u.Device.Mem, prometheus.GaugeValue, d.SystemStats.Mem, labels},
|
||||
})
|
||||
u.exportWANPorts(r, labels, d.Wan1, d.Wan2)
|
||||
u.exportUSGstats(r, d.Stat.Gw, d.SpeedtestStatus, labels)
|
||||
u.exportUSGstats(r, labels, d.Stat.Gw, d.SpeedtestStatus)
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUSGstats(r *Report, gw *unifi.Gw, st unifi.SpeedtestStatus, labels []string) {
|
||||
func (u *unifiCollector) exportUSGstats(r report, labels []string, gw *unifi.Gw, st unifi.SpeedtestStatus) {
|
||||
labelWan := append([]string{"all"}, labels...)
|
||||
r.send([]*metricExports{
|
||||
// Combined Port Stats
|
||||
|
|
@ -128,7 +128,7 @@ func (u *unifiCollector) exportUSGstats(r *Report, gw *unifi.Gw, st unifi.Speedt
|
|||
})
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportWANPorts(r *Report, labels []string, wans ...unifi.Wan) {
|
||||
func (u *unifiCollector) exportWANPorts(r report, labels []string, wans ...unifi.Wan) {
|
||||
for _, wan := range wans {
|
||||
if !wan.Up.Val {
|
||||
continue // only record UP interfaces.
|
||||
|
|
|
|||
|
|
@ -91,20 +91,20 @@ func descUSW(ns string) *usw {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUSWs(r *Report) {
|
||||
if r.Metrics == nil || r.Metrics.Devices == nil || len(r.Metrics.Devices.USWs) < 1 {
|
||||
func (u *unifiCollector) exportUSWs(r report) {
|
||||
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.USWs) < 1 {
|
||||
return
|
||||
}
|
||||
r.wg.Add(one)
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.wg.Done()
|
||||
for _, d := range r.Metrics.Devices.USWs {
|
||||
defer r.done()
|
||||
for _, d := range r.metrics().Devices.USWs {
|
||||
u.exportUSW(r, d)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUSW(r *Report, d *unifi.USW) {
|
||||
func (u *unifiCollector) exportUSW(r report, d *unifi.USW) {
|
||||
labels := []string{d.IP, d.Type, d.Version, d.SiteName, d.Mac, d.Model, d.Name, d.Serial}
|
||||
if d.HasTemperature.Val {
|
||||
r.send([]*metricExports{{u.Device.Temperature, prometheus.GaugeValue, d.GeneralTemperature, labels}})
|
||||
|
|
@ -132,11 +132,11 @@ func (u *unifiCollector) exportUSW(r *Report, d *unifi.USW) {
|
|||
{u.Device.CPU, prometheus.GaugeValue, d.SystemStats.CPU, labels},
|
||||
{u.Device.Mem, prometheus.GaugeValue, d.SystemStats.Mem, labels},
|
||||
})
|
||||
u.exportPortTable(r, d.PortTable, labels[4:])
|
||||
u.exportUSWstats(r, d.Stat.Sw, labels)
|
||||
u.exportPortTable(r, labels, d.PortTable)
|
||||
u.exportUSWstats(r, labels, d.Stat.Sw)
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportUSWstats(r *Report, sw *unifi.Sw, labels []string) {
|
||||
func (u *unifiCollector) exportUSWstats(r report, labels []string, sw *unifi.Sw) {
|
||||
r.send([]*metricExports{
|
||||
{u.USW.SwRxPackets, prometheus.CounterValue, sw.RxPackets, labels},
|
||||
{u.USW.SwRxBytes, prometheus.CounterValue, sw.RxBytes, labels},
|
||||
|
|
@ -157,14 +157,14 @@ func (u *unifiCollector) exportUSWstats(r *Report, sw *unifi.Sw, labels []string
|
|||
})
|
||||
}
|
||||
|
||||
func (u *unifiCollector) exportPortTable(r *Report, pt []unifi.Port, labels []string) {
|
||||
func (u *unifiCollector) exportPortTable(r report, labels []string, pt []unifi.Port) {
|
||||
// Per-port data on a switch
|
||||
for _, p := range pt {
|
||||
if !p.Up.Val {
|
||||
continue
|
||||
}
|
||||
// Copy labels, and add four new ones.
|
||||
l := append([]string{p.PortIdx.Txt, p.Name, p.Mac, p.IP}, labels...)
|
||||
l := append([]string{p.PortIdx.Txt, p.Name, p.Mac, p.IP}, labels[4:]...)
|
||||
if p.PoeEnable.Val && p.PortPoe.Val {
|
||||
r.send([]*metricExports{
|
||||
{u.USW.PoeCurrent, prometheus.GaugeValue, p.PoeCurrent, l},
|
||||
|
|
|
|||
Loading…
Reference in New Issue