diff --git a/Gopkg.lock b/Gopkg.lock index 2c504530..f8e483d8 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -46,11 +46,12 @@ version = "v1.0.1" [[projects]] - digest = "1:eb04f69c8991e52eff33c428bd729e04208bf03235be88e4df0d88497c6861b9" + digest = "1:eb8832cdc904ff89b70c524ab305bf3384c6411f9df6b9f2a41fddc2220e6613" name = "github.com/prometheus/client_golang" packages = [ "prometheus", "prometheus/internal", + "prometheus/promauto", "prometheus/promhttp", ] pruneopts = "UT" @@ -127,6 +128,8 @@ input-imports = [ "github.com/BurntSushi/toml", "github.com/influxdata/influxdb1-client/v2", + "github.com/prometheus/client_golang/prometheus", + "github.com/prometheus/client_golang/prometheus/promauto", "github.com/prometheus/client_golang/prometheus/promhttp", "github.com/spf13/pflag", "golift.io/unifi", diff --git a/examples/up.conf.example b/examples/up.conf.example index e702ec28..82c1f9b1 100644 --- a/examples/up.conf.example +++ b/examples/up.conf.example @@ -34,7 +34,6 @@ quiet = false # /metrics for polling collection by a prometheus server. This disables influxdb. mode = "influx" - # This controls on which ip and port /metrics is exported when mode is "prometheus". # This has no effect in other modes. Must contain a colon and port. http_listen = "0.0.0.0:61317" diff --git a/poller/start.go b/poller/start.go index 0ffe483b..871a55f2 100644 --- a/poller/start.go +++ b/poller/start.go @@ -10,7 +10,9 @@ import ( "strings" "time" + "github.com/davidnewhall/unifi-poller/promunifi" client "github.com/influxdata/influxdb1-client/v2" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/pflag" "golift.io/unifi" @@ -98,19 +100,24 @@ func (u *UnifiPoller) Run() (err error) { case "prometheus", "exporter": u.Logf("Exporting Measurements at https://%s/metrics for Prometheus", u.Config.HTTPListen) u.Config.Mode = "http exporter" - http.Handle("/metrics", promhttp.Handler()) - go func() { - err = http.ListenAndServe(u.Config.HTTPListen, nil) - if err != http.ErrServerClosed { - log.Fatalf("[ERROR] http server: %v", err) - } - }() - return u.PollController(u.ExportMetrics) + http.Handle("/metrics", http.HandlerFunc(u.PromHandler)) + prometheus.MustRegister(promunifi.NewUnifiCollector(promunifi.UnifiCollectorOpts{ + CollectFn: u.ExportMetrics, + ReportErrors: true, + Namespace: "unifi", + CollectIDS: true, + })) + err = http.ListenAndServe(u.Config.HTTPListen, nil) + if err != http.ErrServerClosed { + return err + } + return nil default: if err = u.GetInfluxDB(); err != nil { return err } + u.Logf("Logging Measurements to InfluxDB at %s as user %s", u.Config.InfluxURL, u.Config.InfluxUser) u.Config.Mode = "influx poller" return u.PollController(u.ReportMetrics) @@ -128,9 +135,16 @@ func (u *UnifiPoller) GetInfluxDB() (err error) { if err != nil { return fmt.Errorf("influxdb: %v", err) } + return nil } +// PromHandler logs /metrics requests and serves them with the prometheus handler. +func (u *UnifiPoller) PromHandler(w http.ResponseWriter, r *http.Request) { + u.LogDebugf("/metrics endpoint polled by %v", r.RemoteAddr) + promhttp.Handler().ServeHTTP(w, r) +} + // GetUnifi returns a UniFi controller interface. func (u *UnifiPoller) GetUnifi() (err error) { // Create an authenticated session to the Unifi Controller. diff --git a/poller/unifi.go b/poller/unifi.go index f69c9815..9b4a87b4 100644 --- a/poller/unifi.go +++ b/poller/unifi.go @@ -8,7 +8,6 @@ import ( "github.com/davidnewhall/unifi-poller/influx" "github.com/davidnewhall/unifi-poller/metrics" - "github.com/davidnewhall/unifi-poller/prometheus" client "github.com/influxdata/influxdb1-client/v2" "golift.io/unifi" ) @@ -84,14 +83,45 @@ func (u *UnifiPoller) CollectAndProcess(process func(*metrics.Metrics) error) er if err != nil { return err } - if err := u.AugmentMetrics(metrics); err != nil { - return err - } + u.AugmentMetrics(metrics) err = process(metrics) u.LogError(err, "processing metrics") return err } +// ExportMetrics updates the internal metrics provided via +// HTTP at /metrics for prometheus collection. +func (u *UnifiPoller) ExportMetrics() *metrics.Metrics { + if u.Config.ReAuth { + u.LogDebugf("Re-authenticating to UniFi Controller") + // Some users need to re-auth every interval because the cookie times out. + if err := u.Unifi.Login(); err != nil { + u.LogError(err, "re-authenticating") + return nil + } + } + metrics, err := u.CollectMetrics() + if err != nil { + u.LogErrorf("collecting metrics: %v", err) + return nil + } + u.AugmentMetrics(metrics) + u.LogExportReport(metrics) + return metrics +} + +// LogExportReport writes a log line after exporting metrics via HTTP. +func (u *UnifiPoller) LogExportReport(m *metrics.Metrics) { + idsMsg := "" + if u.Config.CollectIDS { + 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", + len(m.Sites), len(m.Clients), len(m.UAPs), + len(m.UDMs)+len(m.USGs), len(m.USWs), idsMsg) +} + // CollectMetrics grabs all the measurements from a UniFi controller and returns them. func (u *UnifiPoller) CollectMetrics() (*metrics.Metrics, error) { m := &metrics.Metrics{TS: u.LastCheck} // At this point, it's the Current Check. @@ -115,9 +145,9 @@ func (u *UnifiPoller) CollectMetrics() (*metrics.Metrics, error) { // AugmentMetrics is our middleware layer between collecting metrics and writing them. // This is where we can manipuate the returned data or make arbitrary decisions. // This function currently adds parent device names to client metrics. -func (u *UnifiPoller) AugmentMetrics(metrics *metrics.Metrics) error { +func (u *UnifiPoller) AugmentMetrics(metrics *metrics.Metrics) { if metrics == nil || metrics.Devices == nil || metrics.Clients == nil { - return fmt.Errorf("nil metrics, augment impossible") + return } devices := make(map[string]string) bssdIDs := make(map[string]string) @@ -143,30 +173,6 @@ func (u *UnifiPoller) AugmentMetrics(metrics *metrics.Metrics) error { metrics.Clients[i].GwName = devices[c.GwMac] metrics.Clients[i].RadioDescription = bssdIDs[metrics.Clients[i].Bssid] + metrics.Clients[i].RadioProto } - return nil -} - -// ExportMetrics updates the internal metrics provided via -// HTTP at /metrics for prometheus collection. -func (u *UnifiPoller) ExportMetrics(metrics *metrics.Metrics) error { - m := &prometheus.Metrics{Metrics: metrics} - for _, err := range m.ProcessExports() { - u.LogError(err, "prometheus.ProcessExports") - } - u.LogExportReport(m) - return nil -} - -// LogExportReport writes a log line after exporting metrics via HTTP. -func (u *UnifiPoller) LogExportReport(m *prometheus.Metrics) { - idsMsg := "" - if u.Config.CollectIDS { - 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", - len(m.Sites), len(m.Clients), len(m.UAPs), - len(m.UDMs)+len(m.USGs), len(m.USWs), idsMsg) } // ReportMetrics batches all the metrics and writes them to InfluxDB. diff --git a/prometheus/exporter.go b/prometheus/exporter.go deleted file mode 100644 index 506ae890..00000000 --- a/prometheus/exporter.go +++ /dev/null @@ -1,13 +0,0 @@ -package prometheus - -import "github.com/davidnewhall/unifi-poller/metrics" - -// Metrics contains all the data from the controller. -type Metrics struct { - *metrics.Metrics -} - -// ProcessExports turns the data into exported data. -func (m *Metrics) ProcessExports() []error { - return nil -} diff --git a/prometheus/README.md b/promunifi/README.md similarity index 69% rename from prometheus/README.md rename to promunifi/README.md index f883cfd4..27e9ef04 100644 --- a/prometheus/README.md +++ b/promunifi/README.md @@ -1,4 +1,4 @@ # prometheus This package provides the methods to turn UniFi measurements into prometheus -exported metrics with an HTTP listener. +exported metrics. diff --git a/promunifi/clients.go b/promunifi/clients.go new file mode 100644 index 00000000..f4511c98 --- /dev/null +++ b/promunifi/clients.go @@ -0,0 +1,213 @@ +package promunifi + +import ( + "github.com/prometheus/client_golang/prometheus" + "golift.io/unifi" +) + +type client struct { + Anomalies *prometheus.Desc + BytesR *prometheus.Desc + CCQ *prometheus.Desc + Noise *prometheus.Desc + RoamCount *prometheus.Desc + RSSI *prometheus.Desc + RxBytes *prometheus.Desc + RxBytesR *prometheus.Desc + RxPackets *prometheus.Desc + RxRate *prometheus.Desc + Signal *prometheus.Desc + TxBytes *prometheus.Desc + TxBytesR *prometheus.Desc + TxPackets *prometheus.Desc + TxPower *prometheus.Desc + TxRate *prometheus.Desc + Uptime *prometheus.Desc + WifiTxAttempts *prometheus.Desc + WiredRxBytes *prometheus.Desc + WiredRxBytesR *prometheus.Desc + WiredRxPackets *prometheus.Desc + WiredTxBytes *prometheus.Desc + WiredTxBytesR *prometheus.Desc + WiredTxPackets *prometheus.Desc + DpiStatsApp *prometheus.Desc + DpiStatsCat *prometheus.Desc + DpiStatsRxBytes *prometheus.Desc + DpiStatsRxPackets *prometheus.Desc + DpiStatsTxBytes *prometheus.Desc + DpiStatsTxPackets *prometheus.Desc +} + +func descClient(ns string) *client { + labels := []string{"id", "mac", "user_id", "site_id", "site_name", + "network_id", "ap_mac", "gw_mac", "sw_mac", "ap_name", "gw_name", + "sw_name", "radio_name", "radio", "radio_proto", "name", "channel", + "vlan", "ip", "essid", "bssid", "radio_desc"} + ns2 := "client" + + return &client{ + Anomalies: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "anomalies"), + "Client Anomalies", labels, nil, + ), + BytesR: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "bytesr"), + "Client Data Rate", labels, nil, + ), + CCQ: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "ccq"), + "Client Connection Quality", labels, nil, + ), + Noise: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "noise"), + "Client AP Noise", labels, nil, + ), + RoamCount: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "roamcount"), + "Client Roam Counter", labels, nil, + ), + RSSI: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "rssi"), + "Client RSSI", labels, nil, + ), + RxBytes: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "rxbytes"), + "Client Receive Bytes", labels, nil, + ), + RxBytesR: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "rxbytesr"), + "Client Receive Data Rate", labels, nil, + ), + RxPackets: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "rxpackets"), + "Client Receive Packets", labels, nil, + ), + RxRate: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "rxrate"), + "Client Receive Rate", labels, nil, + ), + Signal: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "signal"), + "Client Signal Strength", labels, nil, + ), + TxBytes: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "txbytes"), + "Client Transmit Bytes", labels, nil, + ), + TxBytesR: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "txbytesr"), + "Client Transmit Data Rate", labels, nil, + ), + TxPackets: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "txpackets"), + "Client Transmit Packets", labels, nil, + ), + TxPower: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "txpower"), + "Client Transmit Power", labels, nil, + ), + TxRate: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "txrate"), + "Client Transmit Rate", labels, nil, + ), + Uptime: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "uptime"), + "Client Uptime", labels, nil, + ), + WifiTxAttempts: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "wifitxattempts"), + "Client Wifi Transmit Attempts", labels, nil, + ), + WiredRxBytes: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "wiredrxbytes"), + "Client Wired Receive Bytes", labels, nil, + ), + WiredRxBytesR: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "wiredrxbytesr"), + "Client Wired Receive Data Rate", labels, nil, + ), + WiredRxPackets: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "wiredrxpackets"), + "Client Wired Receive Packets", labels, nil, + ), + WiredTxBytes: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "wiredtxbytes"), + "Client Wired Transmit Bytes", labels, nil, + ), + WiredTxBytesR: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "wiredtxbytesr"), + "Client Wired Data Rate", labels, nil, + ), + WiredTxPackets: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "wiredtxpackets"), + "Client Wired Transmit Packets", labels, nil, + ), + DpiStatsApp: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "dpistatsapp"), + "Client DPI Stats App", labels, nil, + ), + DpiStatsCat: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "dpistatscat"), + "Client DPI Stats Cat", labels, nil, + ), + DpiStatsRxBytes: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "dpistatsrxbytes"), + "Client DPI Stats Receive Bytes", labels, nil, + ), + DpiStatsRxPackets: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "dpistatsrxpackets"), + "Client DPI Stats Receive Packets", labels, nil, + ), + DpiStatsTxBytes: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "dpistatstxbytes"), + "Client DPI Stats Transmit Bytes", labels, nil, + ), + DpiStatsTxPackets: prometheus.NewDesc( + prometheus.BuildFQName(ns, ns2, "dpistatstxpackets"), + "Client DPI Stats Transmit Packets", labels, nil, + ), + } +} + +// CollectClient exports Clients' Data +func (u *unifiCollector) exportClient(c *unifi.Client) []*metricExports { + labels := []string{c.ID, c.Mac, c.UserID, c.SiteID, c.SiteName, + c.NetworkID, c.ApMac, c.GwMac, c.SwMac, c.ApName, c.GwName, + c.SwName, c.RadioName, c.Radio, c.RadioProto, c.Name, c.Channel.Txt, + c.Vlan.Txt, c.IP, c.Essid, c.Bssid, c.RadioDescription, + } + + return []*metricExports{ + {u.Client.Anomalies, prometheus.CounterValue, c.Anomalies, labels}, + {u.Client.Anomalies, prometheus.CounterValue, c.Anomalies, labels}, + {u.Client.BytesR, prometheus.GaugeValue, c.BytesR, labels}, + {u.Client.CCQ, prometheus.GaugeValue, c.Ccq, labels}, + {u.Client.Noise, prometheus.GaugeValue, c.Noise, labels}, + {u.Client.RoamCount, prometheus.CounterValue, c.RoamCount, labels}, + {u.Client.RSSI, prometheus.GaugeValue, c.Rssi, labels}, + {u.Client.RxBytes, prometheus.CounterValue, c.RxBytes, labels}, + {u.Client.RxBytesR, prometheus.GaugeValue, c.RxBytesR, labels}, + {u.Client.RxPackets, prometheus.CounterValue, c.RxPackets, labels}, + {u.Client.RxRate, prometheus.GaugeValue, c.RxRate, labels}, + {u.Client.Signal, prometheus.GaugeValue, c.Signal, labels}, + {u.Client.TxBytes, prometheus.CounterValue, c.TxBytes, labels}, + {u.Client.TxBytesR, prometheus.GaugeValue, c.TxBytesR, labels}, + {u.Client.TxPackets, prometheus.CounterValue, c.TxPackets, labels}, + {u.Client.TxPower, prometheus.GaugeValue, c.TxPower, labels}, + {u.Client.TxRate, prometheus.CounterValue, c.TxRate, labels}, + {u.Client.Uptime, prometheus.GaugeValue, c.Uptime, labels}, + {u.Client.WifiTxAttempts, prometheus.CounterValue, c.WifiTxAttempts, labels}, + {u.Client.WiredRxBytes, prometheus.CounterValue, c.WiredRxBytes, labels}, + {u.Client.WiredRxBytesR, prometheus.GaugeValue, c.WiredRxBytesR, labels}, + {u.Client.WiredRxPackets, prometheus.CounterValue, c.WiredRxPackets, labels}, + {u.Client.WiredTxBytes, prometheus.CounterValue, c.TxRate, labels}, + {u.Client.WiredTxBytesR, prometheus.GaugeValue, c.WiredTxBytesR, labels}, + {u.Client.WiredTxPackets, prometheus.CounterValue, c.WiredTxPackets, labels}, + {u.Client.DpiStatsApp, prometheus.GaugeValue, c.DpiStats.App, labels}, + {u.Client.DpiStatsCat, prometheus.GaugeValue, c.DpiStats.Cat, labels}, + {u.Client.DpiStatsRxBytes, prometheus.CounterValue, c.DpiStats.RxBytes, labels}, + {u.Client.DpiStatsRxPackets, prometheus.CounterValue, c.DpiStats.RxPackets, labels}, + {u.Client.DpiStatsTxBytes, prometheus.CounterValue, c.DpiStats.TxBytes, labels}, + {u.Client.DpiStatsTxPackets, prometheus.CounterValue, c.DpiStats.TxPackets, labels}, + } +} diff --git a/promunifi/collector.go b/promunifi/collector.go new file mode 100644 index 00000000..9487231b --- /dev/null +++ b/promunifi/collector.go @@ -0,0 +1,135 @@ +package promunifi + +import ( + "fmt" + "reflect" + "time" + + "github.com/davidnewhall/unifi-poller/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +// UnifiCollectorOpts defines the data needed to collect and report UniFi Metrics. +type UnifiCollectorOpts struct { + // If non-empty, each of the collected metrics is prefixed by the + // provided string and an underscore ("_"). + Namespace string + // If true, any error encountered during collection is reported as an + // invalid metric (see NewInvalidMetric). Otherwise, errors are ignored + // and the collected metrics will be incomplete. (Possibly, no metrics + // will be collected at all.) + ReportErrors bool + // This function is passed to the Collect() method. The Collect method runs This + // function to retreive the latest UniFi + CollectFn func() *metrics.Metrics + // Setting this to true will enable IDS exports. + CollectIDS bool +} + +type unifiCollector struct { + opts UnifiCollectorOpts + Client *client + // UAP *UAP + // USG *USG + // USW *USW + // UDM *UDM + // IDS *IDS + // Site *Site +} + +type metricExports struct { + Desc *prometheus.Desc + ValueType prometheus.ValueType + Value interface{} + Labels []string +} + +// NewUnifiCollector returns a prometheus collector that will export any available +// UniFi metrics. You must provide a collection function in the opts. +func NewUnifiCollector(opts UnifiCollectorOpts) prometheus.Collector { + if opts.CollectFn == nil { + panic("nil collector function") + } + return &unifiCollector{ + opts: opts, + Client: descClient(opts.Namespace), + // UAP: descUAP(opts.Namespace), + // USG: descUSG(opts.Namespace), + // USW: descUSW(opts.Namespace), + // UDM: descUDM(opts.Namespace), + // Site: descSite(opts.Namespace), + // IDS: descIDS(opts.Namespace), + } +} + +// 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.ValueOf(from) + // 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) + if ok && desc != nil { + ch <- desc + } + } + } + describe(u.Client) + // describe(u.UAP) + // describe(u.USG) + // describe(u.USW) + // describe(u.UDM) + // describe(u.Site) + // if u.opts.CollectIDS { + // describe(u.IDS) + // } +} + +// Collect satisifes 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) { + m := u.opts.CollectFn() + + for _, asset := range m.Clients { + u.export(ch, u.exportClient(asset), m.TS) + } + for _, asset := range m.Sites { + u.export(ch, u.exportSite(asset), m.TS) + } + if u.opts.CollectIDS { + for _, asset := range m.IDSList { + u.export(ch, u.exportIDS(asset), m.TS) + } + } + + if m.Devices == nil { + return + } + + for _, asset := range m.Devices.UAPs { + u.export(ch, u.exportUAP(asset), m.TS) + } + for _, asset := range m.Devices.USGs { + u.export(ch, u.exportUSG(asset), m.TS) + } + for _, asset := range m.Devices.USWs { + u.export(ch, u.exportUSW(asset), m.TS) + } + for _, asset := range m.Devices.UDMs { + u.export(ch, u.exportUDM(asset), m.TS) + } +} + +func (u *unifiCollector) export(ch chan<- prometheus.Metric, exports []*metricExports, ts time.Time) { + for _, e := range exports { + v, ok := e.Value.(float64) + if !ok { + if u.opts.ReportErrors { + ch <- prometheus.NewInvalidMetric(e.Desc, fmt.Errorf("not a number")) + } + return + } + ch <- prometheus.NewMetricWithTimestamp(ts, prometheus.MustNewConstMetric(e.Desc, e.ValueType, v, e.Labels...)) + } +} diff --git a/promunifi/ids.go b/promunifi/ids.go new file mode 100644 index 00000000..f49639e7 --- /dev/null +++ b/promunifi/ids.go @@ -0,0 +1,10 @@ +package promunifi + +import ( + "golift.io/unifi" +) + +// exportIDS exports Intrusion Detection System Data +func (u *unifiCollector) exportIDS(i *unifi.IDS) []*metricExports { + return nil +} diff --git a/promunifi/site.go b/promunifi/site.go new file mode 100644 index 00000000..03af7aa0 --- /dev/null +++ b/promunifi/site.go @@ -0,0 +1,10 @@ +package promunifi + +import ( + "golift.io/unifi" +) + +// exportSite exports Network Site Data +func (u *unifiCollector) exportSite(s *unifi.Site) []*metricExports { + return nil +} diff --git a/promunifi/uap.go b/promunifi/uap.go new file mode 100644 index 00000000..2608f3f4 --- /dev/null +++ b/promunifi/uap.go @@ -0,0 +1,10 @@ +package promunifi + +import ( + "golift.io/unifi" +) + +// exportUAP exports Access Point Data +func (u *unifiCollector) exportUAP(a *unifi.UAP) []*metricExports { + return nil +} diff --git a/promunifi/udm.go b/promunifi/udm.go new file mode 100644 index 00000000..dc9e6c4a --- /dev/null +++ b/promunifi/udm.go @@ -0,0 +1,10 @@ +package promunifi + +import ( + "golift.io/unifi" +) + +// exportUDM exports UniFi Dream Machine (and Pro) Data +func (u *unifiCollector) exportUDM(d *unifi.UDM) []*metricExports { + return nil +} diff --git a/promunifi/usg.go b/promunifi/usg.go new file mode 100644 index 00000000..240c0bdf --- /dev/null +++ b/promunifi/usg.go @@ -0,0 +1,10 @@ +package promunifi + +import ( + "golift.io/unifi" +) + +// exportUSG Exports Security Gateway Data +func (u *unifiCollector) exportUSG(s *unifi.USG) []*metricExports { + return nil +} diff --git a/promunifi/usw.go b/promunifi/usw.go new file mode 100644 index 00000000..d190f8f7 --- /dev/null +++ b/promunifi/usw.go @@ -0,0 +1,10 @@ +package promunifi + +import ( + "golift.io/unifi" +) + +// exportUSW exports Network Switch Data +func (u *unifiCollector) exportUSW(s *unifi.USW) []*metricExports { + return nil +}