more cleanup

This commit is contained in:
davidnewhall2 2019-11-29 21:16:49 -08:00
parent a9a7862438
commit a58c1210d0
8 changed files with 70 additions and 55 deletions

View File

@ -12,6 +12,8 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
)
const oneDecimalPoint = 10
// RunPrometheus starts the web server and registers the collector.
func (u *UnifiPoller) RunPrometheus() error {
u.Logf("Exporting Measurements at https://%s/metrics for Prometheus", u.Config.HTTPListen)
@ -57,10 +59,11 @@ func (u *UnifiPoller) LogExportReport(report *promunifi.Report) {
idsMsg = fmt.Sprintf(", IDS Events: %d, ", len(m.IDSList))
}
u.Logf("UniFi Measurements Exported. Sites: %d, Clients: %d, "+
"Wireless APs: %d, Gateways: %d, Switches: %d%s, Descs: %d, "+
"Metrics: %d, Errors: %d, Zeros: %d, Elapsed: %v",
len(m.Sites), len(m.Clients), len(m.UAPs), len(m.UDMs)+len(m.USGs),
len(m.USWs), idsMsg, report.Descs, report.Total, report.Errors,
report.Zeros, report.Elapsed.Round(time.Millisecond))
u.Logf("UniFi Measurements Exported. Site: %d, Client: %d, "+
"UAP: %d, USG/UDM: %d, USW: %d%s, Descs: %d, "+
"Metrics: %d, Errs: %d, 0s: %d, Reqs/Total: %v/%v",
len(m.Sites), len(m.Clients), len(m.UAPs), len(m.UDMs)+len(m.USGs), len(m.USWs),
idsMsg, report.Descs, report.Total, report.Errors, report.Zeros,
report.Fetch.Round(time.Millisecond/oneDecimalPoint),
report.Elapsed.Round(time.Millisecond/oneDecimalPoint))
}

View File

@ -72,11 +72,12 @@ func descClient(ns string) *uclient {
}
func (u *unifiCollector) exportClient(r report, c *unifi.Client) {
labels := []string{c.Name, c.Mac, c.SiteName, c.GwName, c.SwName, c.Vlan.Txt, c.IP, c.Oui, c.Network, c.SwPort.Txt, c.ApName, "false"}
labels := []string{c.Name, c.Mac, c.SiteName, c.GwName, c.SwName, c.Vlan.Txt, c.IP, c.Oui, c.Network, c.SwPort.Txt, c.ApName, ""}
labelW := append([]string{c.RadioName, c.Radio, c.RadioProto, c.Channel.Txt, c.Essid, c.Bssid, c.RadioDescription}, labels...)
if c.IsWired.Val {
labels[len(labels)-1] = "true"
labelW[len(labelW)-1] = "true"
r.send([]*metricExports{
{u.Client.RxBytes, prometheus.CounterValue, c.WiredRxBytes, labels},
{u.Client.RxBytesR, prometheus.GaugeValue, c.WiredRxBytesR, labels},
@ -87,6 +88,7 @@ func (u *unifiCollector) exportClient(r report, c *unifi.Client) {
})
} else {
labels[len(labels)-1] = "false"
labelW[len(labelW)-1] = "false"
r.send([]*metricExports{
{u.Client.Anomalies, prometheus.CounterValue, c.Anomalies, labelW},
{u.Client.CCQ, prometheus.GaugeValue, c.Ccq / 10, labelW},

View File

@ -58,6 +58,7 @@ type Report struct {
Descs int
Metrics *metrics.Metrics
Elapsed time.Duration
Fetch time.Duration
Start time.Time
ch chan []*metricExports
wg sync.WaitGroup
@ -121,12 +122,13 @@ func (u *unifiCollector) Collect(ch chan<- prometheus.Metric) {
}()
var err error
if r.Metrics, err = u.Config.CollectFn(); err != nil {
ch <- prometheus.NewInvalidMetric(
prometheus.NewInvalidDesc(fmt.Errorf("metric fetch failed")), err)
if r.Metrics, err = r.cf.CollectFn(); err != nil {
r.error(ch, prometheus.NewInvalidDesc(fmt.Errorf("metric fetch failed")), err)
return
}
r.Fetch = time.Since(r.Start)
// Pass Report interface into our collecting and reporting methods.
go u.exportMetrics(r, ch)
// in loops.go.
u.loopClients(r)
@ -155,7 +157,7 @@ func (u *unifiCollector) exportMetrics(r report, ch chan<- prometheus.Metric) {
case int:
ch <- r.export(m, float64(v))
default:
r.error(ch, m.Desc, m.Value)
r.error(ch, m.Desc, fmt.Sprintf("not a number: %v", m.Value))
}
}
r.done()

View File

@ -5,78 +5,84 @@ package promunifi
// they usually all change at once since they're pretty much the same code.
func (u *unifiCollector) loopSites(r report) {
if r.metrics() == nil || len(r.metrics().Sites) < 1 {
m := r.metrics()
if m == nil || len(m.Sites) < 1 {
return
}
r.add()
go func() {
defer r.done()
for _, s := range r.metrics().Sites {
for _, s := range m.Sites {
u.exportSite(r, s)
}
}()
}
func (u *unifiCollector) loopUAPs(r report) {
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.UAPs) < 1 {
m := r.metrics()
if m == nil || m.Devices == nil || len(m.Devices.UAPs) < 1 {
return
}
r.add()
go func() {
defer r.done()
for _, d := range r.metrics().Devices.UAPs {
for _, d := range m.Devices.UAPs {
u.exportUAP(r, d)
}
}()
}
func (u *unifiCollector) loopUDMs(r report) {
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.UDMs) < 1 {
m := r.metrics()
if m == nil || m.Devices == nil || len(m.Devices.UDMs) < 1 {
return
}
r.add()
go func() {
defer r.done()
for _, d := range r.metrics().Devices.UDMs {
for _, d := range m.Devices.UDMs {
u.exportUDM(r, d)
}
}()
}
func (u *unifiCollector) loopUSGs(r report) {
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.USGs) < 1 {
m := r.metrics()
if m == nil || m.Devices == nil || len(m.Devices.USGs) < 1 {
return
}
r.add()
go func() {
defer r.done()
for _, d := range r.metrics().Devices.USGs {
for _, d := range m.Devices.USGs {
u.exportUSG(r, d)
}
}()
}
func (u *unifiCollector) loopUSWs(r report) {
if r.metrics() == nil || r.metrics().Devices == nil || len(r.metrics().Devices.USWs) < 1 {
m := r.metrics()
if m == nil || m.Devices == nil || len(m.Devices.USWs) < 1 {
return
}
r.add()
go func() {
defer r.done()
for _, d := range r.metrics().Devices.USWs {
for _, d := range m.Devices.USWs {
u.exportUSW(r, d)
}
}()
}
func (u *unifiCollector) loopClients(r report) {
if r.metrics() == nil || len(r.metrics().Clients) < 1 {
m := r.metrics()
if m == nil || len(m.Clients) < 1 {
return
}
r.add()
go func() {
defer r.done()
for _, c := range r.metrics().Clients {
for _, c := range m.Clients {
u.exportClient(r, c)
}
}()

View File

@ -9,23 +9,44 @@ import (
)
// This file contains the report interface.
// This interface can be mocked and overrridden for tests.
// This interface can be mocked and overridden for tests.
// report is an internal interface used to "process metrics"
type report interface {
send([]*metricExports)
add()
done()
send([]*metricExports)
metrics() *metrics.Metrics
channel() chan []*metricExports
report(descs map[*prometheus.Desc]bool)
export(m *metricExports, v float64) prometheus.Metric
channel() chan []*metricExports
error(ch chan<- prometheus.Metric, d *prometheus.Desc, v interface{})
}
// satisfy gomnd
const one = 1
func (r *Report) add() {
r.wg.Add(one)
}
func (r *Report) done() {
r.wg.Add(-one)
}
func (r *Report) send(m []*metricExports) {
r.wg.Add(one)
r.ch <- m
}
func (r *Report) metrics() *metrics.Metrics {
return r.Metrics
}
func (r *Report) channel() chan []*metricExports {
return r.ch
}
func (r *Report) report(descs map[*prometheus.Desc]bool) {
if r.cf.LoggingFn == nil {
return
@ -42,30 +63,9 @@ func (r *Report) export(m *metricExports, v float64) prometheus.Metric {
return prometheus.MustNewConstMetric(m.Desc, m.ValueType, v, m.Labels...)
}
func (r *Report) metrics() *metrics.Metrics {
return r.Metrics
}
func (r *Report) channel() chan []*metricExports {
return r.ch
}
func (r *Report) error(ch chan<- prometheus.Metric, d *prometheus.Desc, v interface{}) {
r.Errors++
if r.cf.ReportErrors {
ch <- prometheus.NewInvalidMetric(d, fmt.Errorf("not a number: %v", v))
ch <- prometheus.NewInvalidMetric(d, fmt.Errorf("error: %v", v))
}
}
func (r *Report) add() {
r.wg.Add(one)
}
func (r *Report) done() {
r.wg.Add(-one)
}
func (r *Report) send(m []*metricExports) {
r.wg.Add(one)
r.ch <- m
}

View File

@ -167,7 +167,7 @@ func descUAP(ns string) *uap {
func (u *unifiCollector) exportUAP(r report, d *unifi.UAP) {
labels := []string{d.IP, d.Version, d.Model, d.Serial, d.Type, d.Mac, d.SiteName, d.Name}
// AP data.
// Wireless System Data.
r.send([]*metricExports{
{u.Device.Uptime, prometheus.GaugeValue, d.Uptime, labels},
{u.Device.TotalTxBytes, prometheus.CounterValue, d.TxBytes, labels},
@ -189,6 +189,7 @@ 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, d.Stat.Ap)
u.exportVAPtable(r, labels, d.VapTable)
u.exportRadtable(r, labels, d.RadioTable, d.RadioTableStats)

View File

@ -70,7 +70,7 @@ func descDevice(ns string) *unifiDevice {
// 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) {
labels := []string{d.IP, d.Version, d.Model, d.Serial, d.Type, d.Mac, d.SiteName, d.Name}
// Gateway System Data.
// Dream Machine System Data.
r.send([]*metricExports{
{u.Device.Uptime, prometheus.GaugeValue, d.Uptime, labels},
{u.Device.TotalTxBytes, prometheus.CounterValue, d.TxBytes, labels},
@ -91,12 +91,15 @@ 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},
})
// Switch Data
u.exportUSWstats(r, labels, d.Stat.Sw)
u.exportPortTable(r, labels, d.PortTable)
// Gateway Data
u.exportUSGstats(r, labels, d.Stat.Gw, d.SpeedtestStatus)
u.exportWANPorts(r, labels, d.Wan1, d.Wan2)
u.exportPortTable(r, labels, d.PortTable)
// Wireless Data - UDM (non-pro) only
if d.Stat.Ap != nil && d.VapTable != nil {
// UDM Pro does not have these. UDM non-Pro does.
u.exportUAPstats(r, labels, d.Stat.Ap)
u.exportVAPtable(r, labels, *d.VapTable)
u.exportRadtable(r, labels, *d.RadioTable, *d.RadioTableStats)

View File

@ -47,11 +47,9 @@ type usw struct {
func descUSW(ns string) *usw {
pns := ns + "port_"
// The first five labels for switch are shared with (the same as) switch ports.
// labels := []string{"ip", "version", "model", "serial", "type", "mac", "site_name", "name"}
labelS := []string{"site_name", "name"} // labels[6:]
// Copy labels, and replace first four with different names.
labelP := append([]string{"port_num", "port_name", "port_mac", "port_ip"}, labelS...)
labelP := []string{"port_num", "port_name", "port_mac", "port_ip", "site_name", "name"}
return &usw{
SwRxPackets: prometheus.NewDesc(ns+"switch_receive_packets_total", "Switch Packets Received Total", labelS, nil),
SwRxBytes: prometheus.NewDesc(ns+"switch_receive_bytes_total", "Switch Bytes Received Total", labelS, nil),