diff --git a/integrations/inputunifi/.metadata.sh b/integrations/inputunifi/.metadata.sh index dd683d8c..d329ad7d 100755 --- a/integrations/inputunifi/.metadata.sh +++ b/integrations/inputunifi/.metadata.sh @@ -11,7 +11,7 @@ HBREPO="golift/homebrew-mugs" MAINT="David Newhall II " VENDOR="Go Lift " DESC="Polls a UniFi controller and exports metrics to InfluxDB" -GOLANGCI_LINT_ARGS="--enable-all -D gochecknoglobals -D dupl -D lll -e G101 " +GOLANGCI_LINT_ARGS="--enable-all -D gochecknoglobals -D dupl -D lll" # Example must exist at examples/$CONFIG_FILE.example CONFIG_FILE="up.conf" LICENSE="MIT" diff --git a/integrations/inputunifi/Gopkg.lock b/integrations/inputunifi/Gopkg.lock index 6d3ecf14..ffd65d42 100644 --- a/integrations/inputunifi/Gopkg.lock +++ b/integrations/inputunifi/Gopkg.lock @@ -30,12 +30,12 @@ version = "v1.0.3" [[projects]] - digest = "1:8a7dc583b5300f5d3f2602769b11127193330f74bb0a31e135d7354a1f96374a" + digest = "1:8b8439a870abfe8df15cd9963fe7702d20fc55cd0f2375304b4eecc955b45902" name = "golift.io/unifi" packages = ["."] pruneopts = "UT" - revision = "65d8c5a10faeb8180053a760d20800baf515f01a" - version = "v4.0.2" + revision = "a96d3c9d2e02e41013974e6595f7df581cf194dc" + version = "v4.1.2" [[projects]] digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96" diff --git a/integrations/inputunifi/README.md b/integrations/inputunifi/README.md index 50bbf6fc..c2ca2d6a 100644 --- a/integrations/inputunifi/README.md +++ b/integrations/inputunifi/README.md @@ -1,13 +1,13 @@ -[![discord](https://badgen.net/badge/icon/Discord?color=0011ff&label&icon=https://simpleicons.now.sh/discord/eee "Captain's Discord")](https://discord.gg/DyVsMyt) +[![discord](https://badgen.net/badge/icon/Discord?color=0011ff&label&icon=https://simpleicons.now.sh/discord/eee "Ubiquiti Discord")](https://discord.gg/KnyKYt2) [![twitter](https://badgen.net/twitter/follow/TwitchCaptain?icon=https://simpleicons.now.sh/twitter/0099ff&label=TwitchCaptain&color=0116ff "TwitchCaptain @ Twitter")](https://twitter.com/TwitchCaptain) [![grafana](https://badgen.net/https/golift.io/bd/grafana/dashboard-downloads/10414,10415,10416,10417,10418?icon=https://simpleicons.now.sh/grafana/ED7F38&color=0011ff "Grafana Dashboard Downloads")](http://grafana.com/dashboards?search=unifi-poller) [![pulls](https://badgen.net/docker/pulls/golift/unifi-poller?icon=https://simpleicons.now.sh/docker/38B1ED&label=pulls&color=0011ff "Docker Pulls")](https://hub.docker.com/r/golift/unifi-poller) [![DLs](https://img.shields.io/github/downloads/davidnewhall/unifi-poller/total.svg?logo=github&color=0116ff "GitHub Downloads")](https://www.somsubhra.com/github-release-stats/?username=davidnewhall&repository=unifi-poller) -[![unifi](https://badgen.net/badge/UniFi/5.10.x,5.11.x,UAP,USG,USW?list=|&icon=https://docs.golift.io/svg/ubiquiti_color.svg&color=0099ee "UniFi Products Supported")](https://github.com/golift/unifi) +[![unifi](https://badgen.net/badge/UniFi/5.11.x,5.12.x,UAP,USG,USW,UDM?list=|&icon=https://docs.golift.io/svg/ubiquiti_color.svg&color=0099ee "UniFi Products Supported")](https://github.com/golift/unifi) [![builer](https://badgen.net/badge/go/Application%20Builder?label=&icon=https://docs.golift.io/svg/go.svg&color=0099ee "Go Application Builder")](https://github.com/golift/application-builder) [![stars](https://badgen.net/github/stars/davidnewhall/unifi-poller?icon=https://simpleicons.now.sh/macys/fab&label=&color=0099ee "GitHub Stars")](https://github.com/davidnewhall/unifi-poller) [![travis](https://badgen.net/travis/davidnewhall/unifi-poller?icon=travis&label=build "Travis Build")](https://travis-ci.org/davidnewhall/unifi-poller) @@ -22,8 +22,8 @@ included; with screenshots. Updated 2019. We have a special place for [Docker Users](https://github.com/davidnewhall/unifi-poller/wiki/Docker). I'm willing to help if you have troubles. Open an [Issue](https://github.com/davidnewhall/unifi-poller/issues) and -we'll figure out how to get things working for you. You can also check out -my [Discord server](https://discord.gg/DyVsMyt); sometimes I look at it too! +we'll figure out how to get things working for you. You can also get help in +the #unifi-poller channel on the [Ubiquiti Discord server](https://discord.gg/KnyKYt2). ## Description diff --git a/integrations/inputunifi/init/docker/README.md b/integrations/inputunifi/init/docker/README.md new file mode 100644 index 00000000..67b37750 --- /dev/null +++ b/integrations/inputunifi/init/docker/README.md @@ -0,0 +1,17 @@ +## Docker Cloud Builds + +This folder contains the files that build our Docker image. The image +is built by Docker Hub "automatically" using the [Dockerfile](Dockerfile) +and [hooks/](hooks/) in this folder. + +## Docker Compose + +The other files in this folder can be used locally to spin up +a full set of applications (minus the UniFi controller) to get +UniFi Poller up and running. Including InfluxDB, Grafana, and +Chronograph. This last app is useful to inspect the data stored +in InfluxDB by UniFi Poller. + +##### HOWTO +**Learn more about how and when to use these *Docker Compose* files in the +[Docker Wiki](https://github.com/davidnewhall/unifi-poller/wiki/Docker).** diff --git a/integrations/inputunifi/init/systemd/template.unit.service b/integrations/inputunifi/init/systemd/template.unit.service index d09fd9a9..82673d82 100644 --- a/integrations/inputunifi/init/systemd/template.unit.service +++ b/integrations/inputunifi/init/systemd/template.unit.service @@ -12,6 +12,7 @@ ExecStart=/usr/bin/{{BINARY}} $DAEMON_OPTS EnvironmentFile=-/etc/default/{{BINARY}} EnvironmentFile=-/etc/sysconfig/{{BINARY}} Restart=always +RestartSec=10 StandardOutput=syslog StandardError=syslog SyslogIdentifier={{BINARY}} diff --git a/integrations/inputunifi/unifipoller/config.go b/integrations/inputunifi/unifipoller/config.go index 09d20b83..f75499b2 100644 --- a/integrations/inputunifi/unifipoller/config.go +++ b/integrations/inputunifi/unifipoller/config.go @@ -16,7 +16,7 @@ import ( influx "github.com/influxdata/influxdb1-client/v2" "github.com/spf13/pflag" "golift.io/unifi" - "gopkg.in/yaml.v2" + yaml "gopkg.in/yaml.v2" ) // Version is injected by the Makefile @@ -24,13 +24,13 @@ var Version = "development" const ( // App defaults in case they're missing from the config. - defaultInterval = 30 * time.Second - defaultInfxDb = "unifi" - defaultInfxUser = "unifi" - defaultInfxPass = "unifi" - defaultInfxURL = "http://127.0.0.1:8086" - defaultUnifUser = "influx" - defaultUnifURL = "https://127.0.0.1:8443" + defaultInterval = 30 * time.Second + defaultInfluxDB = "unifi" + defaultInfluxUser = "unifi" + defaultInfluxPass = "unifi" + defaultInfluxURL = "http://127.0.0.1:8086" + defaultUnifiUser = "influx" + defaultUnifiURL = "https://127.0.0.1:8443" ) // ENVConfigPrefix is the prefix appended to an env variable tag diff --git a/integrations/inputunifi/unifipoller/influx_clients.go b/integrations/inputunifi/unifipoller/influx_clients.go index ea9079ca..3ecb8ce0 100644 --- a/integrations/inputunifi/unifipoller/influx_clients.go +++ b/integrations/inputunifi/unifipoller/influx_clients.go @@ -55,6 +55,7 @@ func ClientPoints(c *unifi.Client, now time.Time) ([]*influx.Point, error) { "ip": c.IP, "essid": c.Essid, "bssid": c.Bssid, + "radio_desc": c.RadioDescription, "hostname": c.Hostname, "dpi_stats_last_updated": c.DpiStatsLastUpdated, "last_seen_by_uap": c.LastSeenByUAP, diff --git a/integrations/inputunifi/unifipoller/influx_uap.go b/integrations/inputunifi/unifipoller/influx_uap.go index ea9da689..c521a64a 100644 --- a/integrations/inputunifi/unifipoller/influx_uap.go +++ b/integrations/inputunifi/unifipoller/influx_uap.go @@ -14,172 +14,107 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) { u.Stat.Ap = &unifi.Ap{} } tags := map[string]string{ - "id": u.ID, - "mac": u.Mac, - "device_type": u.Stat.O, - "device_oid": u.Stat.Oid, - "device_ap": u.Stat.Ap.Ap, - "site_id": u.SiteID, - "site_name": u.SiteName, - "name": u.Name, - "adopted": u.Adopted.Txt, - "cfgversion": u.Cfgversion, - "config_network_ip": u.ConfigNetwork.IP, - "config_network_type": u.ConfigNetwork.Type, - "connect_request_ip": u.ConnectRequestIP, - "device_id": u.DeviceID, - "has_eth1": u.HasEth1.Txt, - "inform_ip": u.InformIP, - "isolated": u.Isolated.Txt, - "known_cfgversion": u.KnownCfgversion, - "model": u.Model, - "outdoor_mode_override": u.OutdoorModeOverride, - "serial": u.Serial, - "type": u.Type, - "vwireEnabled": u.VwireEnabled.Txt, + "id": u.ID, + "ip": u.IP, + "mac": u.Mac, + "device_type": u.Stat.Ap.O, + "device_oid": u.Stat.Ap.Oid, + "device_ap": u.Stat.Ap.Ap, + "site_id": u.SiteID, + "site_name": u.SiteName, + "name": u.Name, + "adopted": u.Adopted.Txt, + "cfgversion": u.Cfgversion, + "config_network_ip": u.ConfigNetwork.IP, + "config_network_type": u.ConfigNetwork.Type, + "connect_request_ip": u.ConnectRequestIP, + "device_id": u.DeviceID, + "has_eth1": u.HasEth1.Txt, + "inform_ip": u.InformIP, + "known_cfgversion": u.KnownCfgversion, + "model": u.Model, + "serial": u.Serial, + "type": u.Type, } fields := map[string]interface{}{ - "ip": u.IP, - "bytes": u.Bytes.Val, - "bytes_d": u.BytesD.Val, - "bytes_r": u.BytesR.Val, - "last_seen": u.LastSeen.Val, - "rx_bytes": u.RxBytes.Val, - "rx_bytes-d": u.RxBytesD.Val, - "tx_bytes": u.TxBytes.Val, - "tx_bytes-d": u.TxBytesD.Val, - "uptime": u.Uptime.Val, - "scanning": u.Scanning.Val, - "spectrum_scanning": u.SpectrumScanning.Val, - "roll_upgrade": u.Rollupgrade.Val, - "state": u.State, - "upgradable": u.Upgradable.Val, - "user-num_sta": u.UserNumSta, - "guest-num_sta": u.GuestNumSta, - "version": u.Version, - "loadavg_1": u.SysStats.Loadavg1.Val, - "loadavg_5": u.SysStats.Loadavg5.Val, - "loadavg_15": u.SysStats.Loadavg15.Val, - "mem_buffer": u.SysStats.MemBuffer.Val, - "mem_total": u.SysStats.MemTotal.Val, - "mem_used": u.SysStats.MemUsed.Val, - "cpu": u.SystemStats.CPU.Val, - "mem": u.SystemStats.Mem.Val, - "system_uptime": u.SystemStats.Uptime.Val, - "stat_guest-wifi0-rx_packets": u.Stat.GuestWifi0RxPackets.Val, - "stat_guest-wifi1-rx_packets": u.Stat.GuestWifi1RxPackets.Val, - "stat_user-wifi1-rx_packets": u.Stat.UserWifi1RxPackets.Val, - "stat_user-wifi0-rx_packets": u.Stat.UserWifi0RxPackets.Val, - "stat_user-rx_packets": u.Stat.UserRxPackets.Val, - "stat_guest-rx_packets": u.Stat.GuestRxPackets.Val, - "stat_wifi0-rx_packets": u.Stat.Wifi0RxPackets.Val, - "stat_wifi1-rx_packets": u.Stat.Wifi1RxPackets.Val, - "stat_rx_packets": u.Stat.RxPackets.Val, - "stat_guest-wifi0-rx_bytes": u.Stat.GuestWifi0RxBytes.Val, - "stat_guest-wifi1-rx_bytes": u.Stat.GuestWifi1RxBytes.Val, - "stat_user-wifi1-rx_bytes": u.Stat.UserWifi1RxBytes.Val, - "stat_user-wifi0-rx_bytes": u.Stat.UserWifi0RxBytes.Val, - "stat_user-rx_bytes": u.Stat.UserRxBytes.Val, - "stat_guest-rx_bytes": u.Stat.GuestRxBytes.Val, - "stat_wifi0-rx_bytes": u.Stat.Wifi0RxBytes.Val, - "stat_wifi1-rx_bytes": u.Stat.Wifi1RxBytes.Val, - "stat_rx_bytes": u.Stat.RxBytes.Val, - "stat_guest-wifi0-rx_errors": u.Stat.GuestWifi0RxErrors.Val, - "stat_guest-wifi1-rx_errors": u.Stat.GuestWifi1RxErrors.Val, - "stat_user-wifi1-rx_errors": u.Stat.UserWifi1RxErrors.Val, - "stat_user-wifi0-rx_errors": u.Stat.UserWifi0RxErrors.Val, - "stat_user-rx_errors": u.Stat.UserRxErrors.Val, - "stat_guest-rx_errors": u.Stat.GuestRxErrors.Val, - "stat_wifi0-rx_errors": u.Stat.Wifi0RxErrors.Val, - "stat_wifi1-rx_errors": u.Stat.Wifi1RxErrors.Val, - "stat_rx_errors": u.Stat.RxErrors.Val, - "stat_guest-wifi0-rx_dropped": u.Stat.GuestWifi0RxDropped.Val, - "stat_guest-wifi1-rx_dropped": u.Stat.GuestWifi1RxDropped.Val, - "stat_user-wifi1-rx_dropped": u.Stat.UserWifi1RxDropped.Val, - "stat_user-wifi0-rx_dropped": u.Stat.UserWifi0RxDropped.Val, - "stat_user-rx_dropped": u.Stat.UserRxDropped.Val, - "stat_guest-rx_dropped": u.Stat.GuestRxDropped.Val, - "stat_wifi0-rx_dropped": u.Stat.Wifi0RxDropped.Val, - "stat_wifi1-rx_dropped": u.Stat.Wifi1RxDropped.Val, - "stat_rx_dropped": u.Stat.RxDropped.Val, - "stat_guest-wifi0-rx_crypts": u.Stat.GuestWifi0RxCrypts.Val, - "stat_guest-wifi1-rx_crypts": u.Stat.GuestWifi1RxCrypts.Val, - "stat_user-wifi1-rx_crypts": u.Stat.UserWifi1RxCrypts.Val, - "stat_user-wifi0-rx_crypts": u.Stat.UserWifi0RxCrypts.Val, - "stat_user-rx_crypts": u.Stat.UserRxCrypts.Val, - "stat_guest-rx_crypts": u.Stat.GuestRxCrypts.Val, - "stat_wifi0-rx_crypts": u.Stat.Wifi0RxCrypts.Val, - "stat_wifi1-rx_crypts": u.Stat.Wifi1RxCrypts.Val, - "stat_rx_crypts": u.Stat.RxCrypts.Val, - "stat_guest-wifi0-rx_frags": u.Stat.GuestWifi0RxFrags.Val, - "stat_guest-wifi1-rx_frags": u.Stat.GuestWifi1RxFrags.Val, - "stat_user-wifi1-rx_frags": u.Stat.UserWifi1RxFrags.Val, - "stat_user-wifi0-rx_frags": u.Stat.UserWifi0RxFrags.Val, - "stat_user-rx_frags": u.Stat.UserRxFrags.Val, - "stat_guest-rx_frags": u.Stat.GuestRxFrags.Val, - "stat_wifi0-rx_frags": u.Stat.Wifi0RxFrags.Val, - "stat_wifi1-rx_frags": u.Stat.Wifi1RxFrags.Val, - "stat_rx_frags": u.Stat.RxFrags.Val, - "stat_guest-wifi0-tx_packets": u.Stat.GuestWifi0TxPackets.Val, - "stat_guest-wifi1-tx_packets": u.Stat.GuestWifi1TxPackets.Val, - "stat_user-wifi1-tx_packets": u.Stat.UserWifi1TxPackets.Val, - "stat_user-wifi0-tx_packets": u.Stat.UserWifi0TxPackets.Val, - "stat_user-tx_packets": u.Stat.UserTxPackets.Val, - "stat_guest-tx_packets": u.Stat.GuestTxPackets.Val, - "stat_wifi0-tx_packets": u.Stat.Wifi0TxPackets.Val, - "stat_wifi1-tx_packets": u.Stat.Wifi1TxPackets.Val, - "stat_tx_packets": u.Stat.TxPackets.Val, - "stat_guest-wifi0-tx_bytes": u.Stat.GuestWifi0TxBytes.Val, - "stat_guest-wifi1-tx_bytes": u.Stat.GuestWifi1TxBytes.Val, - "stat_user-wifi1-tx_bytes": u.Stat.UserWifi1TxBytes.Val, - "stat_user-wifi0-tx_bytes": u.Stat.UserWifi0TxBytes.Val, - "stat_user-tx_bytes": u.Stat.UserTxBytes.Val, - "stat_guest-tx_bytes": u.Stat.GuestTxBytes.Val, - "stat_wifi0-tx_bytes": u.Stat.Wifi0TxBytes.Val, - "stat_wifi1-tx_bytes": u.Stat.Wifi1TxBytes.Val, - "stat_tx_bytes": u.Stat.TxBytes.Val, - "stat_guest-wifi0-tx_errors": u.Stat.GuestWifi0TxErrors.Val, - "stat_guest-wifi1-tx_errors": u.Stat.GuestWifi1TxErrors.Val, - "stat_user-wifi1-tx_errors": u.Stat.UserWifi1TxErrors.Val, - "stat_user-wifi0-tx_errors": u.Stat.UserWifi0TxErrors.Val, - "stat_user-tx_errors": u.Stat.UserTxErrors.Val, - "stat_guest-tx_errors": u.Stat.GuestTxErrors.Val, - "stat_wifi0-tx_errors": u.Stat.Wifi0TxErrors.Val, - "stat_wifi1-tx_errors": u.Stat.Wifi1TxErrors.Val, - "stat_tx_errors": u.Stat.TxErrors.Val, - "stat_guest-wifi0-tx_dropped": u.Stat.GuestWifi0TxDropped.Val, - "stat_guest-wifi1-tx_dropped": u.Stat.GuestWifi1TxDropped.Val, - "stat_user-wifi1-tx_dropped": u.Stat.UserWifi1TxDropped.Val, - "stat_user-wifi0-tx_dropped": u.Stat.UserWifi0TxDropped.Val, - "stat_user-tx_dropped": u.Stat.UserTxDropped.Val, - "stat_guest-tx_dropped": u.Stat.GuestTxDropped.Val, - "stat_wifi0-tx_dropped": u.Stat.Wifi0TxDropped.Val, - "stat_wifi1-tx_dropped": u.Stat.Wifi1TxDropped.Val, - "stat_tx_dropped": u.Stat.TxDropped.Val, - "stat_guest-wifi0-tx_retries": u.Stat.GuestWifi0TxRetries.Val, - "stat_guest-wifi1-tx_retries": u.Stat.GuestWifi1TxRetries.Val, - "stat_user-wifi1-tx_retries": u.Stat.UserWifi1TxRetries.Val, - "stat_user-wifi0-tx_retries": u.Stat.UserWifi0TxRetries.Val, - "stat_user-tx_retries": u.Stat.UserTxRetries.Val, - "stat_guest-tx_retries": u.Stat.GuestTxRetries.Val, - "stat_wifi0-tx_retries": u.Stat.Wifi0TxRetries.Val, - "stat_wifi1-tx_retries": u.Stat.Wifi1TxRetries.Val, + "ip": u.IP, + "bytes": u.Bytes.Val, + "last_seen": u.LastSeen.Val, + "rx_bytes": u.RxBytes.Val, + "tx_bytes": u.TxBytes.Val, + "uptime": u.Uptime.Val, + "state": u.State, + "user-num_sta": int(u.UserNumSta.Val), + "guest-num_sta": int(u.GuestNumSta.Val), + "num_sta": u.NumSta.Val, + "version": u.Version, + "loadavg_1": u.SysStats.Loadavg1.Val, + "loadavg_5": u.SysStats.Loadavg5.Val, + "loadavg_15": u.SysStats.Loadavg15.Val, + "mem_buffer": u.SysStats.MemBuffer.Val, + "mem_total": u.SysStats.MemTotal.Val, + "mem_used": u.SysStats.MemUsed.Val, + "cpu": u.SystemStats.CPU.Val, + "mem": u.SystemStats.Mem.Val, + "system_uptime": u.SystemStats.Uptime.Val, + // Accumulative Statistics. + "stat_user-rx_packets": u.Stat.Ap.UserRxPackets.Val, + "stat_guest-rx_packets": u.Stat.Ap.GuestRxPackets.Val, + "stat_rx_packets": u.Stat.Ap.RxPackets.Val, + "stat_user-rx_bytes": u.Stat.Ap.UserRxBytes.Val, + "stat_guest-rx_bytes": u.Stat.Ap.GuestRxBytes.Val, + "stat_rx_bytes": u.Stat.Ap.RxBytes.Val, + "stat_user-rx_errors": u.Stat.Ap.UserRxErrors.Val, + "stat_guest-rx_errors": u.Stat.Ap.GuestRxErrors.Val, + "stat_rx_errors": u.Stat.Ap.RxErrors.Val, + "stat_user-rx_dropped": u.Stat.Ap.UserRxDropped.Val, + "stat_guest-rx_dropped": u.Stat.Ap.GuestRxDropped.Val, + "stat_rx_dropped": u.Stat.Ap.RxDropped.Val, + "stat_user-rx_crypts": u.Stat.Ap.UserRxCrypts.Val, + "stat_guest-rx_crypts": u.Stat.Ap.GuestRxCrypts.Val, + "stat_rx_crypts": u.Stat.Ap.RxCrypts.Val, + "stat_user-rx_frags": u.Stat.Ap.UserRxFrags.Val, + "stat_guest-rx_frags": u.Stat.Ap.GuestRxFrags.Val, + "stat_rx_frags": u.Stat.Ap.RxFrags.Val, + "stat_user-tx_packets": u.Stat.Ap.UserTxPackets.Val, + "stat_guest-tx_packets": u.Stat.Ap.GuestTxPackets.Val, + "stat_tx_packets": u.Stat.Ap.TxPackets.Val, + "stat_user-tx_bytes": u.Stat.Ap.UserTxBytes.Val, + "stat_guest-tx_bytes": u.Stat.Ap.GuestTxBytes.Val, + "stat_tx_bytes": u.Stat.Ap.TxBytes.Val, + "stat_user-tx_errors": u.Stat.Ap.UserTxErrors.Val, + "stat_guest-tx_errors": u.Stat.Ap.GuestTxErrors.Val, + "stat_tx_errors": u.Stat.Ap.TxErrors.Val, + "stat_user-tx_dropped": u.Stat.Ap.UserTxDropped.Val, + "stat_guest-tx_dropped": u.Stat.Ap.GuestTxDropped.Val, + "stat_tx_dropped": u.Stat.Ap.TxDropped.Val, + "stat_user-tx_retries": u.Stat.Ap.UserTxRetries.Val, + "stat_guest-tx_retries": u.Stat.Ap.GuestTxRetries.Val, } pt, err := influx.NewPoint("uap", tags, fields, now) if err != nil { return nil, err } - points := []*influx.Point{pt} + morePoints, err := processVAPs(u.VapTable, u.RadioTable, u.RadioTableStats, u.Name, u.ID, u.Mac, u.SiteName, now) + if err != nil { + return nil, err + } + return append(morePoints, pt), nil +} + +// processVAPs creates points for Wifi Radios. This works with several types of UAP-capable devices. +func processVAPs(vt unifi.VapTable, rt unifi.RadioTable, rts unifi.RadioTableStats, name, id, mac, sitename string, ts time.Time) ([]*influx.Point, error) { + tags := make(map[string]string) + fields := make(map[string]interface{}) + points := []*influx.Point{} - tags = make(map[string]string) - fields = make(map[string]interface{}) // Loop each virtual AP (ESSID) and extract data for it // from radio_tables and radio_table_stats. - for _, s := range u.VapTable { - tags["device_name"] = u.Name - tags["device_id"] = u.ID - tags["device_mac"] = u.Mac - tags["site_name"] = u.SiteName + for _, s := range vt { + tags["device_name"] = name + tags["device_id"] = id + tags["device_mac"] = mac + tags["site_name"] = sitename tags["ap_mac"] = s.ApMac tags["bssid"] = s.Bssid tags["id"] = s.ID @@ -232,7 +167,7 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) { fields["wifi_tx_latency_mov_total"] = s.WifiTxLatencyMov.Total.Val fields["wifi_tx_latency_mov_cuont"] = s.WifiTxLatencyMov.TotalCount.Val - for _, p := range u.RadioTable { + for _, p := range rt { if p.Name != s.RadioName { continue } @@ -249,7 +184,7 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) { fields["tx_power"] = p.TxPower.Val } - for _, p := range u.RadioTableStats { + for _, p := range rts { if p.Name != s.RadioName { continue } @@ -269,7 +204,7 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) { fields["user-num_sta"] = p.UserNumSta.Val } - pt, err := influx.NewPoint("uap_vaps", tags, fields, now) + pt, err := influx.NewPoint("uap_vaps", tags, fields, ts) if err != nil { return points, err } diff --git a/integrations/inputunifi/unifipoller/influx_udm.go b/integrations/inputunifi/unifipoller/influx_udm.go index 80492878..53ae9ea2 100644 --- a/integrations/inputunifi/unifipoller/influx_udm.go +++ b/integrations/inputunifi/unifipoller/influx_udm.go @@ -53,6 +53,7 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) { "uptime": u.Uptime.Val, "state": u.State.Val, "user-num_sta": u.UserNumSta.Val, + "num_sta": u.NumSta.Val, "version": u.Version, "num_desktop": u.NumDesktop.Val, "num_handheld": u.NumHandheld.Val, @@ -173,7 +174,7 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) { } fields = map[string]interface{}{ "fw_caps": u.FwCaps.Val, - "guest-num_sta": u.GuestNumSta.Val, + "guest-num_sta": u.GuestLanNumSta.Val, "ip": u.IP, "bytes": u.Bytes.Val, "fan_level": float64(0), @@ -185,7 +186,8 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) { "tx_bytes": u.TxBytes.Val, "uptime": u.Uptime.Val, "state": u.State.Val, - "user-num_sta": u.UserNumSta.Val, + "user-num_sta": u.UserLanNumSta.Val, + "num_sta": u.LanNumSta.Val, "version": u.Version, "loadavg_1": u.SysStats.Loadavg1.Val, "loadavg_5": u.SysStats.Loadavg5.Val, @@ -196,19 +198,18 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) { "cpu": u.SystemStats.CPU.Val, "mem": u.SystemStats.Mem.Val, "system_uptime": u.SystemStats.Uptime.Val, - "stat_bytes": u.Stat.Bytes.Val, - "stat_rx_bytes": u.Stat.RxBytes.Val, - "stat_rx_crypts": u.Stat.RxCrypts.Val, - "stat_rx_dropped": u.Stat.RxDropped.Val, - "stat_rx_errors": u.Stat.RxErrors.Val, - "stat_rx_frags": u.Stat.RxFrags.Val, - "stat_rx_packets": u.Stat.TxPackets.Val, - "stat_tx_bytes": u.Stat.TxBytes.Val, - "stat_tx_dropped": u.Stat.TxDropped.Val, - "stat_tx_errors": u.Stat.TxErrors.Val, - "stat_tx_packets": u.Stat.TxPackets.Val, - "stat_tx_retries": u.Stat.TxRetries.Val, - "uplink_depth": "0", + "stat_bytes": u.Stat.Sw.Bytes.Val, + "stat_rx_bytes": u.Stat.Sw.RxBytes.Val, + "stat_rx_crypts": u.Stat.Sw.RxCrypts.Val, + "stat_rx_dropped": u.Stat.Sw.RxDropped.Val, + "stat_rx_errors": u.Stat.Sw.RxErrors.Val, + "stat_rx_frags": u.Stat.Sw.RxFrags.Val, + "stat_rx_packets": u.Stat.Sw.TxPackets.Val, + "stat_tx_bytes": u.Stat.Sw.TxBytes.Val, + "stat_tx_dropped": u.Stat.Sw.TxDropped.Val, + "stat_tx_errors": u.Stat.Sw.TxErrors.Val, + "stat_tx_packets": u.Stat.Sw.TxPackets.Val, + "stat_tx_retries": u.Stat.Sw.TxRetries.Val, } pt, err = influx.NewPoint("usw", tags, fields, now) if err != nil { @@ -321,5 +322,95 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) { } points = append(points, pt) } - return points, nil + if u.Stat.Ap == nil { + return points, nil + // we're done now. the following code process UDM (non-pro) UAP data. + } + tags = map[string]string{ + "id": u.ID, + "ip": u.IP, + "mac": u.Mac, + "device_type": u.Stat.Ap.O, + "device_oid": u.Stat.Ap.Oid, + "device_ap": u.Stat.Ap.Ap, + "site_id": u.SiteID, + "site_name": u.SiteName, + "name": u.Name, + "adopted": u.Adopted.Txt, + "cfgversion": u.Cfgversion, + "config_network_ip": u.ConfigNetwork.IP, + "config_network_type": u.ConfigNetwork.Type, + "connect_request_ip": u.ConnectRequestIP, + "device_id": u.DeviceID, + "has_eth1": u.HasEth1.Txt, + "inform_ip": u.InformIP, + "known_cfgversion": u.KnownCfgversion, + "model": u.Model, + "serial": u.Serial, + "type": u.Type, + } + fields = map[string]interface{}{ + "ip": u.IP, + "bytes": u.Bytes.Val, + "last_seen": u.LastSeen.Val, + "rx_bytes": u.RxBytes.Val, + "tx_bytes": u.TxBytes.Val, + "uptime": u.Uptime.Val, + "state": int(u.State.Val), + "user-num_sta": int(u.UserWlanNumSta.Val), + "guest-num_sta": int(u.GuestWlanNumSta.Val), + "num_sta": u.WlanNumSta.Val, + "version": u.Version, + "loadavg_1": u.SysStats.Loadavg1.Val, + "loadavg_5": u.SysStats.Loadavg5.Val, + "loadavg_15": u.SysStats.Loadavg15.Val, + "mem_buffer": u.SysStats.MemBuffer.Val, + "mem_total": u.SysStats.MemTotal.Val, + "mem_used": u.SysStats.MemUsed.Val, + "cpu": u.SystemStats.CPU.Val, + "mem": u.SystemStats.Mem.Val, + "system_uptime": u.SystemStats.Uptime.Val, + // Accumulative Statistics. + "stat_user-rx_packets": u.Stat.Ap.UserRxPackets.Val, + "stat_guest-rx_packets": u.Stat.Ap.GuestRxPackets.Val, + "stat_rx_packets": u.Stat.Ap.RxPackets.Val, + "stat_user-rx_bytes": u.Stat.Ap.UserRxBytes.Val, + "stat_guest-rx_bytes": u.Stat.Ap.GuestRxBytes.Val, + "stat_rx_bytes": u.Stat.Ap.RxBytes.Val, + "stat_user-rx_errors": u.Stat.Ap.UserRxErrors.Val, + "stat_guest-rx_errors": u.Stat.Ap.GuestRxErrors.Val, + "stat_rx_errors": u.Stat.Ap.RxErrors.Val, + "stat_user-rx_dropped": u.Stat.Ap.UserRxDropped.Val, + "stat_guest-rx_dropped": u.Stat.Ap.GuestRxDropped.Val, + "stat_rx_dropped": u.Stat.Ap.RxDropped.Val, + "stat_user-rx_crypts": u.Stat.Ap.UserRxCrypts.Val, + "stat_guest-rx_crypts": u.Stat.Ap.GuestRxCrypts.Val, + "stat_rx_crypts": u.Stat.Ap.RxCrypts.Val, + "stat_user-rx_frags": u.Stat.Ap.UserRxFrags.Val, + "stat_guest-rx_frags": u.Stat.Ap.GuestRxFrags.Val, + "stat_rx_frags": u.Stat.Ap.RxFrags.Val, + "stat_user-tx_packets": u.Stat.Ap.UserTxPackets.Val, + "stat_guest-tx_packets": u.Stat.Ap.GuestTxPackets.Val, + "stat_tx_packets": u.Stat.Ap.TxPackets.Val, + "stat_user-tx_bytes": u.Stat.Ap.UserTxBytes.Val, + "stat_guest-tx_bytes": u.Stat.Ap.GuestTxBytes.Val, + "stat_tx_bytes": u.Stat.Ap.TxBytes.Val, + "stat_user-tx_errors": u.Stat.Ap.UserTxErrors.Val, + "stat_guest-tx_errors": u.Stat.Ap.GuestTxErrors.Val, + "stat_tx_errors": u.Stat.Ap.TxErrors.Val, + "stat_user-tx_dropped": u.Stat.Ap.UserTxDropped.Val, + "stat_guest-tx_dropped": u.Stat.Ap.GuestTxDropped.Val, + "stat_tx_dropped": u.Stat.Ap.TxDropped.Val, + "stat_user-tx_retries": u.Stat.Ap.UserTxRetries.Val, + "stat_guest-tx_retries": u.Stat.Ap.GuestTxRetries.Val, + } + pt, err = influx.NewPoint("uap", tags, fields, now) + if err != nil { + return nil, err + } + uapPoints, err := processVAPs(*u.VapTable, *u.RadioTable, *u.RadioTableStats, u.Name, u.ID, u.Mac, u.SiteName, now) + if err != nil { + return nil, err + } + return append(append(points, pt), uapPoints...), nil } diff --git a/integrations/inputunifi/unifipoller/start.go b/integrations/inputunifi/unifipoller/start.go index dbd2b44e..df26aaa2 100644 --- a/integrations/inputunifi/unifipoller/start.go +++ b/integrations/inputunifi/unifipoller/start.go @@ -16,16 +16,17 @@ import ( // Parses flags, parses config and executes Run(). func Start() error { log.SetFlags(log.LstdFlags) - up := &UnifiPoller{Flag: &Flag{}, + up := &UnifiPoller{ + Flag: &Flag{}, Config: &Config{ // Preload our defaults. - InfluxURL: defaultInfxURL, - InfluxUser: defaultInfxUser, - InfluxPass: defaultInfxPass, - InfluxDB: defaultInfxDb, - UnifiUser: defaultUnifUser, + InfluxURL: defaultInfluxURL, + InfluxUser: defaultInfluxUser, + InfluxPass: defaultInfluxPass, + InfluxDB: defaultInfluxDB, + UnifiUser: defaultUnifiUser, UnifiPass: os.Getenv("UNIFI_PASSWORD"), // deprecated name. - UnifiBase: defaultUnifURL, + UnifiBase: defaultUnifiURL, Interval: Duration{defaultInterval}, Sites: []string{"all"}, }} @@ -53,14 +54,14 @@ func Start() error { func (f *Flag) Parse(args []string) { f.FlagSet = pflag.NewFlagSet("unifi-poller", pflag.ExitOnError) f.Usage = func() { - fmt.Println("Usage: unifi-poller [--config=filepath] [--version]") + fmt.Println("Usage: unifi-poller [--config=/path/to/up.conf] [--version]") f.PrintDefaults() } f.StringVarP(&f.DumpJSON, "dumpjson", "j", "", "This debug option prints a json payload and exits. See man page for more info.") f.StringVarP(&f.ConfigFile, "config", "c", DefaultConfFile, "Poller config file path.") f.BoolVarP(&f.ShowVer, "version", "v", false, "Print the version and exit.") - _ = f.FlagSet.Parse(args) + _ = f.FlagSet.Parse(args) // pflag.ExitOnError means this will never return error. } // Run invokes all the application logic and routines. @@ -119,5 +120,6 @@ func (u *UnifiPoller) GetUnifi() (err error) { if err != nil { return fmt.Errorf("unifi controller: %v", err) } + u.LogDebugf("Authenticated with controller successfully") return u.CheckSites() } diff --git a/integrations/inputunifi/unifipoller/unifi.go b/integrations/inputunifi/unifipoller/unifi.go index 6e2da433..85bb19c6 100644 --- a/integrations/inputunifi/unifipoller/unifi.go +++ b/integrations/inputunifi/unifipoller/unifi.go @@ -16,6 +16,7 @@ func (u *UnifiPoller) CheckSites() error { if strings.Contains(strings.ToLower(u.Config.Mode), "lambda") { return nil // Skip this in lambda mode. } + u.LogDebugf("Checking Controller Sites List") sites, err := u.Unifi.GetSites() if err != nil { return err @@ -116,8 +117,12 @@ func (u *UnifiPoller) CollectMetrics() (*Metrics, error) { // This function currently adds parent device names to client metrics. func (u *UnifiPoller) AugmentMetrics(metrics *Metrics) error { 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 @@ -133,6 +138,7 @@ func (u *UnifiPoller) AugmentMetrics(metrics *Metrics) error { 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 } return nil } @@ -175,25 +181,27 @@ func (u *UnifiPoller) ReportMetrics(metrics *Metrics) error { // still check&log it in case the data going is skewed up and causes errors! func (m *Metrics) ProcessPoints() []error { errs := []error{} - processPoints := func(m *Metrics, p []*influx.Point, err error) error { - if err != nil || p == nil { - return err + processPoints := func(m *Metrics, p []*influx.Point, err error) { + switch { + case err != nil: + errs = append(errs, err) + case p == nil: + default: + m.BatchPoints.AddPoints(p) } - m.BatchPoints.AddPoints(p) - return nil } for _, asset := range m.Sites { pts, err := SitePoints(asset, m.TS) - errs = append(errs, processPoints(m, pts, err)) + processPoints(m, pts, err) } for _, asset := range m.Clients { pts, err := ClientPoints(asset, m.TS) - errs = append(errs, processPoints(m, pts, err)) + processPoints(m, pts, err) } for _, asset := range m.IDSList { pts, err := IDSPoints(asset) // no m.TS. - errs = append(errs, processPoints(m, pts, err)) + processPoints(m, pts, err) } if m.Devices == nil { @@ -201,19 +209,19 @@ func (m *Metrics) ProcessPoints() []error { } for _, asset := range m.Devices.UAPs { pts, err := UAPPoints(asset, m.TS) - errs = append(errs, processPoints(m, pts, err)) + processPoints(m, pts, err) } for _, asset := range m.Devices.USGs { pts, err := USGPoints(asset, m.TS) - errs = append(errs, processPoints(m, pts, err)) + processPoints(m, pts, err) } for _, asset := range m.Devices.USWs { pts, err := USWPoints(asset, m.TS) - errs = append(errs, processPoints(m, pts, err)) + processPoints(m, pts, err) } for _, asset := range m.Devices.UDMs { pts, err := UDMPoints(asset, m.TS) - errs = append(errs, processPoints(m, pts, err)) + processPoints(m, pts, err) } return errs }