convert input to plugin
This commit is contained in:
parent
4e48247f54
commit
0b8473657e
|
|
@ -11,7 +11,7 @@ HBREPO="golift/homebrew-mugs"
|
|||
MAINT="David Newhall II <david at sleepers dot pro>"
|
||||
VENDOR="Go Lift <code at golift dot io>"
|
||||
DESC="Polls a UniFi controller, exports metrics to InfluxDB and Prometheus"
|
||||
GOLANGCI_LINT_ARGS="--enable-all -D gochecknoglobals -D dupl -D lll -D funlen -D wsl -e G402 -D gochecknoinits"
|
||||
GOLANGCI_LINT_ARGS="--enable-all -D gochecknoglobals -D funlen -e G402 -D gochecknoinits"
|
||||
# Example must exist at examples/$CONFIG_FILE.example
|
||||
CONFIG_FILE="up.conf"
|
||||
LICENSE="MIT"
|
||||
|
|
|
|||
4
main.go
4
main.go
|
|
@ -4,7 +4,9 @@ import (
|
|||
"log"
|
||||
|
||||
"github.com/davidnewhall/unifi-poller/pkg/poller"
|
||||
// Enable output plugins!
|
||||
// Load input plugins!
|
||||
_ "github.com/davidnewhall/unifi-poller/pkg/inputunifi"
|
||||
// Load output plugins!
|
||||
_ "github.com/davidnewhall/unifi-poller/pkg/influxunifi"
|
||||
_ "github.com/davidnewhall/unifi-poller/pkg/promunifi"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -66,14 +66,7 @@ func (u *InfluxUnifi) batchClient(r report, s *unifi.Client) {
|
|||
"wired-tx_bytes": s.WiredTxBytes,
|
||||
"wired-tx_bytes-r": s.WiredTxBytesR,
|
||||
"wired-tx_packets": s.WiredTxPackets,
|
||||
/*
|
||||
"dpi_app": c.DpiStats.App.Val,
|
||||
"dpi_cat": c.DpiStats.Cat.Val,
|
||||
"dpi_rx_bytes": c.DpiStats.RxBytes.Val,
|
||||
"dpi_rx_packets": c.DpiStats.RxPackets.Val,
|
||||
"dpi_tx_bytes": c.DpiStats.TxBytes.Val,
|
||||
"dpi_tx_packets": c.DpiStats.TxPackets.Val,
|
||||
*/
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "clients", Tags: tags, Fields: fields})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,5 +35,6 @@ func (u *InfluxUnifi) batchIDS(r report, i *unifi.IDS) {
|
|||
"srcipASN": i.SrcipASN,
|
||||
"usgipASN": i.UsgipASN,
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "intrusion_detect", Tags: tags, Fields: fields})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const (
|
|||
defaultInterval = 30 * time.Second
|
||||
minimumInterval = 10 * time.Second
|
||||
defaultInfluxDB = "unifi"
|
||||
defaultInfluxUser = "unifi"
|
||||
defaultInfluxUser = "unifipoller"
|
||||
defaultInfluxURL = "http://127.0.0.1:8086"
|
||||
)
|
||||
|
||||
|
|
@ -53,6 +53,7 @@ type metric struct {
|
|||
|
||||
func init() {
|
||||
u := &InfluxUnifi{InfluxDB: &InfluxDB{}, LastCheck: time.Now()}
|
||||
|
||||
poller.NewOutput(&poller.Output{
|
||||
Name: "influxdb",
|
||||
Config: u.InfluxDB,
|
||||
|
|
@ -143,9 +144,12 @@ func (u *InfluxUnifi) setConfigDefaults() {
|
|||
func (u *InfluxUnifi) ReportMetrics(m *poller.Metrics) (*Report, error) {
|
||||
r := &Report{Metrics: m, ch: make(chan *metric), Start: time.Now()}
|
||||
defer close(r.ch)
|
||||
// Make a new Influx Points Batcher.
|
||||
|
||||
var err error
|
||||
|
||||
// Make a new Influx Points Batcher.
|
||||
r.bp, err = influx.NewBatchPoints(influx.BatchPointsConfig{Database: u.Config.DB})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("influx.NewBatchPoints: %v", err)
|
||||
}
|
||||
|
|
@ -159,7 +163,9 @@ func (u *InfluxUnifi) ReportMetrics(m *poller.Metrics) (*Report, error) {
|
|||
if err = u.influx.Write(r.bp); err != nil {
|
||||
return nil, fmt.Errorf("influxdb.Write(points): %v", err)
|
||||
}
|
||||
|
||||
r.Elapsed = time.Since(r.Start)
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +178,7 @@ func (u *InfluxUnifi) collect(r report, ch chan *metric) {
|
|||
} else {
|
||||
r.batch(m, pt)
|
||||
}
|
||||
|
||||
r.done()
|
||||
}
|
||||
}
|
||||
|
|
@ -182,24 +189,28 @@ func (u *InfluxUnifi) loopPoints(r report) {
|
|||
m := r.metrics()
|
||||
|
||||
r.add()
|
||||
r.add()
|
||||
r.add()
|
||||
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.Sites {
|
||||
u.batchSite(r, s)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.Clients {
|
||||
u.batchClient(r, s)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.IDSList {
|
||||
u.batchIDS(r, s)
|
||||
}
|
||||
|
|
@ -209,33 +220,44 @@ func (u *InfluxUnifi) loopPoints(r report) {
|
|||
return
|
||||
}
|
||||
|
||||
u.loopDevicePoints(r)
|
||||
}
|
||||
|
||||
func (u *InfluxUnifi) loopDevicePoints(r report) {
|
||||
m := r.metrics()
|
||||
|
||||
r.add()
|
||||
r.add()
|
||||
r.add()
|
||||
r.add()
|
||||
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.UAPs {
|
||||
u.batchUAP(r, s)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.USGs {
|
||||
u.batchUSG(r, s)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.USWs {
|
||||
u.batchUSW(r, s)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.UDMs {
|
||||
u.batchUDM(r, s)
|
||||
}
|
||||
|
|
@ -51,6 +51,7 @@ func (u *InfluxUnifi) batchSite(r report, s *unifi.Site) {
|
|||
"remote_user_tx_packets": h.RemoteUserTxPackets.Val,
|
||||
"num_new_alarms": s.NumNewAlarms.Val,
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "subsystems", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ func (u *InfluxUnifi) batchUAP(r report, s *unifi.UAP) {
|
|||
if !s.Adopted.Val || s.Locating.Val {
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
|
|
@ -30,6 +31,7 @@ func (u *InfluxUnifi) batchUAP(r report, s *unifi.UAP) {
|
|||
fields["user-num_sta"] = int(s.UserNumSta.Val)
|
||||
fields["guest-num_sta"] = int(s.GuestNumSta.Val)
|
||||
fields["num_sta"] = s.NumSta.Val
|
||||
|
||||
r.send(&metric{Table: "uap", Tags: tags, Fields: fields})
|
||||
u.processRadTable(r, tags, s.RadioTable, s.RadioTableStats)
|
||||
u.processVAPTable(r, tags, s.VapTable)
|
||||
|
|
@ -39,6 +41,7 @@ func (u *InfluxUnifi) processUAPstats(ap *unifi.Ap) map[string]interface{} {
|
|||
if ap == nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
// Accumulative Statistics.
|
||||
return map[string]interface{}{
|
||||
"stat_user-rx_packets": ap.UserRxPackets.Val,
|
||||
|
|
@ -135,6 +138,7 @@ func (u *InfluxUnifi) processVAPTable(r report, t map[string]string, vt unifi.Va
|
|||
"wifi_tx_latency_mov_total": s.WifiTxLatencyMov.Total.Val,
|
||||
"wifi_tx_latency_mov_cuont": s.WifiTxLatencyMov.TotalCount.Val,
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "uap_vaps", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
|
@ -155,6 +159,7 @@ func (u *InfluxUnifi) processRadTable(r report, t map[string]string, rt unifi.Ra
|
|||
"nss": p.Nss.Val,
|
||||
"radio_caps": p.RadioCaps.Val,
|
||||
}
|
||||
|
||||
for _, t := range rts {
|
||||
if t.Name == p.Name {
|
||||
fields["ast_be_xmit"] = t.AstBeXmit.Val
|
||||
|
|
@ -171,9 +176,11 @@ func (u *InfluxUnifi) processRadTable(r report, t map[string]string, rt unifi.Ra
|
|||
fields["tx_power"] = t.TxPower.Val
|
||||
fields["tx_retries"] = t.TxRetries.Val
|
||||
fields["user-num_sta"] = t.UserNumSta.Val
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "uap_radios", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,16 @@ import (
|
|||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// Combines concatenates N maps. This will delete things if not used with caution.
|
||||
// Combine concatenates N maps. This will delete things if not used with caution.
|
||||
func Combine(in ...map[string]interface{}) map[string]interface{} {
|
||||
out := make(map[string]interface{})
|
||||
|
||||
for i := range in {
|
||||
for k := range in[i] {
|
||||
out[k] = in[i][k]
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +38,7 @@ func (u *InfluxUnifi) batchUDM(r report, s *unifi.UDM) {
|
|||
if !s.Adopted.Val || s.Locating.Val {
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
|
|
@ -65,6 +68,7 @@ func (u *InfluxUnifi) batchUDM(r report, s *unifi.UDM) {
|
|||
"num_mobile": s.NumMobile.Val,
|
||||
},
|
||||
)
|
||||
|
||||
r.send(&metric{Table: "usg", Tags: tags, Fields: fields})
|
||||
u.batchNetTable(r, tags, s.NetworkTable)
|
||||
u.batchUSGwans(r, tags, s.Wan1, s.Wan2)
|
||||
|
|
@ -90,13 +94,14 @@ func (u *InfluxUnifi) batchUDM(r report, s *unifi.UDM) {
|
|||
"uptime": s.Uptime.Val,
|
||||
"state": s.State.Val,
|
||||
})
|
||||
|
||||
r.send(&metric{Table: "usw", Tags: tags, Fields: fields})
|
||||
u.batchPortTable(r, tags, s.PortTable)
|
||||
|
||||
if s.Stat.Ap == nil {
|
||||
return
|
||||
// we're done now. the following code process UDM (non-pro) UAP data.
|
||||
return // we're done now. the following code process UDM (non-pro) UAP data.
|
||||
}
|
||||
|
||||
tags = map[string]string{
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
|
|
@ -117,6 +122,7 @@ func (u *InfluxUnifi) batchUDM(r report, s *unifi.UDM) {
|
|||
fields["user-num_sta"] = int(s.UserNumSta.Val)
|
||||
fields["guest-num_sta"] = int(s.GuestNumSta.Val)
|
||||
fields["num_sta"] = s.NumSta.Val
|
||||
|
||||
r.send(&metric{Table: "uap", Tags: tags, Fields: fields})
|
||||
u.processRadTable(r, tags, *s.RadioTable, *s.RadioTableStats)
|
||||
u.processVAPTable(r, tags, *s.VapTable)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ func (u *InfluxUnifi) batchUSG(r report, s *unifi.USG) {
|
|||
if !s.Adopted.Val || s.Locating.Val {
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
|
|
@ -39,44 +40,17 @@ func (u *InfluxUnifi) batchUSG(r report, s *unifi.USG) {
|
|||
"num_mobile": s.NumMobile.Val,
|
||||
},
|
||||
)
|
||||
|
||||
r.send(&metric{Table: "usg", Tags: tags, Fields: fields})
|
||||
u.batchNetTable(r, tags, s.NetworkTable)
|
||||
u.batchUSGwans(r, tags, s.Wan1, s.Wan2)
|
||||
}
|
||||
|
||||
/*
|
||||
for _, p := range s.PortTable {
|
||||
t := map[string]string{
|
||||
"device_name": tags["name"],
|
||||
"site_name": tags["site_name"],
|
||||
"name": p.Name,
|
||||
"ifname": p.Ifname,
|
||||
"ip": p.IP,
|
||||
"mac": p.Mac,
|
||||
"up": p.Up.Txt,
|
||||
"speed": p.Speed.Txt,
|
||||
"full_duplex": p.FullDuplex.Txt,
|
||||
"enable": p.Enable.Txt,
|
||||
}
|
||||
f := map[string]interface{}{
|
||||
"rx_bytes": p.RxBytes.Val,
|
||||
"rx_dropped": p.RxDropped.Val,
|
||||
"rx_errors": p.RxErrors.Val,
|
||||
"rx_packets": p.RxBytes.Val,
|
||||
"tx_bytes": p.TxBytes.Val,
|
||||
"tx_dropped": p.TxDropped.Val,
|
||||
"tx_errors": p.TxErrors.Val,
|
||||
"tx_packets": p.TxPackets.Val,
|
||||
"rx_multicast": p.RxMulticast.Val,
|
||||
"dns_servers": strings.Join(p.DNS, ","),
|
||||
}
|
||||
r.send(&metric{Table: "usg_ports", Tags: t, Fields: f})
|
||||
}
|
||||
*/
|
||||
}
|
||||
func (u *InfluxUnifi) batchUSGstat(ss unifi.SpeedtestStatus, gw *unifi.Gw, ul unifi.Uplink) map[string]interface{} {
|
||||
if gw == nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"uplink_latency": ul.Latency.Val,
|
||||
"uplink_speed": ul.Speed.Val,
|
||||
|
|
@ -92,11 +66,13 @@ func (u *InfluxUnifi) batchUSGstat(ss unifi.SpeedtestStatus, gw *unifi.Gw, ul un
|
|||
"lan-rx_dropped": gw.LanRxDropped.Val,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *InfluxUnifi) batchUSGwans(r report, tags map[string]string, wans ...unifi.Wan) {
|
||||
for _, wan := range wans {
|
||||
if !wan.Up.Val {
|
||||
continue
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"device_name": tags["name"],
|
||||
"site_name": tags["site_name"],
|
||||
|
|
@ -129,6 +105,7 @@ func (u *InfluxUnifi) batchUSGwans(r report, tags map[string]string, wans ...uni
|
|||
"tx_broadcast": wan.TxBroadcast.Val,
|
||||
"tx_multicast": wan.TxMulticast.Val,
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "usg_wan_ports", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
|
@ -154,6 +131,7 @@ func (u *InfluxUnifi) batchNetTable(r report, tags map[string]string, nt unifi.N
|
|||
"tx_bytes": p.TxBytes.Val,
|
||||
"tx_packets": p.TxPackets.Val,
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "usg_networks", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ func (u *InfluxUnifi) batchUSW(r report, s *unifi.USW) {
|
|||
"state": s.State.Val,
|
||||
"user-num_sta": s.UserNumSta.Val,
|
||||
})
|
||||
|
||||
r.send(&metric{Table: "usw", Tags: tags, Fields: fields})
|
||||
u.batchPortTable(r, tags, s.PortTable)
|
||||
}
|
||||
|
|
@ -44,6 +45,7 @@ func (u *InfluxUnifi) batchUSWstat(sw *unifi.Sw) map[string]interface{} {
|
|||
if sw == nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"stat_bytes": sw.Bytes.Val,
|
||||
"stat_rx_bytes": sw.RxBytes.Val,
|
||||
|
|
@ -59,11 +61,13 @@ func (u *InfluxUnifi) batchUSWstat(sw *unifi.Sw) map[string]interface{} {
|
|||
"stat_tx_retries": sw.TxRetries.Val,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *InfluxUnifi) batchPortTable(r report, t map[string]string, pt []unifi.Port) {
|
||||
for _, p := range pt {
|
||||
if !p.Up.Val || !p.Enable.Val {
|
||||
continue // only record UP ports.
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"site_name": t["site_name"],
|
||||
"device_name": t["name"],
|
||||
|
|
@ -96,11 +100,13 @@ func (u *InfluxUnifi) batchPortTable(r report, t map[string]string, pt []unifi.P
|
|||
"tx_multicast": p.TxMulticast.Val,
|
||||
"tx_packets": p.TxPackets.Val,
|
||||
}
|
||||
|
||||
if p.PoeEnable.Val && p.PortPoe.Val {
|
||||
fields["poe_current"] = p.PoeCurrent.Val
|
||||
fields["poe_power"] = p.PoePower.Val
|
||||
fields["poe_voltage"] = p.PoeVoltage.Val
|
||||
}
|
||||
|
||||
r.send(&metric{Table: "usw_ports", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
package inputunifi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/davidnewhall/unifi-poller/pkg/poller"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
func (u *InputUnifi) isNill(c Controller) bool {
|
||||
u.Config.RLock()
|
||||
defer u.Config.RUnlock()
|
||||
|
||||
return c.Unifi == nil
|
||||
}
|
||||
|
||||
func (u *InputUnifi) collectController(c Controller) (*poller.Metrics, error) {
|
||||
if u.isNill(c) {
|
||||
u.Logf("Re-authenticating to UniFi Controller: %s", c.URL)
|
||||
|
||||
if err := u.getUnifi(c); err != nil {
|
||||
return nil, fmt.Errorf("re-authenticating to %s: %v", c.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
m, err := u.pollController(c)
|
||||
if err == nil {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
return u.pollController(c)
|
||||
}
|
||||
|
||||
func (u *InputUnifi) pollController(c Controller) (*poller.Metrics, error) {
|
||||
var err error
|
||||
|
||||
u.Config.RLock()
|
||||
defer u.Config.RUnlock()
|
||||
|
||||
m := &poller.Metrics{TS: time.Now()} // At this point, it's the Current Check.
|
||||
|
||||
// Get the sites we care about.
|
||||
if m.Sites, err = u.getFilteredSites(c); err != nil {
|
||||
return m, fmt.Errorf("unifi.GetSites(%v): %v", c.URL, err)
|
||||
}
|
||||
|
||||
if c.SaveIDS {
|
||||
m.IDSList, err = c.Unifi.GetIDS(m.Sites, time.Now().Add(2*time.Minute), time.Now())
|
||||
if err != nil {
|
||||
return m, fmt.Errorf("unifi.GetIDS(%v): %v", c.URL, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all the points.
|
||||
if m.Clients, err = c.Unifi.GetClients(m.Sites); err != nil {
|
||||
return m, fmt.Errorf("unifi.GetClients(%v): %v", c.URL, err)
|
||||
}
|
||||
|
||||
if m.Devices, err = c.Unifi.GetDevices(m.Sites); err != nil {
|
||||
return m, fmt.Errorf("unifi.GetDevices(%v): %v", c.URL, err)
|
||||
}
|
||||
|
||||
return u.augmentMetrics(c, m), nil
|
||||
}
|
||||
|
||||
// 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 *InputUnifi) augmentMetrics(c Controller, metrics *poller.Metrics) *poller.Metrics {
|
||||
if metrics == nil || metrics.Devices == nil || metrics.Clients == nil {
|
||||
return metrics
|
||||
}
|
||||
|
||||
devices := make(map[string]string)
|
||||
bssdIDs := make(map[string]string)
|
||||
|
||||
for _, r := range metrics.UAPs {
|
||||
devices[r.Mac] = r.Name
|
||||
|
||||
for _, v := range r.VapTable {
|
||||
bssdIDs[v.Bssid] = fmt.Sprintf("%s %s %s:", r.Name, v.Radio, v.RadioName)
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range metrics.USGs {
|
||||
devices[r.Mac] = r.Name
|
||||
}
|
||||
|
||||
for _, r := range metrics.USWs {
|
||||
devices[r.Mac] = r.Name
|
||||
}
|
||||
|
||||
for _, r := range metrics.UDMs {
|
||||
devices[r.Mac] = r.Name
|
||||
}
|
||||
|
||||
// These come blank, so set them here.
|
||||
for i, c := range metrics.Clients {
|
||||
metrics.Clients[i].SwName = devices[c.SwMac]
|
||||
metrics.Clients[i].ApName = devices[c.ApMac]
|
||||
metrics.Clients[i].GwName = devices[c.GwMac]
|
||||
metrics.Clients[i].RadioDescription = bssdIDs[metrics.Clients[i].Bssid] + metrics.Clients[i].RadioProto
|
||||
}
|
||||
|
||||
if !c.SaveSites {
|
||||
metrics.Sites = nil
|
||||
}
|
||||
|
||||
return metrics
|
||||
}
|
||||
|
||||
// getFilteredSites returns a list of sites to fetch data for.
|
||||
// Omits requested but unconfigured sites. Grabs the full list from the
|
||||
// controller and returns the sites provided in the config file.
|
||||
func (u *InputUnifi) getFilteredSites(c Controller) (unifi.Sites, error) {
|
||||
u.Config.RLock()
|
||||
defer u.Config.RUnlock()
|
||||
|
||||
sites, err := c.Unifi.GetSites()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(c.Sites) < 1 || poller.StringInSlice("all", c.Sites) {
|
||||
return sites, nil
|
||||
}
|
||||
|
||||
var i int
|
||||
|
||||
for _, s := range sites {
|
||||
// Only include valid sites in the request filter.
|
||||
if poller.StringInSlice(s.Name, c.Sites) {
|
||||
sites[i] = s
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
return sites[:i], nil
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Package inputunifi implements the poller.Input interface and bridges the gap between
|
||||
// metrics from the unifi library, and the augments required to pump them into unifi-poller.
|
||||
package inputunifi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/davidnewhall/unifi-poller/pkg/poller"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// InputUnifi contains the running data.
|
||||
type InputUnifi struct {
|
||||
Config Config `json:"unifi" toml:"unifi" xml:"unifi" yaml:"unifi"`
|
||||
poller.Logger
|
||||
}
|
||||
|
||||
// Controller represents the configuration for a UniFi Controller.
|
||||
// Each polled controller may have its own configuration.
|
||||
type Controller struct {
|
||||
VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"`
|
||||
SaveIDS bool `json:"save_ids" toml:"save_ids" xml:"save_ids" yaml:"save_ids"`
|
||||
SaveSites bool `json:"save_sites" toml:"save_sites" xml:"save_sites" yaml:"save_sites"`
|
||||
Name string `json:"name" toml:"name" xml:"name,attr" yaml:"name"`
|
||||
User string `json:"user" toml:"user" xml:"user" yaml:"user"`
|
||||
Pass string `json:"pass" toml:"pass" xml:"pass" yaml:"pass"`
|
||||
URL string `json:"url" toml:"url" xml:"url" yaml:"url"`
|
||||
Sites []string `json:"sites,omitempty" toml:"sites,omitempty" xml:"sites" yaml:"sites"`
|
||||
Unifi *unifi.Unifi `json:"-" toml:"-" xml:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
// Config contains our configuration data
|
||||
type Config struct {
|
||||
sync.RWMutex // locks the Unifi struct member when re-authing to unifi.
|
||||
Disable bool `json:"disable" toml:"disable" xml:"disable" yaml:"disable"`
|
||||
Controllers []Controller `json:"controller" toml:"controller" xml:"controller" yaml:"controller"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
u := &InputUnifi{}
|
||||
|
||||
poller.NewInput(&poller.InputPlugin{
|
||||
Input: u, // this library implements poller.Input interface for Metrics().
|
||||
Config: u, // Defines our config data interface.
|
||||
})
|
||||
}
|
||||
|
||||
// getUnifi (re-)authenticates to a unifi controller.
|
||||
func (u *InputUnifi) getUnifi(c Controller) error {
|
||||
var err error
|
||||
|
||||
u.Config.Lock()
|
||||
defer u.Config.Unlock()
|
||||
|
||||
if c.Unifi != nil {
|
||||
c.Unifi.CloseIdleConnections()
|
||||
}
|
||||
|
||||
// Create an authenticated session to the Unifi Controller.
|
||||
c.Unifi, err = unifi.NewUnifi(&unifi.Config{
|
||||
User: c.User,
|
||||
Pass: c.Pass,
|
||||
URL: c.URL,
|
||||
VerifySSL: c.VerifySSL,
|
||||
ErrorLog: u.LogErrorf, // Log all errors.
|
||||
DebugLog: u.LogDebugf, // Log debug messages.
|
||||
})
|
||||
if err != nil {
|
||||
c.Unifi = nil
|
||||
return fmt.Errorf("unifi controller: %v", err)
|
||||
}
|
||||
|
||||
u.LogDebugf("Authenticated with controller successfully, %s", c.URL)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package inputunifi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/davidnewhall/unifi-poller/pkg/poller"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// Metrics grabs all the measurements from a UniFi controller and returns them.
|
||||
func (u *InputUnifi) Metrics() (*poller.Metrics, error) {
|
||||
errs := []string{}
|
||||
metrics := &poller.Metrics{}
|
||||
|
||||
for _, c := range u.Config.Controllers {
|
||||
m, err := u.collectController(c)
|
||||
if err != nil {
|
||||
errs = append(errs, err.Error())
|
||||
}
|
||||
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
metrics.Sites = append(metrics.Sites, m.Sites...)
|
||||
metrics.Clients = append(metrics.Clients, m.Clients...)
|
||||
metrics.IDSList = append(metrics.IDSList, m.IDSList...)
|
||||
|
||||
if m.Devices == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if metrics.Devices == nil {
|
||||
metrics.Devices = &unifi.Devices{}
|
||||
}
|
||||
|
||||
metrics.UAPs = append(metrics.UAPs, m.UAPs...)
|
||||
metrics.USGs = append(metrics.USGs, m.USGs...)
|
||||
metrics.USWs = append(metrics.USWs, m.USWs...)
|
||||
metrics.UDMs = append(metrics.UDMs, m.UDMs...)
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return metrics, fmt.Errorf(strings.Join(errs, ", "))
|
||||
}
|
||||
|
||||
return metrics, nil
|
||||
}
|
||||
|
||||
// Initialize gets called one time when starting up.
|
||||
// Satisfies poller.Input interface.
|
||||
func (u *InputUnifi) Initialize(l poller.Logger) error {
|
||||
if u.Config.Disable {
|
||||
l.Logf("unifi input disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(u.Config.Controllers) < 1 {
|
||||
return fmt.Errorf("no unifi controllers defined for unifi input")
|
||||
}
|
||||
|
||||
u.Logger = l
|
||||
|
||||
for i, c := range u.Config.Controllers {
|
||||
if c.Name == "" {
|
||||
u.Config.Controllers[i].Name = c.URL
|
||||
}
|
||||
|
||||
switch err := u.getUnifi(c); err {
|
||||
case nil:
|
||||
if err := u.checkSites(c); err != nil {
|
||||
u.LogErrorf("checking sites on %s: %v", c.Name, err)
|
||||
}
|
||||
|
||||
u.Logf("Polling UniFi Controller at %s v%s as user %s. Sites: %v",
|
||||
c.URL, c.Unifi.ServerVersion, c.User, c.Sites)
|
||||
default:
|
||||
u.LogErrorf("Controller Auth or Connection failed, but continuing to retry! %s: %v", c.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkSites makes sure the list of provided sites exists on the controller.
|
||||
// This only runs once during initialization.
|
||||
func (u *InputUnifi) checkSites(c Controller) error {
|
||||
u.Config.RLock()
|
||||
defer u.Config.RUnlock()
|
||||
u.LogDebugf("Checking Controller Sites List")
|
||||
|
||||
sites, err := c.Unifi.GetSites()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := []string{}
|
||||
|
||||
for _, site := range sites {
|
||||
msg = append(msg, site.Name+" ("+site.Desc+")")
|
||||
}
|
||||
|
||||
u.Logf("Found %d site(s) on controller: %v", len(msg), strings.Join(msg, ", "))
|
||||
|
||||
if poller.StringInSlice("all", c.Sites) {
|
||||
c.Sites = []string{"all"}
|
||||
return nil
|
||||
}
|
||||
|
||||
FIRST:
|
||||
for _, s := range c.Sites {
|
||||
for _, site := range sites {
|
||||
if s == site.Name {
|
||||
continue FIRST
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("configured site not found on controller: %v", s)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
package poller
|
||||
|
||||
// DefaultConfFile is where to find config is --config is not prvided.
|
||||
// DefaultConfFile is where to find config if --config is not prvided.
|
||||
const DefaultConfFile = "/usr/local/etc/unifi-poller/up.conf"
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
package poller
|
||||
|
||||
// DefaultConfFile is where to find config is --config is not prvided.
|
||||
// DefaultConfFile is where to find config if --config is not prvided.
|
||||
const DefaultConfFile = "/etc/unifi-poller/up.conf"
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
package poller
|
||||
|
||||
// DefaultConfFile is where to find config is --config is not prvided.
|
||||
// DefaultConfFile is where to find config if --config is not prvided.
|
||||
const DefaultConfFile = `C:\ProgramData\unifi-poller\up.conf`
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ package poller
|
|||
*/
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
|
@ -17,23 +16,17 @@ import (
|
|||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// App defaults in case they're missing from the config.
|
||||
const (
|
||||
// AppName is the name of the application.
|
||||
AppName = "unifi-poller"
|
||||
defaultUnifiUser = "influx"
|
||||
defaultUnifiURL = "https://127.0.0.1:8443"
|
||||
// ENVConfigPrefix is the prefix appended to an env variable tag name.
|
||||
ENVConfigPrefix = "UP"
|
||||
)
|
||||
|
||||
// ENVConfigPrefix is the prefix appended to an env variable tag
|
||||
// name before retrieving the value from the OS.
|
||||
const ENVConfigPrefix = "UP"
|
||||
|
||||
// UnifiPoller contains the application startup data, and auth info for UniFi & Influx.
|
||||
type UnifiPoller struct {
|
||||
Flags *Flags
|
||||
Config *Config
|
||||
sync.Mutex // locks the Unifi struct member when re-authing to unifi.
|
||||
*Config
|
||||
}
|
||||
|
||||
// Flags represents the CLI args available and their settings.
|
||||
|
|
@ -53,26 +46,9 @@ type Metrics struct {
|
|||
*unifi.Devices
|
||||
}
|
||||
|
||||
// Controller represents the configuration for a UniFi Controller.
|
||||
// Each polled controller may have its own configuration.
|
||||
type Controller struct {
|
||||
VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"`
|
||||
SaveIDS bool `json:"save_ids" toml:"save_ids" xml:"save_ids" yaml:"save_ids"`
|
||||
SaveSites bool `json:"save_sites,omitempty" toml:"save_sites,omitempty" xml:"save_sites" yaml:"save_sites"`
|
||||
Name string `json:"name" toml:"name" xml:"name,attr" yaml:"name"`
|
||||
User string `json:"user,omitempty" toml:"user,omitempty" xml:"user" yaml:"user"`
|
||||
Pass string `json:"pass,omitempty" toml:"pass,omitempty" xml:"pass" yaml:"pass"`
|
||||
URL string `json:"url,omitempty" toml:"url,omitempty" xml:"url" yaml:"url"`
|
||||
Sites []string `json:"sites,omitempty" toml:"sites,omitempty" xml:"sites" yaml:"sites"`
|
||||
Unifi *unifi.Unifi `json:"-" toml:"-" xml:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
// Config represents the data needed to poll a controller and report to influxdb.
|
||||
// This is all of the data stored in the config file.
|
||||
// Any with explicit defaults have omitempty on json and toml tags.
|
||||
// Config represents the core library input data.
|
||||
type Config struct {
|
||||
Poller `json:"poller" toml:"poller" xml:"poller" yaml:"poller"`
|
||||
Controllers []Controller `json:"controller,omitempty" toml:"controller,omitempty" xml:"controller" yaml:"controller"`
|
||||
}
|
||||
|
||||
// Poller is the global config values.
|
||||
|
|
@ -83,31 +59,43 @@ type Poller struct {
|
|||
|
||||
// ParseConfigs parses the poller config and the config for each registered output plugin.
|
||||
func (u *UnifiPoller) ParseConfigs() error {
|
||||
// Parse config file.
|
||||
if err := config.ParseFile(u.Config, u.Flags.ConfigFile); err != nil {
|
||||
u.Flags.Usage()
|
||||
return err
|
||||
}
|
||||
|
||||
// Update Config with ENV variable overrides.
|
||||
if _, err := config.ParseENV(u.Config, ENVConfigPrefix); err != nil {
|
||||
// Parse core config.
|
||||
if err := u.ParseInterface(u.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse output plugin configs.
|
||||
outputSync.Lock()
|
||||
defer outputSync.Unlock()
|
||||
|
||||
for _, o := range outputs {
|
||||
// Parse config file for each output plugin.
|
||||
if err := config.ParseFile(o.Config, u.Flags.ConfigFile); err != nil {
|
||||
if err := u.ParseInterface(o.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update Config for each output with ENV variable overrides.
|
||||
if _, err := config.ParseENV(o.Config, ENVConfigPrefix); err != nil {
|
||||
// Parse input plugin configs.
|
||||
inputSync.Lock()
|
||||
defer inputSync.Unlock()
|
||||
|
||||
for _, i := range inputs {
|
||||
if err := u.ParseInterface(i.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseInterface parses the config file and environment variables into the provided interface.
|
||||
func (u *UnifiPoller) ParseInterface(i interface{}) error {
|
||||
// Parse config file into provided interface.
|
||||
if err := config.ParseFile(i, u.Flags.ConfigFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse environment variables into provided interface.
|
||||
_, err := config.ParseENV(i, ENVConfigPrefix)
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
package poller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// DumpJSONPayload prints raw json from the UniFi Controller.
|
||||
// This only works with controller 0 (first one) in the config.
|
||||
func (u *UnifiPoller) DumpJSONPayload() (err error) {
|
||||
if true {
|
||||
return nil
|
||||
}
|
||||
/*
|
||||
u.Config.Quiet = true
|
||||
config := u.Config.Controllers[0]
|
||||
|
||||
|
|
@ -48,8 +48,11 @@ func (u *UnifiPoller) DumpJSONPayload() (err error) {
|
|||
default:
|
||||
return fmt.Errorf("must provide filter: devices, clients, other")
|
||||
}
|
||||
*/
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (u *UnifiPoller) dumpSitesJSON(c Controller, path, name string, sites unifi.Sites) error {
|
||||
for _, s := range sites {
|
||||
apiPath := fmt.Sprintf(path, s.Name)
|
||||
|
|
@ -68,3 +71,15 @@ func (u *UnifiPoller) PrintRawAPIJSON(c Controller, apiPath string) error {
|
|||
fmt.Println(string(body))
|
||||
return err
|
||||
}
|
||||
*/
|
||||
|
||||
// StringInSlice returns true if a string is in a slice.
|
||||
func StringInSlice(str string, slice []string) bool {
|
||||
for _, s := range slice {
|
||||
if strings.EqualFold(s, str) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package poller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
var (
|
||||
inputs []*InputPlugin
|
||||
inputSync sync.Mutex
|
||||
)
|
||||
|
||||
// Input plugins must implement this interface.
|
||||
type Input interface {
|
||||
Initialize(Logger) error // Called once on startup to initialize the plugin.
|
||||
Metrics() (*Metrics, error) // Called every time new metrics are requested.
|
||||
}
|
||||
|
||||
// InputPlugin describes an input plugin's consumable interface.
|
||||
type InputPlugin struct {
|
||||
Config interface{} // Each config is passed into an unmarshaller later.
|
||||
Input
|
||||
}
|
||||
|
||||
// NewInput creates a metric input. This should be called by input plugins
|
||||
// init() functions.
|
||||
func NewInput(i *InputPlugin) {
|
||||
inputSync.Lock()
|
||||
defer inputSync.Unlock()
|
||||
|
||||
if i == nil || i.Input == nil {
|
||||
panic("nil output or method passed to poller.NewOutput")
|
||||
}
|
||||
|
||||
inputs = append(inputs, i)
|
||||
}
|
||||
|
||||
// InitializeInputs runs the passed-in initializer method for each input plugin.
|
||||
func (u *UnifiPoller) InitializeInputs() error {
|
||||
inputSync.Lock()
|
||||
defer inputSync.Unlock()
|
||||
|
||||
for _, input := range inputs {
|
||||
// This must return, or the app locks up here.
|
||||
if err := input.Initialize(u); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Metrics aggregates all the measurements from all configured inputs and returns them.
|
||||
func (u *UnifiPoller) Metrics() (*Metrics, error) {
|
||||
errs := []string{}
|
||||
metrics := &Metrics{}
|
||||
|
||||
for _, input := range inputs {
|
||||
m, err := input.Metrics()
|
||||
if err != nil {
|
||||
errs = append(errs, err.Error())
|
||||
}
|
||||
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
metrics.Sites = append(metrics.Sites, m.Sites...)
|
||||
metrics.Clients = append(metrics.Clients, m.Clients...)
|
||||
metrics.IDSList = append(metrics.IDSList, m.IDSList...)
|
||||
|
||||
if m.Devices == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if metrics.Devices == nil {
|
||||
metrics.Devices = &unifi.Devices{}
|
||||
}
|
||||
|
||||
metrics.UAPs = append(metrics.UAPs, m.UAPs...)
|
||||
metrics.USGs = append(metrics.USGs, m.USGs...)
|
||||
metrics.USWs = append(metrics.USWs, m.USWs...)
|
||||
metrics.UDMs = append(metrics.UDMs, m.UDMs...)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if len(errs) > 0 {
|
||||
err = fmt.Errorf(strings.Join(errs, ", "))
|
||||
}
|
||||
|
||||
return metrics, err
|
||||
}
|
||||
|
|
@ -3,19 +3,15 @@ package poller
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const callDepth = 2
|
||||
|
||||
// StringInSlice returns true if a string is in a slice.
|
||||
func StringInSlice(str string, slice []string) bool {
|
||||
for _, s := range slice {
|
||||
if strings.EqualFold(s, str) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
// Logger is passed into input packages so they may write logs.
|
||||
type Logger interface {
|
||||
Logf(m string, v ...interface{})
|
||||
LogErrorf(m string, v ...interface{})
|
||||
LogDebugf(m string, v ...interface{})
|
||||
}
|
||||
|
||||
// Logf prints a log entry if quiet is false.
|
||||
|
|
@ -14,9 +14,7 @@ var (
|
|||
// Output packages must implement this interface.
|
||||
type Collect interface {
|
||||
Metrics() (*Metrics, error)
|
||||
Logf(m string, v ...interface{})
|
||||
LogErrorf(m string, v ...interface{})
|
||||
LogDebugf(m string, v ...interface{})
|
||||
Logger
|
||||
}
|
||||
|
||||
// Output defines the output data for a metric exporter like influx or prometheus.
|
||||
|
|
@ -49,6 +47,7 @@ func (u *UnifiPoller) InitializeOutputs() error {
|
|||
|
||||
for _, o := range outputs {
|
||||
count++
|
||||
|
||||
go func(o *Output) {
|
||||
v <- o.Method(u)
|
||||
}(o)
|
||||
|
|
|
|||
|
|
@ -37,25 +37,6 @@ func (u *UnifiPoller) Start() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if len(u.Config.Controllers) < 1 {
|
||||
u.Config.Controllers = []Controller{{
|
||||
Sites: []string{"all"},
|
||||
User: defaultUnifiUser,
|
||||
Pass: "",
|
||||
URL: defaultUnifiURL,
|
||||
SaveSites: true,
|
||||
}}
|
||||
}
|
||||
|
||||
if u.Flags.DumpJSON != "" {
|
||||
return u.DumpJSONPayload()
|
||||
}
|
||||
|
||||
if u.Config.Debug {
|
||||
log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate)
|
||||
u.LogDebugf("Debug Logging Enabled")
|
||||
}
|
||||
|
||||
return u.Run()
|
||||
}
|
||||
|
||||
|
|
@ -79,20 +60,19 @@ func (f *Flags) Parse(args []string) {
|
|||
// 2. Run the collector one time and report the metrics to influxdb. (lambda)
|
||||
// 3. Start a web server and wait for Prometheus to poll the application for metrics.
|
||||
func (u *UnifiPoller) Run() error {
|
||||
if u.Flags.DumpJSON != "" {
|
||||
return u.DumpJSONPayload()
|
||||
}
|
||||
|
||||
if u.Config.Debug {
|
||||
log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate)
|
||||
u.LogDebugf("Debug Logging Enabled")
|
||||
}
|
||||
|
||||
log.Printf("[INFO] UniFi Poller v%v Starting Up! PID: %d", version.Version, os.Getpid())
|
||||
|
||||
for i, c := range u.Config.Controllers {
|
||||
if c.Name == "" {
|
||||
u.Config.Controllers[i].Name = c.URL
|
||||
}
|
||||
|
||||
switch err := u.GetUnifi(c); err {
|
||||
case nil:
|
||||
u.Logf("Polling UniFi Controller at %s v%s as user %s. Sites: %v",
|
||||
c.URL, c.Unifi.ServerVersion, c.User, c.Sites)
|
||||
default:
|
||||
u.LogErrorf("Controller Auth or Connection failed, but continuing to retry! %s: %v", c.Name, err)
|
||||
}
|
||||
if err := u.InitializeInputs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return u.InitializeOutputs()
|
||||
|
|
|
|||
|
|
@ -1,241 +0,0 @@
|
|||
package poller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// GetUnifi returns a UniFi controller interface.
|
||||
func (u *UnifiPoller) GetUnifi(c Controller) error {
|
||||
var err error
|
||||
|
||||
u.Lock()
|
||||
defer u.Unlock()
|
||||
|
||||
if c.Unifi != nil {
|
||||
c.Unifi.CloseIdleConnections()
|
||||
}
|
||||
// Create an authenticated session to the Unifi Controller.
|
||||
c.Unifi, err = unifi.NewUnifi(&unifi.Config{
|
||||
User: c.User,
|
||||
Pass: c.Pass,
|
||||
URL: c.URL,
|
||||
VerifySSL: c.VerifySSL,
|
||||
ErrorLog: u.LogErrorf, // Log all errors.
|
||||
DebugLog: u.LogDebugf, // Log debug messages.
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.Unifi = nil
|
||||
return fmt.Errorf("unifi controller: %v", err)
|
||||
}
|
||||
|
||||
u.LogDebugf("Authenticated with controller successfully, %s", c.URL)
|
||||
|
||||
return u.CheckSites(c)
|
||||
}
|
||||
|
||||
// CheckSites makes sure the list of provided sites exists on the controller.
|
||||
// This does not run in Lambda (run-once) mode.
|
||||
func (u *UnifiPoller) CheckSites(c Controller) error {
|
||||
u.LogDebugf("Checking Controller Sites List")
|
||||
|
||||
sites, err := c.Unifi.GetSites()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := []string{}
|
||||
|
||||
for _, site := range sites {
|
||||
msg = append(msg, site.Name+" ("+site.Desc+")")
|
||||
}
|
||||
|
||||
u.Logf("Found %d site(s) on controller: %v", len(msg), strings.Join(msg, ", "))
|
||||
|
||||
if StringInSlice("all", c.Sites) {
|
||||
c.Sites = []string{"all"}
|
||||
return nil
|
||||
}
|
||||
|
||||
FIRST:
|
||||
for _, s := range c.Sites {
|
||||
for _, site := range sites {
|
||||
if s == site.Name {
|
||||
continue FIRST
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("configured site not found on controller: %v", s)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Metrics grabs all the measurements from a UniFi controller and returns them.
|
||||
func (u *UnifiPoller) Metrics() (*Metrics, error) {
|
||||
errs := []string{}
|
||||
metrics := &Metrics{}
|
||||
|
||||
for _, c := range u.Config.Controllers {
|
||||
m, err := u.checkAndPollController(c)
|
||||
if err != nil {
|
||||
errs = append(errs, err.Error())
|
||||
}
|
||||
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
metrics.Sites = append(metrics.Sites, m.Sites...)
|
||||
metrics.Clients = append(metrics.Clients, m.Clients...)
|
||||
metrics.IDSList = append(metrics.IDSList, m.IDSList...)
|
||||
|
||||
if m.Devices == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if metrics.Devices == nil {
|
||||
metrics.Devices = &unifi.Devices{}
|
||||
}
|
||||
|
||||
metrics.UAPs = append(metrics.UAPs, m.UAPs...)
|
||||
metrics.USGs = append(metrics.USGs, m.USGs...)
|
||||
metrics.USWs = append(metrics.USWs, m.USWs...)
|
||||
metrics.UDMs = append(metrics.UDMs, m.UDMs...)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if len(errs) > 0 {
|
||||
err = fmt.Errorf(strings.Join(errs, ", "))
|
||||
}
|
||||
|
||||
return metrics, err
|
||||
}
|
||||
|
||||
func (u *UnifiPoller) checkAndPollController(c Controller) (*Metrics, error) {
|
||||
if c.Unifi == nil {
|
||||
u.Logf("Re-authenticating to UniFi Controller: %s", c.URL)
|
||||
|
||||
if err := u.GetUnifi(c); err != nil {
|
||||
u.LogErrorf("re-authenticating to %s: %v", c.URL, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
m, err := u.collectController(c)
|
||||
if err == nil {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
u.LogErrorf("collecting metrics %v", err)
|
||||
u.Logf("Re-authenticating to UniFi Controller: %s", c.URL)
|
||||
|
||||
if err := u.GetUnifi(c); err != nil {
|
||||
u.LogErrorf("re-authenticating to %s: %v", c.URL, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u.collectController(c)
|
||||
}
|
||||
|
||||
func (u *UnifiPoller) collectController(c Controller) (*Metrics, error) {
|
||||
var err error
|
||||
|
||||
m := &Metrics{TS: time.Now()} // At this point, it's the Current Check.
|
||||
|
||||
// Get the sites we care about.
|
||||
if m.Sites, err = u.GetFilteredSites(c); err != nil {
|
||||
return m, fmt.Errorf("unifi.GetSites(%v): %v", c.URL, err)
|
||||
}
|
||||
|
||||
if c.SaveIDS {
|
||||
m.IDSList, err = c.Unifi.GetIDS(m.Sites, time.Now().Add(2*time.Minute), time.Now())
|
||||
if err != nil {
|
||||
return m, fmt.Errorf("unifi.GetIDS(%v): %v", c.URL, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all the points.
|
||||
if m.Clients, err = c.Unifi.GetClients(m.Sites); err != nil {
|
||||
return m, fmt.Errorf("unifi.GetClients(%v): %v", c.URL, err)
|
||||
}
|
||||
|
||||
if m.Devices, err = c.Unifi.GetDevices(m.Sites); err != nil {
|
||||
return m, fmt.Errorf("unifi.GetDevices(%v): %v", c.URL, err)
|
||||
}
|
||||
|
||||
return u.augmentMetrics(c, m), nil
|
||||
}
|
||||
|
||||
// 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(c Controller, metrics *Metrics) *Metrics {
|
||||
if metrics == nil || metrics.Devices == nil || metrics.Clients == nil {
|
||||
return metrics
|
||||
}
|
||||
|
||||
devices := make(map[string]string)
|
||||
bssdIDs := make(map[string]string)
|
||||
|
||||
for _, r := range metrics.UAPs {
|
||||
devices[r.Mac] = r.Name
|
||||
for _, v := range r.VapTable {
|
||||
bssdIDs[v.Bssid] = fmt.Sprintf("%s %s %s:", r.Name, v.Radio, v.RadioName)
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range metrics.USGs {
|
||||
devices[r.Mac] = r.Name
|
||||
}
|
||||
|
||||
for _, r := range metrics.USWs {
|
||||
devices[r.Mac] = r.Name
|
||||
}
|
||||
|
||||
for _, r := range metrics.UDMs {
|
||||
devices[r.Mac] = r.Name
|
||||
}
|
||||
|
||||
// These come blank, so set them here.
|
||||
for i, c := range metrics.Clients {
|
||||
metrics.Clients[i].SwName = devices[c.SwMac]
|
||||
metrics.Clients[i].ApName = devices[c.ApMac]
|
||||
metrics.Clients[i].GwName = devices[c.GwMac]
|
||||
metrics.Clients[i].RadioDescription = bssdIDs[metrics.Clients[i].Bssid] + metrics.Clients[i].RadioProto
|
||||
}
|
||||
|
||||
if !c.SaveSites {
|
||||
metrics.Sites = nil
|
||||
}
|
||||
|
||||
return metrics
|
||||
}
|
||||
|
||||
// GetFilteredSites returns a list of sites to fetch data for.
|
||||
// Omits requested but unconfigured sites. Grabs the full list from the
|
||||
// controller and returns the sites provided in the config file.
|
||||
func (u *UnifiPoller) GetFilteredSites(c Controller) (unifi.Sites, error) {
|
||||
var i int
|
||||
|
||||
sites, err := c.Unifi.GetSites()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(c.Sites) < 1 || StringInSlice("all", c.Sites) {
|
||||
return sites, nil
|
||||
}
|
||||
|
||||
for _, s := range sites {
|
||||
// Only include valid sites in the request filter.
|
||||
if StringInSlice(s.Name, c.Sites) {
|
||||
sites[i] = s
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
return sites[:i], nil
|
||||
}
|
||||
|
|
@ -41,7 +41,8 @@ type uclient struct {
|
|||
}
|
||||
|
||||
func descClient(ns string) *uclient {
|
||||
labels := []string{"name", "mac", "site_name", "gw_name", "sw_name", "vlan", "ip", "oui", "network", "sw_port", "ap_name", "wired"}
|
||||
labels := []string{"name", "mac", "site_name", "gw_name", "sw_name", "vlan",
|
||||
"ip", "oui", "network", "sw_port", "ap_name", "wired"}
|
||||
labelW := append([]string{"radio_name", "radio", "radio_proto", "channel", "essid", "bssid", "radio_desc"}, labels...)
|
||||
|
||||
return &uclient{
|
||||
|
|
@ -64,25 +65,34 @@ func descClient(ns string) *uclient {
|
|||
TxPower: prometheus.NewDesc(ns+"radio_transmit_power_dbm", "Client Transmit Power", labelW, nil),
|
||||
TxRate: prometheus.NewDesc(ns+"radio_transmit_rate_bps", "Client Transmit Rate", labelW, nil),
|
||||
WifiTxAttempts: prometheus.NewDesc(ns+"wifi_attempts_transmit_total", "Client Wifi Transmit Attempts", labelW, nil),
|
||||
Uptime: prometheus.NewDesc(ns+"uptime_seconds", "Client Uptime", labelW, nil), // XXX: re-purpose for info tags.
|
||||
Uptime: prometheus.NewDesc(ns+"uptime_seconds", "Client Uptime", labelW, nil),
|
||||
/* needs more "looking into"
|
||||
DpiStatsApp: prometheus.NewDesc(ns+"dpi_stats_app", "Client DPI Stats App", labels, nil),
|
||||
DpiStatsCat: prometheus.NewDesc(ns+"dpi_stats_cat", "Client DPI Stats Cat", labels, nil),
|
||||
DpiStatsRxBytes: prometheus.NewDesc(ns+"dpi_stats_receive_bytes_total", "Client DPI Stats Receive Bytes", labels, nil),
|
||||
DpiStatsRxPackets: prometheus.NewDesc(ns+"dpi_stats_receive_packets_total", "Client DPI Stats Receive Packets", labels, nil),
|
||||
DpiStatsTxBytes: prometheus.NewDesc(ns+"dpi_stats_transmit_bytes_total", "Client DPI Stats Transmit Bytes", labels, nil),
|
||||
DpiStatsTxPackets: prometheus.NewDesc(ns+"dpi_stats_transmit_packets_total", "Client DPI Stats Transmit Packets", labels, nil),
|
||||
DpiStatsApp: prometheus.NewDesc(ns+"dpi_stats_app",
|
||||
"Client DPI Stats App", labels, nil),
|
||||
DpiStatsCat: prometheus.NewDesc(ns+"dpi_stats_cat",
|
||||
"Client DPI Stats Cat", labels, nil),
|
||||
DpiStatsRxBytes: prometheus.NewDesc(ns+"dpi_stats_receive_bytes_total",
|
||||
"Client DPI Stats Receive Bytes", labels, nil),
|
||||
DpiStatsRxPackets: prometheus.NewDesc(ns+"dpi_stats_receive_packets_total",
|
||||
"Client DPI Stats Receive Packets", labels, nil),
|
||||
DpiStatsTxBytes: prometheus.NewDesc(ns+"dpi_stats_transmit_bytes_total",
|
||||
"Client DPI Stats Transmit Bytes", labels, nil),
|
||||
DpiStatsTxPackets: prometheus.NewDesc(ns+"dpi_stats_transmit_packets_total",
|
||||
"Client DPI Stats Transmit Packets", labels, nil),
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
func (u *promUnifi) 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, ""}
|
||||
labelW := append([]string{c.RadioName, c.Radio, c.RadioProto, c.Channel.Txt, c.Essid, c.Bssid, c.RadioDescription}, labels...)
|
||||
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([]*metric{
|
||||
{u.Client.RxBytes, counter, c.WiredRxBytes, labels},
|
||||
{u.Client.RxBytesR, gauge, c.WiredRxBytesR, labels},
|
||||
|
|
@ -94,6 +104,7 @@ func (u *promUnifi) exportClient(r report, c *unifi.Client) {
|
|||
} else {
|
||||
labels[len(labels)-1] = "false"
|
||||
labelW[len(labelW)-1] = "false"
|
||||
|
||||
r.send([]*metric{
|
||||
{u.Client.Anomalies, counter, c.Anomalies, labelW},
|
||||
{u.Client.CCQ, gauge, float64(c.Ccq) / 1000.0, labelW},
|
||||
|
|
@ -118,6 +129,8 @@ func (u *promUnifi) exportClient(r report, c *unifi.Client) {
|
|||
}
|
||||
|
||||
r.send([]*metric{{u.Client.Uptime, gauge, c.Uptime, labelW}})
|
||||
}
|
||||
|
||||
/* needs more "looking into"
|
||||
{u.Client.DpiStatsApp, gauge, c.DpiStats.App, labels},
|
||||
{u.Client.DpiStatsCat, gauge, c.DpiStats.Cat, labels},
|
||||
|
|
@ -126,4 +139,3 @@ func (u *promUnifi) exportClient(r report, c *unifi.Client) {
|
|||
{u.Client.DpiStatsTxBytes, counter, c.DpiStats.TxBytes, labels},
|
||||
{u.Client.DpiStatsTxPackets, counter, c.DpiStats.TxPackets, labels},
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ type Report struct {
|
|||
|
||||
func init() {
|
||||
u := &promUnifi{Prometheus: &Prometheus{}}
|
||||
|
||||
poller.NewOutput(&poller.Output{
|
||||
Name: "prometheus",
|
||||
Config: u.Prometheus,
|
||||
|
|
@ -93,33 +94,27 @@ func (u *promUnifi) Run(c poller.Collect) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
u.Config.Namespace = strings.Trim(strings.Replace(u.Config.Namespace, "-", "_", -1), "_")
|
||||
if u.Config.Namespace == "" {
|
||||
u.Config.Namespace = strings.Replace(poller.AppName, "-", "", -1)
|
||||
}
|
||||
|
||||
u.Config.Namespace = strings.Replace(u.Config.Namespace, "-", "_", -1)
|
||||
|
||||
if u.Config.HTTPListen == "" {
|
||||
u.Config.HTTPListen = defaultHTTPListen
|
||||
}
|
||||
|
||||
prometheus.MustRegister(version.NewCollector(u.Config.Namespace))
|
||||
|
||||
if u.Config.Namespace = strings.Trim(u.Config.Namespace, "_") + "_"; u.Config.Namespace == "_" {
|
||||
u.Config.Namespace = ""
|
||||
}
|
||||
|
||||
prometheus.MustRegister(&promUnifi{
|
||||
Collector: c,
|
||||
Client: descClient(u.Config.Namespace + "client_"),
|
||||
Device: descDevice(u.Config.Namespace + "device_"), // stats for all device types.
|
||||
UAP: descUAP(u.Config.Namespace + "device_"),
|
||||
USG: descUSG(u.Config.Namespace + "device_"),
|
||||
USW: descUSW(u.Config.Namespace + "device_"),
|
||||
Site: descSite(u.Config.Namespace + "site_"),
|
||||
Client: descClient(u.Config.Namespace + "_client_"),
|
||||
Device: descDevice(u.Config.Namespace + "_device_"), // stats for all device types.
|
||||
UAP: descUAP(u.Config.Namespace + "_device_"),
|
||||
USG: descUSG(u.Config.Namespace + "_device_"),
|
||||
USW: descUSW(u.Config.Namespace + "_device_"),
|
||||
Site: descSite(u.Config.Namespace + "_site_"),
|
||||
})
|
||||
|
||||
c.Logf("Exporting Measurements for Prometheus at https://%s/metrics, namespace: %s", u.Config.HTTPListen, u.Config.Namespace)
|
||||
c.Logf("Exporting Measurements for Prometheus at https://%s/metrics, namespace: %s",
|
||||
u.Config.HTTPListen, u.Config.Namespace)
|
||||
|
||||
return http.ListenAndServe(u.Config.HTTPListen, nil)
|
||||
}
|
||||
|
|
@ -152,6 +147,7 @@ func (u *promUnifi) Collect(ch chan<- prometheus.Metric) {
|
|||
r.error(ch, prometheus.NewInvalidDesc(fmt.Errorf("metric fetch failed")), err)
|
||||
return
|
||||
}
|
||||
|
||||
r.Fetch = time.Since(r.Start)
|
||||
|
||||
if r.Metrics.Devices == nil {
|
||||
|
|
@ -173,6 +169,7 @@ func (u *promUnifi) exportMetrics(r report, ch chan<- prometheus.Metric, ourChan
|
|||
for newMetrics := range ourChan {
|
||||
for _, m := range newMetrics {
|
||||
descs[m.Desc] = true
|
||||
|
||||
switch v := m.Value.(type) {
|
||||
case unifi.FlexInt:
|
||||
ch <- r.export(m, v.Val)
|
||||
|
|
@ -195,48 +192,55 @@ func (u *promUnifi) loopExports(r report) {
|
|||
m := r.metrics()
|
||||
|
||||
r.add()
|
||||
r.add()
|
||||
r.add()
|
||||
r.add()
|
||||
r.add()
|
||||
r.add()
|
||||
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, s := range m.Sites {
|
||||
u.exportSite(r, s)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, d := range m.UAPs {
|
||||
u.exportUAP(r, d)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, d := range m.UDMs {
|
||||
u.exportUDM(r, d)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, d := range m.USGs {
|
||||
u.exportUSG(r, d)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, d := range m.USWs {
|
||||
u.exportUSW(r, d)
|
||||
}
|
||||
}()
|
||||
|
||||
r.add()
|
||||
go func() {
|
||||
defer r.done()
|
||||
|
||||
for _, c := range m.Clients {
|
||||
u.exportClient(r, c)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,32 +35,34 @@ type site struct {
|
|||
|
||||
func descSite(ns string) *site {
|
||||
labels := []string{"subsystem", "status", "site_name"}
|
||||
nd := prometheus.NewDesc
|
||||
|
||||
return &site{
|
||||
NumUser: prometheus.NewDesc(ns+"users", "Number of Users", labels, nil),
|
||||
NumGuest: prometheus.NewDesc(ns+"guests", "Number of Guests", labels, nil),
|
||||
NumIot: prometheus.NewDesc(ns+"iots", "Number of IoT Devices", labels, nil),
|
||||
TxBytesR: prometheus.NewDesc(ns+"transmit_rate_bytes", "Bytes Transmit Rate", labels, nil),
|
||||
RxBytesR: prometheus.NewDesc(ns+"receive_rate_bytes", "Bytes Receive Rate", labels, nil),
|
||||
NumAp: prometheus.NewDesc(ns+"aps", "Access Point Count", labels, nil),
|
||||
NumAdopted: prometheus.NewDesc(ns+"adopted", "Adoption Count", labels, nil),
|
||||
NumDisabled: prometheus.NewDesc(ns+"disabled", "Disabled Count", labels, nil),
|
||||
NumDisconnected: prometheus.NewDesc(ns+"disconnected", "Disconnected Count", labels, nil),
|
||||
NumPending: prometheus.NewDesc(ns+"pending", "Pending Count", labels, nil),
|
||||
NumGw: prometheus.NewDesc(ns+"gateways", "Gateway Count", labels, nil),
|
||||
NumSw: prometheus.NewDesc(ns+"switches", "Switch Count", labels, nil),
|
||||
NumSta: prometheus.NewDesc(ns+"stations", "Station Count", labels, nil),
|
||||
Latency: prometheus.NewDesc(ns+"latency_seconds", "Latency", labels, nil),
|
||||
Uptime: prometheus.NewDesc(ns+"uptime_seconds", "Uptime", labels, nil),
|
||||
Drops: prometheus.NewDesc(ns+"intenet_drops_total", "Internet (WAN) Disconnections", labels, nil),
|
||||
XputUp: prometheus.NewDesc(ns+"xput_up_rate", "Speedtest Upload", labels, nil),
|
||||
XputDown: prometheus.NewDesc(ns+"xput_down_rate", "Speedtest Download", labels, nil),
|
||||
SpeedtestPing: prometheus.NewDesc(ns+"speedtest_ping", "Speedtest Ping", labels, nil),
|
||||
RemoteUserNumActive: prometheus.NewDesc(ns+"remote_user_active", "Remote Users Active", labels, nil),
|
||||
RemoteUserNumInactive: prometheus.NewDesc(ns+"remote_user_inactive", "Remote Users Inactive", labels, nil),
|
||||
RemoteUserRxBytes: prometheus.NewDesc(ns+"remote_user_receive_bytes_total", "Remote Users Receive Bytes", labels, nil),
|
||||
RemoteUserTxBytes: prometheus.NewDesc(ns+"remote_user_transmit_bytes_total", "Remote Users Transmit Bytes", labels, nil),
|
||||
RemoteUserRxPackets: prometheus.NewDesc(ns+"remote_user_receive_packets_total", "Remote Users Receive Packets", labels, nil),
|
||||
RemoteUserTxPackets: prometheus.NewDesc(ns+"remote_user_transmit_packets_total", "Remote Users Transmit Packets", labels, nil),
|
||||
NumUser: nd(ns+"users", "Number of Users", labels, nil),
|
||||
NumGuest: nd(ns+"guests", "Number of Guests", labels, nil),
|
||||
NumIot: nd(ns+"iots", "Number of IoT Devices", labels, nil),
|
||||
TxBytesR: nd(ns+"transmit_rate_bytes", "Bytes Transmit Rate", labels, nil),
|
||||
RxBytesR: nd(ns+"receive_rate_bytes", "Bytes Receive Rate", labels, nil),
|
||||
NumAp: nd(ns+"aps", "Access Point Count", labels, nil),
|
||||
NumAdopted: nd(ns+"adopted", "Adoption Count", labels, nil),
|
||||
NumDisabled: nd(ns+"disabled", "Disabled Count", labels, nil),
|
||||
NumDisconnected: nd(ns+"disconnected", "Disconnected Count", labels, nil),
|
||||
NumPending: nd(ns+"pending", "Pending Count", labels, nil),
|
||||
NumGw: nd(ns+"gateways", "Gateway Count", labels, nil),
|
||||
NumSw: nd(ns+"switches", "Switch Count", labels, nil),
|
||||
NumSta: nd(ns+"stations", "Station Count", labels, nil),
|
||||
Latency: nd(ns+"latency_seconds", "Latency", labels, nil),
|
||||
Uptime: nd(ns+"uptime_seconds", "Uptime", labels, nil),
|
||||
Drops: nd(ns+"intenet_drops_total", "Internet (WAN) Disconnections", labels, nil),
|
||||
XputUp: nd(ns+"xput_up_rate", "Speedtest Upload", labels, nil),
|
||||
XputDown: nd(ns+"xput_down_rate", "Speedtest Download", labels, nil),
|
||||
SpeedtestPing: nd(ns+"speedtest_ping", "Speedtest Ping", labels, nil),
|
||||
RemoteUserNumActive: nd(ns+"remote_user_active", "Remote Users Active", labels, nil),
|
||||
RemoteUserNumInactive: nd(ns+"remote_user_inactive", "Remote Users Inactive", labels, nil),
|
||||
RemoteUserRxBytes: nd(ns+"remote_user_receive_bytes_total", "Remote Users Receive Bytes", labels, nil),
|
||||
RemoteUserTxBytes: nd(ns+"remote_user_transmit_bytes_total", "Remote Users Transmit Bytes", labels, nil),
|
||||
RemoteUserRxPackets: nd(ns+"remote_user_receive_packets_total", "Remote Users Receive Packets", labels, nil),
|
||||
RemoteUserTxPackets: nd(ns+"remote_user_transmit_packets_total", "Remote Users Transmit Packets", labels, nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +80,6 @@ func (u *promUnifi) exportSite(r report, s *unifi.Site) {
|
|||
{u.Site.SpeedtestPing, gauge, h.SpeedtestPing, labels},
|
||||
{u.Site.Drops, counter, h.Drops, labels},
|
||||
})
|
||||
|
||||
case "wlan":
|
||||
r.send([]*metric{
|
||||
{u.Site.TxBytesR, gauge, h.TxBytesR, labels},
|
||||
|
|
@ -92,7 +93,6 @@ func (u *promUnifi) exportSite(r report, s *unifi.Site) {
|
|||
{u.Site.NumAp, gauge, h.NumAp, labels},
|
||||
{u.Site.NumDisabled, gauge, h.NumDisabled, labels},
|
||||
})
|
||||
|
||||
case "wan":
|
||||
r.send([]*metric{
|
||||
{u.Site.TxBytesR, gauge, h.TxBytesR, labels},
|
||||
|
|
@ -103,7 +103,6 @@ func (u *promUnifi) exportSite(r report, s *unifi.Site) {
|
|||
{u.Site.NumGw, gauge, h.NumGw, labels},
|
||||
{u.Site.NumSta, gauge, h.NumSta, labels},
|
||||
})
|
||||
|
||||
case "lan":
|
||||
r.send([]*metric{
|
||||
{u.Site.TxBytesR, gauge, h.TxBytesR, labels},
|
||||
|
|
@ -116,7 +115,6 @@ func (u *promUnifi) exportSite(r report, s *unifi.Site) {
|
|||
{u.Site.NumIot, gauge, h.NumIot, labels},
|
||||
{u.Site.NumSw, gauge, h.NumSw, labels},
|
||||
})
|
||||
|
||||
case "vpn":
|
||||
r.send([]*metric{
|
||||
{u.Site.RemoteUserNumActive, gauge, h.RemoteUserNumActive, labels},
|
||||
|
|
|
|||
|
|
@ -83,79 +83,80 @@ func descUAP(ns string) *uap {
|
|||
labelA := []string{"stat", "site_name", "name"} // stat + labels[1:]
|
||||
labelV := []string{"vap_name", "bssid", "radio", "radio_name", "essid", "usage", "site_name", "name"}
|
||||
labelR := []string{"radio_name", "radio", "site_name", "name"}
|
||||
nd := prometheus.NewDesc
|
||||
|
||||
return &uap{
|
||||
// 3x each - stat table: total, guest, user
|
||||
ApWifiTxDropped: prometheus.NewDesc(ns+"stat_wifi_transmt_dropped_total", "Wifi Transmissions Dropped", labelA, nil),
|
||||
ApRxErrors: prometheus.NewDesc(ns+"stat_receive_errors_total", "Receive Errors", labelA, nil),
|
||||
ApRxDropped: prometheus.NewDesc(ns+"stat_receive_dropped_total", "Receive Dropped", labelA, nil),
|
||||
ApRxFrags: prometheus.NewDesc(ns+"stat_receive_frags_total", "Received Frags", labelA, nil),
|
||||
ApRxCrypts: prometheus.NewDesc(ns+"stat_receive_crypts_total", "Receive Crypts", labelA, nil),
|
||||
ApTxPackets: prometheus.NewDesc(ns+"stat_transmit_packets_total", "Transmit Packets", labelA, nil),
|
||||
ApTxBytes: prometheus.NewDesc(ns+"stat_transmit_bytes_total", "Transmit Bytes", labelA, nil),
|
||||
ApTxErrors: prometheus.NewDesc(ns+"stat_transmit_errors_total", "Transmit Errors", labelA, nil),
|
||||
ApTxDropped: prometheus.NewDesc(ns+"stat_transmit_dropped_total", "Transmit Dropped", labelA, nil),
|
||||
ApTxRetries: prometheus.NewDesc(ns+"stat_retries_tx_total", "Transmit Retries", labelA, nil),
|
||||
ApRxPackets: prometheus.NewDesc(ns+"stat_receive_packets_total", "Receive Packets", labelA, nil),
|
||||
ApRxBytes: prometheus.NewDesc(ns+"stat_receive_bytes_total", "Receive Bytes", labelA, nil),
|
||||
WifiTxAttempts: prometheus.NewDesc(ns+"stat_wifi_transmit_attempts_total", "Wifi Transmission Attempts", labelA, nil),
|
||||
MacFilterRejections: prometheus.NewDesc(ns+"stat_mac_filter_rejects_total", "MAC Filter Rejections", labelA, nil),
|
||||
ApWifiTxDropped: nd(ns+"stat_wifi_transmt_dropped_total", "Wifi Transmissions Dropped", labelA, nil),
|
||||
ApRxErrors: nd(ns+"stat_receive_errors_total", "Receive Errors", labelA, nil),
|
||||
ApRxDropped: nd(ns+"stat_receive_dropped_total", "Receive Dropped", labelA, nil),
|
||||
ApRxFrags: nd(ns+"stat_receive_frags_total", "Received Frags", labelA, nil),
|
||||
ApRxCrypts: nd(ns+"stat_receive_crypts_total", "Receive Crypts", labelA, nil),
|
||||
ApTxPackets: nd(ns+"stat_transmit_packets_total", "Transmit Packets", labelA, nil),
|
||||
ApTxBytes: nd(ns+"stat_transmit_bytes_total", "Transmit Bytes", labelA, nil),
|
||||
ApTxErrors: nd(ns+"stat_transmit_errors_total", "Transmit Errors", labelA, nil),
|
||||
ApTxDropped: nd(ns+"stat_transmit_dropped_total", "Transmit Dropped", labelA, nil),
|
||||
ApTxRetries: nd(ns+"stat_retries_tx_total", "Transmit Retries", labelA, nil),
|
||||
ApRxPackets: nd(ns+"stat_receive_packets_total", "Receive Packets", labelA, nil),
|
||||
ApRxBytes: nd(ns+"stat_receive_bytes_total", "Receive Bytes", labelA, nil),
|
||||
WifiTxAttempts: nd(ns+"stat_wifi_transmit_attempts_total", "Wifi Transmission Attempts", labelA, nil),
|
||||
MacFilterRejections: nd(ns+"stat_mac_filter_rejects_total", "MAC Filter Rejections", labelA, nil),
|
||||
// N each - 1 per Virtual AP (VAP)
|
||||
VAPCcq: prometheus.NewDesc(ns+"vap_ccq_ratio", "VAP Client Connection Quality", labelV, nil),
|
||||
VAPMacFilterRejections: prometheus.NewDesc(ns+"vap_mac_filter_rejects_total", "VAP MAC Filter Rejections", labelV, nil),
|
||||
VAPNumSatisfactionSta: prometheus.NewDesc(ns+"vap_satisfaction_stations", "VAP Number Satisifaction Stations", labelV, nil),
|
||||
VAPAvgClientSignal: prometheus.NewDesc(ns+"vap_average_client_signal", "VAP Average Client Signal", labelV, nil),
|
||||
VAPSatisfaction: prometheus.NewDesc(ns+"vap_satisfaction_ratio", "VAP Satisfaction", labelV, nil),
|
||||
VAPSatisfactionNow: prometheus.NewDesc(ns+"vap_satisfaction_now_ratio", "VAP Satisfaction Now", labelV, nil),
|
||||
VAPDNSAvgLatency: prometheus.NewDesc(ns+"vap_dns_latency_average_seconds", "VAP DNS Latency Average", labelV, nil),
|
||||
VAPRxBytes: prometheus.NewDesc(ns+"vap_receive_bytes_total", "VAP Bytes Received", labelV, nil),
|
||||
VAPRxCrypts: prometheus.NewDesc(ns+"vap_receive_crypts_total", "VAP Crypts Received", labelV, nil),
|
||||
VAPRxDropped: prometheus.NewDesc(ns+"vap_receive_dropped_total", "VAP Dropped Received", labelV, nil),
|
||||
VAPRxErrors: prometheus.NewDesc(ns+"vap_receive_errors_total", "VAP Errors Received", labelV, nil),
|
||||
VAPRxFrags: prometheus.NewDesc(ns+"vap_receive_frags_total", "VAP Frags Received", labelV, nil),
|
||||
VAPRxNwids: prometheus.NewDesc(ns+"vap_receive_nwids_total", "VAP Nwids Received", labelV, nil),
|
||||
VAPRxPackets: prometheus.NewDesc(ns+"vap_receive_packets_total", "VAP Packets Received", labelV, nil),
|
||||
VAPTxBytes: prometheus.NewDesc(ns+"vap_transmit_bytes_total", "VAP Bytes Transmitted", labelV, nil),
|
||||
VAPTxDropped: prometheus.NewDesc(ns+"vap_transmit_dropped_total", "VAP Dropped Transmitted", labelV, nil),
|
||||
VAPTxErrors: prometheus.NewDesc(ns+"vap_transmit_errors_total", "VAP Errors Transmitted", labelV, nil),
|
||||
VAPTxPackets: prometheus.NewDesc(ns+"vap_transmit_packets_total", "VAP Packets Transmitted", labelV, nil),
|
||||
VAPTxPower: prometheus.NewDesc(ns+"vap_transmit_power", "VAP Transmit Power", labelV, nil),
|
||||
VAPTxRetries: prometheus.NewDesc(ns+"vap_transmit_retries_total", "VAP Retries Transmitted", labelV, nil),
|
||||
VAPTxCombinedRetries: prometheus.NewDesc(ns+"vap_transmit_retries_combined_total", "VAP Retries Combined Transmitted", labelV, nil),
|
||||
VAPTxDataMpduBytes: prometheus.NewDesc(ns+"vap_data_mpdu_transmit_bytes_total", "VAP Data MPDU Bytes Transmitted", labelV, nil),
|
||||
VAPTxRtsRetries: prometheus.NewDesc(ns+"vap_transmit_rts_retries_total", "VAP RTS Retries Transmitted", labelV, nil),
|
||||
VAPTxSuccess: prometheus.NewDesc(ns+"vap_transmit_success_total", "VAP Success Transmits", labelV, nil),
|
||||
VAPTxTotal: prometheus.NewDesc(ns+"vap_transmit_total", "VAP Transmit Total", labelV, nil),
|
||||
VAPTxGoodbytes: prometheus.NewDesc(ns+"vap_transmit_goodbyes", "VAP Goodbyes Transmitted", labelV, nil),
|
||||
VAPTxLatAvg: prometheus.NewDesc(ns+"vap_transmit_latency_average_seconds", "VAP Latency Average Transmit", labelV, nil),
|
||||
VAPTxLatMax: prometheus.NewDesc(ns+"vap_transmit_latency_maximum_seconds", "VAP Latency Maximum Transmit", labelV, nil),
|
||||
VAPTxLatMin: prometheus.NewDesc(ns+"vap_transmit_latency_minimum_seconds", "VAP Latency Minimum Transmit", labelV, nil),
|
||||
VAPRxGoodbytes: prometheus.NewDesc(ns+"vap_receive_goodbyes", "VAP Goodbyes Received", labelV, nil),
|
||||
VAPRxLatAvg: prometheus.NewDesc(ns+"vap_receive_latency_average_seconds", "VAP Latency Average Receive", labelV, nil),
|
||||
VAPRxLatMax: prometheus.NewDesc(ns+"vap_receive_latency_maximum_seconds", "VAP Latency Maximum Receive", labelV, nil),
|
||||
VAPRxLatMin: prometheus.NewDesc(ns+"vap_receive_latency_minimum_seconds", "VAP Latency Minimum Receive", labelV, nil),
|
||||
VAPWifiTxLatencyMovAvg: prometheus.NewDesc(ns+"vap_transmit_latency_moving_avg_seconds", "VAP Latency Moving Average Tramsit", labelV, nil),
|
||||
VAPWifiTxLatencyMovMax: prometheus.NewDesc(ns+"vap_transmit_latency_moving_max_seconds", "VAP Latency Moving Maximum Tramsit", labelV, nil),
|
||||
VAPWifiTxLatencyMovMin: prometheus.NewDesc(ns+"vap_transmit_latency_moving_min_seconds", "VAP Latency Moving Minimum Tramsit", labelV, nil),
|
||||
VAPWifiTxLatencyMovTotal: prometheus.NewDesc(ns+"vap_transmit_latency_moving_total", "VAP Latency Moving Total Tramsit", labelV, nil),
|
||||
VAPWifiTxLatencyMovCount: prometheus.NewDesc(ns+"vap_transmit_latency_moving_count", "VAP Latency Moving Count Tramsit", labelV, nil),
|
||||
VAPCcq: nd(ns+"vap_ccq_ratio", "VAP Client Connection Quality", labelV, nil),
|
||||
VAPMacFilterRejections: nd(ns+"vap_mac_filter_rejects_total", "VAP MAC Filter Rejections", labelV, nil),
|
||||
VAPNumSatisfactionSta: nd(ns+"vap_satisfaction_stations", "VAP Number Satisifaction Stations", labelV, nil),
|
||||
VAPAvgClientSignal: nd(ns+"vap_average_client_signal", "VAP Average Client Signal", labelV, nil),
|
||||
VAPSatisfaction: nd(ns+"vap_satisfaction_ratio", "VAP Satisfaction", labelV, nil),
|
||||
VAPSatisfactionNow: nd(ns+"vap_satisfaction_now_ratio", "VAP Satisfaction Now", labelV, nil),
|
||||
VAPDNSAvgLatency: nd(ns+"vap_dns_latency_average_seconds", "VAP DNS Latency Average", labelV, nil),
|
||||
VAPRxBytes: nd(ns+"vap_receive_bytes_total", "VAP Bytes Received", labelV, nil),
|
||||
VAPRxCrypts: nd(ns+"vap_receive_crypts_total", "VAP Crypts Received", labelV, nil),
|
||||
VAPRxDropped: nd(ns+"vap_receive_dropped_total", "VAP Dropped Received", labelV, nil),
|
||||
VAPRxErrors: nd(ns+"vap_receive_errors_total", "VAP Errors Received", labelV, nil),
|
||||
VAPRxFrags: nd(ns+"vap_receive_frags_total", "VAP Frags Received", labelV, nil),
|
||||
VAPRxNwids: nd(ns+"vap_receive_nwids_total", "VAP Nwids Received", labelV, nil),
|
||||
VAPRxPackets: nd(ns+"vap_receive_packets_total", "VAP Packets Received", labelV, nil),
|
||||
VAPTxBytes: nd(ns+"vap_transmit_bytes_total", "VAP Bytes Transmitted", labelV, nil),
|
||||
VAPTxDropped: nd(ns+"vap_transmit_dropped_total", "VAP Dropped Transmitted", labelV, nil),
|
||||
VAPTxErrors: nd(ns+"vap_transmit_errors_total", "VAP Errors Transmitted", labelV, nil),
|
||||
VAPTxPackets: nd(ns+"vap_transmit_packets_total", "VAP Packets Transmitted", labelV, nil),
|
||||
VAPTxPower: nd(ns+"vap_transmit_power", "VAP Transmit Power", labelV, nil),
|
||||
VAPTxRetries: nd(ns+"vap_transmit_retries_total", "VAP Retries Transmitted", labelV, nil),
|
||||
VAPTxCombinedRetries: nd(ns+"vap_transmit_retries_combined_total", "VAP Retries Combined Tx", labelV, nil),
|
||||
VAPTxDataMpduBytes: nd(ns+"vap_data_mpdu_transmit_bytes_total", "VAP Data MPDU Bytes Tx", labelV, nil),
|
||||
VAPTxRtsRetries: nd(ns+"vap_transmit_rts_retries_total", "VAP RTS Retries Transmitted", labelV, nil),
|
||||
VAPTxSuccess: nd(ns+"vap_transmit_success_total", "VAP Success Transmits", labelV, nil),
|
||||
VAPTxTotal: nd(ns+"vap_transmit_total", "VAP Transmit Total", labelV, nil),
|
||||
VAPTxGoodbytes: nd(ns+"vap_transmit_goodbyes", "VAP Goodbyes Transmitted", labelV, nil),
|
||||
VAPTxLatAvg: nd(ns+"vap_transmit_latency_average_seconds", "VAP Latency Average Tx", labelV, nil),
|
||||
VAPTxLatMax: nd(ns+"vap_transmit_latency_maximum_seconds", "VAP Latency Maximum Tx", labelV, nil),
|
||||
VAPTxLatMin: nd(ns+"vap_transmit_latency_minimum_seconds", "VAP Latency Minimum Tx", labelV, nil),
|
||||
VAPRxGoodbytes: nd(ns+"vap_receive_goodbyes", "VAP Goodbyes Received", labelV, nil),
|
||||
VAPRxLatAvg: nd(ns+"vap_receive_latency_average_seconds", "VAP Latency Average Rx", labelV, nil),
|
||||
VAPRxLatMax: nd(ns+"vap_receive_latency_maximum_seconds", "VAP Latency Maximum Rx", labelV, nil),
|
||||
VAPRxLatMin: nd(ns+"vap_receive_latency_minimum_seconds", "VAP Latency Minimum Rx", labelV, nil),
|
||||
VAPWifiTxLatencyMovAvg: nd(ns+"vap_transmit_latency_moving_avg_seconds", "VAP Latency Moving Avg Tx", labelV, nil),
|
||||
VAPWifiTxLatencyMovMax: nd(ns+"vap_transmit_latency_moving_max_seconds", "VAP Latency Moving Min Tx", labelV, nil),
|
||||
VAPWifiTxLatencyMovMin: nd(ns+"vap_transmit_latency_moving_min_seconds", "VAP Latency Moving Max Tx", labelV, nil),
|
||||
VAPWifiTxLatencyMovTotal: nd(ns+"vap_transmit_latency_moving_total", "VAP Latency Moving Total Tramsit", labelV, nil),
|
||||
VAPWifiTxLatencyMovCount: nd(ns+"vap_transmit_latency_moving_count", "VAP Latency Moving Count Tramsit", labelV, nil),
|
||||
// N each - 1 per Radio. 1-4 radios per AP usually
|
||||
RadioCurrentAntennaGain: prometheus.NewDesc(ns+"radio_current_antenna_gain", "Radio Current Antenna Gain", labelR, nil),
|
||||
RadioHt: prometheus.NewDesc(ns+"radio_ht", "Radio HT", labelR, nil),
|
||||
RadioMaxTxpower: prometheus.NewDesc(ns+"radio_max_transmit_power", "Radio Maximum Transmit Power", labelR, nil),
|
||||
RadioMinTxpower: prometheus.NewDesc(ns+"radio_min_transmit_power", "Radio Minimum Transmit Power", labelR, nil),
|
||||
RadioNss: prometheus.NewDesc(ns+"radio_nss", "Radio Nss", labelR, nil),
|
||||
RadioRadioCaps: prometheus.NewDesc(ns+"radio_caps", "Radio Capabilities", labelR, nil),
|
||||
RadioTxPower: prometheus.NewDesc(ns+"radio_transmit_power", "Radio Transmit Power", labelR, nil),
|
||||
RadioAstBeXmit: prometheus.NewDesc(ns+"radio_ast_be_xmit", "Radio AstBe Transmit", labelR, nil),
|
||||
RadioChannel: prometheus.NewDesc(ns+"radio_channel", "Radio Channel", labelR, nil),
|
||||
RadioCuSelfRx: prometheus.NewDesc(ns+"radio_channel_utilization_receive_ratio", "Radio Channel Utilization Receive", labelR, nil),
|
||||
RadioCuSelfTx: prometheus.NewDesc(ns+"radio_channel_utilization_transmit_ratio", "Radio Channel Utilization Transmit", labelR, nil),
|
||||
RadioExtchannel: prometheus.NewDesc(ns+"radio_ext_channel", "Radio Ext Channel", labelR, nil),
|
||||
RadioGain: prometheus.NewDesc(ns+"radio_gain", "Radio Gain", labelR, nil),
|
||||
RadioNumSta: prometheus.NewDesc(ns+"radio_stations", "Radio Total Station Count", append(labelR, "station_type"), nil),
|
||||
RadioTxPackets: prometheus.NewDesc(ns+"radio_transmit_packets", "Radio Transmitted Packets", labelR, nil),
|
||||
RadioTxRetries: prometheus.NewDesc(ns+"radio_transmit_retries", "Radio Transmit Retries", labelR, nil),
|
||||
RadioCurrentAntennaGain: nd(ns+"radio_current_antenna_gain", "Radio Current Antenna Gain", labelR, nil),
|
||||
RadioHt: nd(ns+"radio_ht", "Radio HT", labelR, nil),
|
||||
RadioMaxTxpower: nd(ns+"radio_max_transmit_power", "Radio Maximum Transmit Power", labelR, nil),
|
||||
RadioMinTxpower: nd(ns+"radio_min_transmit_power", "Radio Minimum Transmit Power", labelR, nil),
|
||||
RadioNss: nd(ns+"radio_nss", "Radio Nss", labelR, nil),
|
||||
RadioRadioCaps: nd(ns+"radio_caps", "Radio Capabilities", labelR, nil),
|
||||
RadioTxPower: nd(ns+"radio_transmit_power", "Radio Transmit Power", labelR, nil),
|
||||
RadioAstBeXmit: nd(ns+"radio_ast_be_xmit", "Radio AstBe Transmit", labelR, nil),
|
||||
RadioChannel: nd(ns+"radio_channel", "Radio Channel", labelR, nil),
|
||||
RadioCuSelfRx: nd(ns+"radio_channel_utilization_receive_ratio", "Channel Utilization Rx", labelR, nil),
|
||||
RadioCuSelfTx: nd(ns+"radio_channel_utilization_transmit_ratio", "Channel Utilization Tx", labelR, nil),
|
||||
RadioExtchannel: nd(ns+"radio_ext_channel", "Radio Ext Channel", labelR, nil),
|
||||
RadioGain: nd(ns+"radio_gain", "Radio Gain", labelR, nil),
|
||||
RadioNumSta: nd(ns+"radio_stations", "Radio Total Station Count", append(labelR, "station_type"), nil),
|
||||
RadioTxPackets: nd(ns+"radio_transmit_packets", "Radio Transmitted Packets", labelR, nil),
|
||||
RadioTxRetries: nd(ns+"radio_transmit_retries", "Radio Transmit Retries", labelR, nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -283,6 +284,7 @@ func (u *promUnifi) exportRADtable(r report, labels []string, rt unifi.RadioTabl
|
|||
labelR := []string{p.Name, p.Radio, labels[1], labels[2]}
|
||||
labelRUser := append(labelR, "user")
|
||||
labelRGuest := append(labelR, "guest")
|
||||
|
||||
r.send([]*metric{
|
||||
{u.UAP.RadioCurrentAntennaGain, gauge, p.CurrentAntennaGain, labelR},
|
||||
{u.UAP.RadioHt, gauge, p.Ht, labelR},
|
||||
|
|
@ -311,6 +313,7 @@ func (u *promUnifi) exportRADtable(r report, labels []string, rt unifi.RadioTabl
|
|||
{u.UAP.RadioTxPackets, gauge, t.TxPackets, labelR},
|
||||
{u.UAP.RadioTxRetries, gauge, t.TxRetries, labelR},
|
||||
})
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ type usg struct {
|
|||
|
||||
func descUSG(ns string) *usg {
|
||||
labels := []string{"port", "site_name", "name"}
|
||||
|
||||
return &usg{
|
||||
WanRxPackets: prometheus.NewDesc(ns+"wan_receive_packets_total", "WAN Receive Packets Total", labels, nil),
|
||||
WanRxBytes: prometheus.NewDesc(ns+"wan_receive_bytes_total", "WAN Receive Bytes Total", labels, nil),
|
||||
|
|
@ -75,6 +76,7 @@ func (u *promUnifi) exportUSG(r report, d *unifi.USG) {
|
|||
|
||||
labels := []string{d.Type, d.SiteName, d.Name}
|
||||
infoLabels := []string{d.Version, d.Model, d.Serial, d.Mac, d.IP, d.ID, d.Bytes.Txt, d.Uptime.Txt}
|
||||
|
||||
// Gateway System Data.
|
||||
u.exportWANPorts(r, labels, d.Wan1, d.Wan2)
|
||||
u.exportBYTstats(r, labels, d.TxBytes, d.RxBytes)
|
||||
|
|
@ -95,6 +97,7 @@ func (u *promUnifi) exportUSGstats(r report, labels []string, gw *unifi.Gw, st u
|
|||
|
||||
labelLan := []string{"lan", labels[1], labels[2]}
|
||||
labelWan := []string{"all", labels[1], labels[2]}
|
||||
|
||||
r.send([]*metric{
|
||||
{u.USG.LanRxPackets, counter, gw.LanRxPackets, labelLan},
|
||||
{u.USG.LanRxBytes, counter, gw.LanRxBytes, labelLan},
|
||||
|
|
@ -119,6 +122,7 @@ func (u *promUnifi) exportWANPorts(r report, labels []string, wans ...unifi.Wan)
|
|||
}
|
||||
|
||||
labelWan := []string{wan.Name, labels[1], labels[2]}
|
||||
|
||||
r.send([]*metric{
|
||||
{u.USG.WanRxPackets, counter, wan.RxPackets, labelWan},
|
||||
{u.USG.WanRxBytes, counter, wan.RxBytes, labelWan},
|
||||
|
|
|
|||
|
|
@ -49,45 +49,46 @@ func descUSW(ns string) *usw {
|
|||
pns := ns + "port_"
|
||||
labelS := []string{"site_name", "name"}
|
||||
labelP := []string{"port_id", "port_num", "port_name", "port_mac", "port_ip", "site_name", "name"}
|
||||
nd := prometheus.NewDesc
|
||||
|
||||
return &usw{
|
||||
// This data may be derivable by sum()ing the port data.
|
||||
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),
|
||||
SwRxErrors: prometheus.NewDesc(ns+"switch_receive_errors_total", "Switch Errors Received Total", labelS, nil),
|
||||
SwRxDropped: prometheus.NewDesc(ns+"switch_receive_dropped_total", "Switch Dropped Received Total", labelS, nil),
|
||||
SwRxCrypts: prometheus.NewDesc(ns+"switch_receive_crypts_total", "Switch Crypts Received Total", labelS, nil),
|
||||
SwRxFrags: prometheus.NewDesc(ns+"switch_receive_frags_total", "Switch Frags Received Total", labelS, nil),
|
||||
SwTxPackets: prometheus.NewDesc(ns+"switch_transmit_packets_total", "Switch Packets Transmit Total", labelS, nil),
|
||||
SwTxBytes: prometheus.NewDesc(ns+"switch_transmit_bytes_total", "Switch Bytes Transmit Total", labelS, nil),
|
||||
SwTxErrors: prometheus.NewDesc(ns+"switch_transmit_errors_total", "Switch Errors Transmit Total", labelS, nil),
|
||||
SwTxDropped: prometheus.NewDesc(ns+"switch_transmit_dropped_total", "Switch Dropped Transmit Total", labelS, nil),
|
||||
SwTxRetries: prometheus.NewDesc(ns+"switch_transmit_retries_total", "Switch Retries Transmit Total", labelS, nil),
|
||||
SwRxMulticast: prometheus.NewDesc(ns+"switch_receive_multicast_total", "Switch Multicast Receive Total", labelS, nil),
|
||||
SwRxBroadcast: prometheus.NewDesc(ns+"switch_receive_broadcast_total", "Switch Broadcast Receive Total", labelS, nil),
|
||||
SwTxMulticast: prometheus.NewDesc(ns+"switch_transmit_multicast_total", "Switch Multicast Transmit Total", labelS, nil),
|
||||
SwTxBroadcast: prometheus.NewDesc(ns+"switch_transmit_broadcast_total", "Switch Broadcast Transmit Total", labelS, nil),
|
||||
SwBytes: prometheus.NewDesc(ns+"switch_bytes_total", "Switch Bytes Transferred Total", labelS, nil),
|
||||
SwRxPackets: nd(ns+"switch_receive_packets_total", "Switch Packets Received Total", labelS, nil),
|
||||
SwRxBytes: nd(ns+"switch_receive_bytes_total", "Switch Bytes Received Total", labelS, nil),
|
||||
SwRxErrors: nd(ns+"switch_receive_errors_total", "Switch Errors Received Total", labelS, nil),
|
||||
SwRxDropped: nd(ns+"switch_receive_dropped_total", "Switch Dropped Received Total", labelS, nil),
|
||||
SwRxCrypts: nd(ns+"switch_receive_crypts_total", "Switch Crypts Received Total", labelS, nil),
|
||||
SwRxFrags: nd(ns+"switch_receive_frags_total", "Switch Frags Received Total", labelS, nil),
|
||||
SwTxPackets: nd(ns+"switch_transmit_packets_total", "Switch Packets Transmit Total", labelS, nil),
|
||||
SwTxBytes: nd(ns+"switch_transmit_bytes_total", "Switch Bytes Transmit Total", labelS, nil),
|
||||
SwTxErrors: nd(ns+"switch_transmit_errors_total", "Switch Errors Transmit Total", labelS, nil),
|
||||
SwTxDropped: nd(ns+"switch_transmit_dropped_total", "Switch Dropped Transmit Total", labelS, nil),
|
||||
SwTxRetries: nd(ns+"switch_transmit_retries_total", "Switch Retries Transmit Total", labelS, nil),
|
||||
SwRxMulticast: nd(ns+"switch_receive_multicast_total", "Switch Multicast Receive Total", labelS, nil),
|
||||
SwRxBroadcast: nd(ns+"switch_receive_broadcast_total", "Switch Broadcast Receive Total", labelS, nil),
|
||||
SwTxMulticast: nd(ns+"switch_transmit_multicast_total", "Switch Multicast Transmit Total", labelS, nil),
|
||||
SwTxBroadcast: nd(ns+"switch_transmit_broadcast_total", "Switch Broadcast Transmit Total", labelS, nil),
|
||||
SwBytes: nd(ns+"switch_bytes_total", "Switch Bytes Transferred Total", labelS, nil),
|
||||
// per-port data
|
||||
PoeCurrent: prometheus.NewDesc(pns+"poe_amperes", "POE Current", labelP, nil),
|
||||
PoePower: prometheus.NewDesc(pns+"poe_watts", "POE Power", labelP, nil),
|
||||
PoeVoltage: prometheus.NewDesc(pns+"poe_volts", "POE Voltage", labelP, nil),
|
||||
RxBroadcast: prometheus.NewDesc(pns+"receive_broadcast_total", "Receive Broadcast", labelP, nil),
|
||||
RxBytes: prometheus.NewDesc(pns+"receive_bytes_total", "Total Receive Bytes", labelP, nil),
|
||||
RxBytesR: prometheus.NewDesc(pns+"receive_rate_bytes", "Receive Bytes Rate", labelP, nil),
|
||||
RxDropped: prometheus.NewDesc(pns+"receive_dropped_total", "Total Receive Dropped", labelP, nil),
|
||||
RxErrors: prometheus.NewDesc(pns+"receive_errors_total", "Total Receive Errors", labelP, nil),
|
||||
RxMulticast: prometheus.NewDesc(pns+"receive_multicast_total", "Total Receive Multicast", labelP, nil),
|
||||
RxPackets: prometheus.NewDesc(pns+"receive_packets_total", "Total Receive Packets", labelP, nil),
|
||||
Satisfaction: prometheus.NewDesc(pns+"satisfaction_ratio", "Satisfaction", labelP, nil),
|
||||
Speed: prometheus.NewDesc(pns+"port_speed_bps", "Speed", labelP, nil),
|
||||
TxBroadcast: prometheus.NewDesc(pns+"transmit_broadcast_total", "Total Transmit Broadcast", labelP, nil),
|
||||
TxBytes: prometheus.NewDesc(pns+"transmit_bytes_total", "Total Transmit Bytes", labelP, nil),
|
||||
TxBytesR: prometheus.NewDesc(pns+"transmit_rate_bytes", "Transmit Bytes Rate", labelP, nil),
|
||||
TxDropped: prometheus.NewDesc(pns+"transmit_dropped_total", "Total Transmit Dropped", labelP, nil),
|
||||
TxErrors: prometheus.NewDesc(pns+"transmit_errors_total", "Total Transmit Errors", labelP, nil),
|
||||
TxMulticast: prometheus.NewDesc(pns+"transmit_multicast_total", "Total Tranmist Multicast", labelP, nil),
|
||||
TxPackets: prometheus.NewDesc(pns+"transmit_packets_total", "Total Transmit Packets", labelP, nil),
|
||||
PoeCurrent: nd(pns+"poe_amperes", "POE Current", labelP, nil),
|
||||
PoePower: nd(pns+"poe_watts", "POE Power", labelP, nil),
|
||||
PoeVoltage: nd(pns+"poe_volts", "POE Voltage", labelP, nil),
|
||||
RxBroadcast: nd(pns+"receive_broadcast_total", "Receive Broadcast", labelP, nil),
|
||||
RxBytes: nd(pns+"receive_bytes_total", "Total Receive Bytes", labelP, nil),
|
||||
RxBytesR: nd(pns+"receive_rate_bytes", "Receive Bytes Rate", labelP, nil),
|
||||
RxDropped: nd(pns+"receive_dropped_total", "Total Receive Dropped", labelP, nil),
|
||||
RxErrors: nd(pns+"receive_errors_total", "Total Receive Errors", labelP, nil),
|
||||
RxMulticast: nd(pns+"receive_multicast_total", "Total Receive Multicast", labelP, nil),
|
||||
RxPackets: nd(pns+"receive_packets_total", "Total Receive Packets", labelP, nil),
|
||||
Satisfaction: nd(pns+"satisfaction_ratio", "Satisfaction", labelP, nil),
|
||||
Speed: nd(pns+"port_speed_bps", "Speed", labelP, nil),
|
||||
TxBroadcast: nd(pns+"transmit_broadcast_total", "Total Transmit Broadcast", labelP, nil),
|
||||
TxBytes: nd(pns+"transmit_bytes_total", "Total Transmit Bytes", labelP, nil),
|
||||
TxBytesR: nd(pns+"transmit_rate_bytes", "Transmit Bytes Rate", labelP, nil),
|
||||
TxDropped: nd(pns+"transmit_dropped_total", "Total Transmit Dropped", labelP, nil),
|
||||
TxErrors: nd(pns+"transmit_errors_total", "Total Transmit Errors", labelP, nil),
|
||||
TxMulticast: nd(pns+"transmit_multicast_total", "Total Tranmist Multicast", labelP, nil),
|
||||
TxPackets: nd(pns+"transmit_packets_total", "Total Transmit Packets", labelP, nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +99,7 @@ func (u *promUnifi) exportUSW(r report, d *unifi.USW) {
|
|||
|
||||
labels := []string{d.Type, d.SiteName, d.Name}
|
||||
infoLabels := []string{d.Version, d.Model, d.Serial, d.Mac, d.IP, d.ID, d.Bytes.Txt, d.Uptime.Txt}
|
||||
|
||||
u.exportUSWstats(r, labels, d.Stat.Sw)
|
||||
u.exportPRTtable(r, labels, d.PortTable)
|
||||
u.exportBYTstats(r, labels, d.TxBytes, d.RxBytes)
|
||||
|
|
@ -129,6 +131,7 @@ func (u *promUnifi) exportUSWstats(r report, labels []string, sw *unifi.Sw) {
|
|||
}
|
||||
|
||||
labelS := labels[1:]
|
||||
|
||||
r.send([]*metric{
|
||||
{u.USW.SwRxPackets, counter, sw.RxPackets, labelS},
|
||||
{u.USW.SwRxBytes, counter, sw.RxBytes, labelS},
|
||||
|
|
|
|||
Loading…
Reference in New Issue