From c1be3e79a346f6ff648ccb5c5183e5892a1902f7 Mon Sep 17 00:00:00 2001 From: davidnewhall2 Date: Fri, 29 Nov 2019 22:35:42 -0800 Subject: [PATCH] tighter for loops --- integrations/inputunifi/poller/prometheus.go | 2 +- .../inputunifi/promunifi/collector.go | 39 ++++------ integrations/inputunifi/promunifi/loops.go | 78 +++++-------------- integrations/inputunifi/promunifi/report.go | 13 +++- integrations/inputunifi/promunifi/usg.go | 2 +- integrations/inputunifi/promunifi/usw.go | 2 +- 6 files changed, 46 insertions(+), 90 deletions(-) diff --git a/integrations/inputunifi/poller/prometheus.go b/integrations/inputunifi/poller/prometheus.go index 58e3d6fb..ae2daa63 100644 --- a/integrations/inputunifi/poller/prometheus.go +++ b/integrations/inputunifi/poller/prometheus.go @@ -61,7 +61,7 @@ func (u *UnifiPoller) LogExportReport(report *promunifi.Report) { 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", + "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), diff --git a/integrations/inputunifi/promunifi/collector.go b/integrations/inputunifi/promunifi/collector.go index 85d8d2ba..6ea0964d 100644 --- a/integrations/inputunifi/promunifi/collector.go +++ b/integrations/inputunifi/promunifi/collector.go @@ -88,9 +88,8 @@ func NewUnifiCollector(opts UnifiCollectorCnfg) prometheus.Collector { // Describe satisfies the prometheus Collector. This returns all of the // metric descriptions that this packages produces. func (u *unifiCollector) Describe(ch chan<- *prometheus.Desc) { - describe := func(from interface{}) { - v := reflect.Indirect(reflect.ValueOf(from)) - + for _, f := range []interface{}{u.Client, u.Device, u.UAP, u.USG, u.USW, u.Site} { + v := reflect.Indirect(reflect.ValueOf(f)) // Loop each struct member and send it to the provided channel. for i := 0; i < v.NumField(); i++ { desc, ok := v.Field(i).Interface().(*prometheus.Desc) @@ -99,44 +98,32 @@ func (u *unifiCollector) Describe(ch chan<- *prometheus.Desc) { } } } - - describe(u.Client) - describe(u.Device) - describe(u.UAP) - describe(u.USG) - describe(u.USW) - describe(u.Site) } // Collect satisfies the prometheus Collector. This runs the input method to get // the current metrics (from another package) then exports them for prometheus. func (u *unifiCollector) Collect(ch chan<- prometheus.Metric) { - r := &Report{ - cf: u.Config, - Start: time.Now(), - ch: make(chan []*metricExports, buffer), - } - defer func() { - r.wg.Wait() - close(r.ch) - }() - var err error + r := &Report{cf: u.Config, ch: make(chan []*metricExports, buffer)} + defer r.finish() + + r.Start = time.Now() 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) + if r.Metrics.Devices == nil { + r.Metrics.Devices = &unifi.Devices{} + } // Pass Report interface into our collecting and reporting methods. go u.exportMetrics(r, ch) // in loops.go. - u.loopClients(r) - u.loopSites(r) - u.loopUAPs(r) - u.loopUSWs(r) - u.loopUSGs(r) - u.loopUDMs(r) + for _, f := range []func(report){u.loopClients, u.loopSites, u.loopUAPs, u.loopUSWs, u.loopUSGs, u.loopUDMs} { + r.add() + go f(r) + } } // This is closely tied to the method above with a sync.WaitGroup. diff --git a/integrations/inputunifi/promunifi/loops.go b/integrations/inputunifi/promunifi/loops.go index 1ddcebd5..1e7cd522 100644 --- a/integrations/inputunifi/promunifi/loops.go +++ b/integrations/inputunifi/promunifi/loops.go @@ -5,85 +5,43 @@ package promunifi // they usually all change at once since they're pretty much the same code. func (u *unifiCollector) loopSites(r report) { - m := r.metrics() - if m == nil || len(m.Sites) < 1 { - return + defer r.done() + for _, s := range r.metrics().Sites { + u.exportSite(r, s) } - r.add() - go func() { - defer r.done() - for _, s := range m.Sites { - u.exportSite(r, s) - } - }() } func (u *unifiCollector) loopUAPs(r report) { - m := r.metrics() - if m == nil || m.Devices == nil || len(m.Devices.UAPs) < 1 { - return + defer r.done() + for _, d := range r.metrics().UAPs { + u.exportUAP(r, d) } - r.add() - go func() { - defer r.done() - for _, d := range m.Devices.UAPs { - u.exportUAP(r, d) - } - }() } func (u *unifiCollector) loopUDMs(r report) { - m := r.metrics() - if m == nil || m.Devices == nil || len(m.Devices.UDMs) < 1 { - return + defer r.done() + for _, d := range r.metrics().UDMs { + u.exportUDM(r, d) } - r.add() - go func() { - defer r.done() - for _, d := range m.Devices.UDMs { - u.exportUDM(r, d) - } - }() } func (u *unifiCollector) loopUSGs(r report) { - m := r.metrics() - if m == nil || m.Devices == nil || len(m.Devices.USGs) < 1 { - return + defer r.done() + for _, d := range r.metrics().USGs { + u.exportUSG(r, d) } - r.add() - go func() { - defer r.done() - for _, d := range m.Devices.USGs { - u.exportUSG(r, d) - } - }() } func (u *unifiCollector) loopUSWs(r report) { - m := r.metrics() - if m == nil || m.Devices == nil || len(m.Devices.USWs) < 1 { - return + defer r.done() + for _, d := range r.metrics().USWs { + u.exportUSW(r, d) } - r.add() - go func() { - defer r.done() - for _, d := range m.Devices.USWs { - u.exportUSW(r, d) - } - }() } func (u *unifiCollector) loopClients(r report) { - m := r.metrics() - if m == nil || len(m.Clients) < 1 { - return + defer r.done() + for _, c := range r.metrics().Clients { + u.exportClient(r, c) } - r.add() - go func() { - defer r.done() - for _, c := range m.Clients { - u.exportClient(r, c) - } - }() } diff --git a/integrations/inputunifi/promunifi/report.go b/integrations/inputunifi/promunifi/report.go index d59c222c..92550984 100644 --- a/integrations/inputunifi/promunifi/report.go +++ b/integrations/inputunifi/promunifi/report.go @@ -6,6 +6,7 @@ import ( "github.com/davidnewhall/unifi-poller/metrics" "github.com/prometheus/client_golang/prometheus" + "golift.io/unifi" ) // This file contains the report interface. @@ -40,6 +41,9 @@ func (r *Report) send(m []*metricExports) { } func (r *Report) metrics() *metrics.Metrics { + if r.Metrics == nil { + return &metrics.Metrics{Devices: &unifi.Devices{}} + } return r.Metrics } @@ -51,7 +55,7 @@ func (r *Report) report(descs map[*prometheus.Desc]bool) { if r.cf.LoggingFn == nil { return } - r.Descs, r.Elapsed = len(descs), time.Since(r.Start) + r.Descs = len(descs) r.cf.LoggingFn(r) } @@ -69,3 +73,10 @@ func (r *Report) error(ch chan<- prometheus.Metric, d *prometheus.Desc, v interf ch <- prometheus.NewInvalidMetric(d, fmt.Errorf("error: %v", v)) } } + +// finish is not part of the interface. +func (r *Report) finish() { + r.wg.Wait() + r.Elapsed = time.Since(r.Start) + close(r.ch) +} diff --git a/integrations/inputunifi/promunifi/usg.go b/integrations/inputunifi/promunifi/usg.go index 8eafef7d..5cfef6c1 100644 --- a/integrations/inputunifi/promunifi/usg.go +++ b/integrations/inputunifi/promunifi/usg.go @@ -97,7 +97,7 @@ func (u *unifiCollector) exportUSGstats(r report, labels []string, gw *unifi.Gw, labelLan := []string{"lan", labels[6], labels[7]} labelWan := []string{"all", labels[6], labels[7]} r.send([]*metricExports{ - /* // Combined Port Stats + /* // Combined Port Stats - not really needed. sum() the others instead. {u.USG.WanRxPackets, prometheus.CounterValue, gw.WanRxPackets, labelWan}, {u.USG.WanRxBytes, prometheus.CounterValue, gw.WanRxBytes, labelWan}, {u.USG.WanRxDropped, prometheus.CounterValue, gw.WanRxDropped, labelWan}, diff --git a/integrations/inputunifi/promunifi/usw.go b/integrations/inputunifi/promunifi/usw.go index 6ce9a463..fccb65bf 100644 --- a/integrations/inputunifi/promunifi/usw.go +++ b/integrations/inputunifi/promunifi/usw.go @@ -99,7 +99,7 @@ func (u *unifiCollector) exportUSW(r report, d *unifi.USW) { r.send([]*metricExports{{u.Device.FanLevel, prometheus.GaugeValue, d.FanLevel, labels}}) } - // Switch data. + // Switch System Data. r.send([]*metricExports{ {u.Device.Uptime, prometheus.GaugeValue, d.Uptime, labels}, {u.Device.TotalMaxPower, prometheus.GaugeValue, d.TotalMaxPower, labels},