Merge pull request #110 from davidnewhall/dn2_udm_non_pro

Add AP support to UDM. Fix restart on linux/systemd. Add more debug.
This commit is contained in:
David Newhall II 2019-09-09 20:00:43 -07:00 committed by GitHub
commit c24ddcc874
11 changed files with 267 additions and 212 deletions

View File

@ -11,7 +11,7 @@ HBREPO="golift/homebrew-mugs"
MAINT="David Newhall II <david at sleepers dot pro>" MAINT="David Newhall II <david at sleepers dot pro>"
VENDOR="Go Lift <code at golift dot io>" VENDOR="Go Lift <code at golift dot io>"
DESC="Polls a UniFi controller and exports metrics to InfluxDB" 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 # Example must exist at examples/$CONFIG_FILE.example
CONFIG_FILE="up.conf" CONFIG_FILE="up.conf"
LICENSE="MIT" LICENSE="MIT"

View File

@ -30,12 +30,12 @@
version = "v1.0.3" version = "v1.0.3"
[[projects]] [[projects]]
digest = "1:8a7dc583b5300f5d3f2602769b11127193330f74bb0a31e135d7354a1f96374a" digest = "1:8b8439a870abfe8df15cd9963fe7702d20fc55cd0f2375304b4eecc955b45902"
name = "golift.io/unifi" name = "golift.io/unifi"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "65d8c5a10faeb8180053a760d20800baf515f01a" revision = "a96d3c9d2e02e41013974e6595f7df581cf194dc"
version = "v4.0.2" version = "v4.1.2"
[[projects]] [[projects]]
digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96" digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96"

View File

@ -1,13 +1,13 @@
<img width="320px" src="https://raw.githubusercontent.com/wiki/davidnewhall/unifi-poller/images/unifi-poller-logo.png"> <img width="320px" src="https://raw.githubusercontent.com/wiki/davidnewhall/unifi-poller/images/unifi-poller-logo.png">
[![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) [![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) [![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) [![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) [![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) [![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) [![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) [![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). 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. I'm willing to help if you have troubles.
Open an [Issue](https://github.com/davidnewhall/unifi-poller/issues) and 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 we'll figure out how to get things working for you. You can also get help in
my [Discord server](https://discord.gg/DyVsMyt); sometimes I look at it too! the #unifi-poller channel on the [Ubiquiti Discord server](https://discord.gg/KnyKYt2).
## Description ## Description

View File

@ -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).**

View File

@ -12,6 +12,7 @@ ExecStart=/usr/bin/{{BINARY}} $DAEMON_OPTS
EnvironmentFile=-/etc/default/{{BINARY}} EnvironmentFile=-/etc/default/{{BINARY}}
EnvironmentFile=-/etc/sysconfig/{{BINARY}} EnvironmentFile=-/etc/sysconfig/{{BINARY}}
Restart=always Restart=always
RestartSec=10
StandardOutput=syslog StandardOutput=syslog
StandardError=syslog StandardError=syslog
SyslogIdentifier={{BINARY}} SyslogIdentifier={{BINARY}}

View File

@ -16,7 +16,7 @@ import (
influx "github.com/influxdata/influxdb1-client/v2" influx "github.com/influxdata/influxdb1-client/v2"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"golift.io/unifi" "golift.io/unifi"
"gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
// Version is injected by the Makefile // Version is injected by the Makefile
@ -25,12 +25,12 @@ var Version = "development"
const ( const (
// App defaults in case they're missing from the config. // App defaults in case they're missing from the config.
defaultInterval = 30 * time.Second defaultInterval = 30 * time.Second
defaultInfxDb = "unifi" defaultInfluxDB = "unifi"
defaultInfxUser = "unifi" defaultInfluxUser = "unifi"
defaultInfxPass = "unifi" defaultInfluxPass = "unifi"
defaultInfxURL = "http://127.0.0.1:8086" defaultInfluxURL = "http://127.0.0.1:8086"
defaultUnifUser = "influx" defaultUnifiUser = "influx"
defaultUnifURL = "https://127.0.0.1:8443" defaultUnifiURL = "https://127.0.0.1:8443"
) )
// ENVConfigPrefix is the prefix appended to an env variable tag // ENVConfigPrefix is the prefix appended to an env variable tag

View File

@ -55,6 +55,7 @@ func ClientPoints(c *unifi.Client, now time.Time) ([]*influx.Point, error) {
"ip": c.IP, "ip": c.IP,
"essid": c.Essid, "essid": c.Essid,
"bssid": c.Bssid, "bssid": c.Bssid,
"radio_desc": c.RadioDescription,
"hostname": c.Hostname, "hostname": c.Hostname,
"dpi_stats_last_updated": c.DpiStatsLastUpdated, "dpi_stats_last_updated": c.DpiStatsLastUpdated,
"last_seen_by_uap": c.LastSeenByUAP, "last_seen_by_uap": c.LastSeenByUAP,

View File

@ -15,9 +15,10 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) {
} }
tags := map[string]string{ tags := map[string]string{
"id": u.ID, "id": u.ID,
"ip": u.IP,
"mac": u.Mac, "mac": u.Mac,
"device_type": u.Stat.O, "device_type": u.Stat.Ap.O,
"device_oid": u.Stat.Oid, "device_oid": u.Stat.Ap.Oid,
"device_ap": u.Stat.Ap.Ap, "device_ap": u.Stat.Ap.Ap,
"site_id": u.SiteID, "site_id": u.SiteID,
"site_name": u.SiteName, "site_name": u.SiteName,
@ -30,32 +31,22 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) {
"device_id": u.DeviceID, "device_id": u.DeviceID,
"has_eth1": u.HasEth1.Txt, "has_eth1": u.HasEth1.Txt,
"inform_ip": u.InformIP, "inform_ip": u.InformIP,
"isolated": u.Isolated.Txt,
"known_cfgversion": u.KnownCfgversion, "known_cfgversion": u.KnownCfgversion,
"model": u.Model, "model": u.Model,
"outdoor_mode_override": u.OutdoorModeOverride,
"serial": u.Serial, "serial": u.Serial,
"type": u.Type, "type": u.Type,
"vwireEnabled": u.VwireEnabled.Txt,
} }
fields := map[string]interface{}{ fields := map[string]interface{}{
"ip": u.IP, "ip": u.IP,
"bytes": u.Bytes.Val, "bytes": u.Bytes.Val,
"bytes_d": u.BytesD.Val,
"bytes_r": u.BytesR.Val,
"last_seen": u.LastSeen.Val, "last_seen": u.LastSeen.Val,
"rx_bytes": u.RxBytes.Val, "rx_bytes": u.RxBytes.Val,
"rx_bytes-d": u.RxBytesD.Val,
"tx_bytes": u.TxBytes.Val, "tx_bytes": u.TxBytes.Val,
"tx_bytes-d": u.TxBytesD.Val,
"uptime": u.Uptime.Val, "uptime": u.Uptime.Val,
"scanning": u.Scanning.Val,
"spectrum_scanning": u.SpectrumScanning.Val,
"roll_upgrade": u.Rollupgrade.Val,
"state": u.State, "state": u.State,
"upgradable": u.Upgradable.Val, "user-num_sta": int(u.UserNumSta.Val),
"user-num_sta": u.UserNumSta, "guest-num_sta": int(u.GuestNumSta.Val),
"guest-num_sta": u.GuestNumSta, "num_sta": u.NumSta.Val,
"version": u.Version, "version": u.Version,
"loadavg_1": u.SysStats.Loadavg1.Val, "loadavg_1": u.SysStats.Loadavg1.Val,
"loadavg_5": u.SysStats.Loadavg5.Val, "loadavg_5": u.SysStats.Loadavg5.Val,
@ -66,120 +57,64 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) {
"cpu": u.SystemStats.CPU.Val, "cpu": u.SystemStats.CPU.Val,
"mem": u.SystemStats.Mem.Val, "mem": u.SystemStats.Mem.Val,
"system_uptime": u.SystemStats.Uptime.Val, "system_uptime": u.SystemStats.Uptime.Val,
"stat_guest-wifi0-rx_packets": u.Stat.GuestWifi0RxPackets.Val, // Accumulative Statistics.
"stat_guest-wifi1-rx_packets": u.Stat.GuestWifi1RxPackets.Val, "stat_user-rx_packets": u.Stat.Ap.UserRxPackets.Val,
"stat_user-wifi1-rx_packets": u.Stat.UserWifi1RxPackets.Val, "stat_guest-rx_packets": u.Stat.Ap.GuestRxPackets.Val,
"stat_user-wifi0-rx_packets": u.Stat.UserWifi0RxPackets.Val, "stat_rx_packets": u.Stat.Ap.RxPackets.Val,
"stat_user-rx_packets": u.Stat.UserRxPackets.Val, "stat_user-rx_bytes": u.Stat.Ap.UserRxBytes.Val,
"stat_guest-rx_packets": u.Stat.GuestRxPackets.Val, "stat_guest-rx_bytes": u.Stat.Ap.GuestRxBytes.Val,
"stat_wifi0-rx_packets": u.Stat.Wifi0RxPackets.Val, "stat_rx_bytes": u.Stat.Ap.RxBytes.Val,
"stat_wifi1-rx_packets": u.Stat.Wifi1RxPackets.Val, "stat_user-rx_errors": u.Stat.Ap.UserRxErrors.Val,
"stat_rx_packets": u.Stat.RxPackets.Val, "stat_guest-rx_errors": u.Stat.Ap.GuestRxErrors.Val,
"stat_guest-wifi0-rx_bytes": u.Stat.GuestWifi0RxBytes.Val, "stat_rx_errors": u.Stat.Ap.RxErrors.Val,
"stat_guest-wifi1-rx_bytes": u.Stat.GuestWifi1RxBytes.Val, "stat_user-rx_dropped": u.Stat.Ap.UserRxDropped.Val,
"stat_user-wifi1-rx_bytes": u.Stat.UserWifi1RxBytes.Val, "stat_guest-rx_dropped": u.Stat.Ap.GuestRxDropped.Val,
"stat_user-wifi0-rx_bytes": u.Stat.UserWifi0RxBytes.Val, "stat_rx_dropped": u.Stat.Ap.RxDropped.Val,
"stat_user-rx_bytes": u.Stat.UserRxBytes.Val, "stat_user-rx_crypts": u.Stat.Ap.UserRxCrypts.Val,
"stat_guest-rx_bytes": u.Stat.GuestRxBytes.Val, "stat_guest-rx_crypts": u.Stat.Ap.GuestRxCrypts.Val,
"stat_wifi0-rx_bytes": u.Stat.Wifi0RxBytes.Val, "stat_rx_crypts": u.Stat.Ap.RxCrypts.Val,
"stat_wifi1-rx_bytes": u.Stat.Wifi1RxBytes.Val, "stat_user-rx_frags": u.Stat.Ap.UserRxFrags.Val,
"stat_rx_bytes": u.Stat.RxBytes.Val, "stat_guest-rx_frags": u.Stat.Ap.GuestRxFrags.Val,
"stat_guest-wifi0-rx_errors": u.Stat.GuestWifi0RxErrors.Val, "stat_rx_frags": u.Stat.Ap.RxFrags.Val,
"stat_guest-wifi1-rx_errors": u.Stat.GuestWifi1RxErrors.Val, "stat_user-tx_packets": u.Stat.Ap.UserTxPackets.Val,
"stat_user-wifi1-rx_errors": u.Stat.UserWifi1RxErrors.Val, "stat_guest-tx_packets": u.Stat.Ap.GuestTxPackets.Val,
"stat_user-wifi0-rx_errors": u.Stat.UserWifi0RxErrors.Val, "stat_tx_packets": u.Stat.Ap.TxPackets.Val,
"stat_user-rx_errors": u.Stat.UserRxErrors.Val, "stat_user-tx_bytes": u.Stat.Ap.UserTxBytes.Val,
"stat_guest-rx_errors": u.Stat.GuestRxErrors.Val, "stat_guest-tx_bytes": u.Stat.Ap.GuestTxBytes.Val,
"stat_wifi0-rx_errors": u.Stat.Wifi0RxErrors.Val, "stat_tx_bytes": u.Stat.Ap.TxBytes.Val,
"stat_wifi1-rx_errors": u.Stat.Wifi1RxErrors.Val, "stat_user-tx_errors": u.Stat.Ap.UserTxErrors.Val,
"stat_rx_errors": u.Stat.RxErrors.Val, "stat_guest-tx_errors": u.Stat.Ap.GuestTxErrors.Val,
"stat_guest-wifi0-rx_dropped": u.Stat.GuestWifi0RxDropped.Val, "stat_tx_errors": u.Stat.Ap.TxErrors.Val,
"stat_guest-wifi1-rx_dropped": u.Stat.GuestWifi1RxDropped.Val, "stat_user-tx_dropped": u.Stat.Ap.UserTxDropped.Val,
"stat_user-wifi1-rx_dropped": u.Stat.UserWifi1RxDropped.Val, "stat_guest-tx_dropped": u.Stat.Ap.GuestTxDropped.Val,
"stat_user-wifi0-rx_dropped": u.Stat.UserWifi0RxDropped.Val, "stat_tx_dropped": u.Stat.Ap.TxDropped.Val,
"stat_user-rx_dropped": u.Stat.UserRxDropped.Val, "stat_user-tx_retries": u.Stat.Ap.UserTxRetries.Val,
"stat_guest-rx_dropped": u.Stat.GuestRxDropped.Val, "stat_guest-tx_retries": u.Stat.Ap.GuestTxRetries.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,
} }
pt, err := influx.NewPoint("uap", tags, fields, now) pt, err := influx.NewPoint("uap", tags, fields, now)
if err != nil { if err != nil {
return nil, err 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 // Loop each virtual AP (ESSID) and extract data for it
// from radio_tables and radio_table_stats. // from radio_tables and radio_table_stats.
for _, s := range u.VapTable { for _, s := range vt {
tags["device_name"] = u.Name tags["device_name"] = name
tags["device_id"] = u.ID tags["device_id"] = id
tags["device_mac"] = u.Mac tags["device_mac"] = mac
tags["site_name"] = u.SiteName tags["site_name"] = sitename
tags["ap_mac"] = s.ApMac tags["ap_mac"] = s.ApMac
tags["bssid"] = s.Bssid tags["bssid"] = s.Bssid
tags["id"] = s.ID 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_total"] = s.WifiTxLatencyMov.Total.Val
fields["wifi_tx_latency_mov_cuont"] = s.WifiTxLatencyMov.TotalCount.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 { if p.Name != s.RadioName {
continue continue
} }
@ -249,7 +184,7 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) {
fields["tx_power"] = p.TxPower.Val fields["tx_power"] = p.TxPower.Val
} }
for _, p := range u.RadioTableStats { for _, p := range rts {
if p.Name != s.RadioName { if p.Name != s.RadioName {
continue continue
} }
@ -269,7 +204,7 @@ func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) {
fields["user-num_sta"] = p.UserNumSta.Val 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 { if err != nil {
return points, err return points, err
} }

View File

@ -53,6 +53,7 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) {
"uptime": u.Uptime.Val, "uptime": u.Uptime.Val,
"state": u.State.Val, "state": u.State.Val,
"user-num_sta": u.UserNumSta.Val, "user-num_sta": u.UserNumSta.Val,
"num_sta": u.NumSta.Val,
"version": u.Version, "version": u.Version,
"num_desktop": u.NumDesktop.Val, "num_desktop": u.NumDesktop.Val,
"num_handheld": u.NumHandheld.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{}{ fields = map[string]interface{}{
"fw_caps": u.FwCaps.Val, "fw_caps": u.FwCaps.Val,
"guest-num_sta": u.GuestNumSta.Val, "guest-num_sta": u.GuestLanNumSta.Val,
"ip": u.IP, "ip": u.IP,
"bytes": u.Bytes.Val, "bytes": u.Bytes.Val,
"fan_level": float64(0), "fan_level": float64(0),
@ -185,7 +186,8 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) {
"tx_bytes": u.TxBytes.Val, "tx_bytes": u.TxBytes.Val,
"uptime": u.Uptime.Val, "uptime": u.Uptime.Val,
"state": u.State.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, "version": u.Version,
"loadavg_1": u.SysStats.Loadavg1.Val, "loadavg_1": u.SysStats.Loadavg1.Val,
"loadavg_5": u.SysStats.Loadavg5.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, "cpu": u.SystemStats.CPU.Val,
"mem": u.SystemStats.Mem.Val, "mem": u.SystemStats.Mem.Val,
"system_uptime": u.SystemStats.Uptime.Val, "system_uptime": u.SystemStats.Uptime.Val,
"stat_bytes": u.Stat.Bytes.Val, "stat_bytes": u.Stat.Sw.Bytes.Val,
"stat_rx_bytes": u.Stat.RxBytes.Val, "stat_rx_bytes": u.Stat.Sw.RxBytes.Val,
"stat_rx_crypts": u.Stat.RxCrypts.Val, "stat_rx_crypts": u.Stat.Sw.RxCrypts.Val,
"stat_rx_dropped": u.Stat.RxDropped.Val, "stat_rx_dropped": u.Stat.Sw.RxDropped.Val,
"stat_rx_errors": u.Stat.RxErrors.Val, "stat_rx_errors": u.Stat.Sw.RxErrors.Val,
"stat_rx_frags": u.Stat.RxFrags.Val, "stat_rx_frags": u.Stat.Sw.RxFrags.Val,
"stat_rx_packets": u.Stat.TxPackets.Val, "stat_rx_packets": u.Stat.Sw.TxPackets.Val,
"stat_tx_bytes": u.Stat.TxBytes.Val, "stat_tx_bytes": u.Stat.Sw.TxBytes.Val,
"stat_tx_dropped": u.Stat.TxDropped.Val, "stat_tx_dropped": u.Stat.Sw.TxDropped.Val,
"stat_tx_errors": u.Stat.TxErrors.Val, "stat_tx_errors": u.Stat.Sw.TxErrors.Val,
"stat_tx_packets": u.Stat.TxPackets.Val, "stat_tx_packets": u.Stat.Sw.TxPackets.Val,
"stat_tx_retries": u.Stat.TxRetries.Val, "stat_tx_retries": u.Stat.Sw.TxRetries.Val,
"uplink_depth": "0",
} }
pt, err = influx.NewPoint("usw", tags, fields, now) pt, err = influx.NewPoint("usw", tags, fields, now)
if err != nil { if err != nil {
@ -321,5 +322,95 @@ func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) {
} }
points = append(points, pt) points = append(points, pt)
} }
if u.Stat.Ap == nil {
return points, 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
} }

View File

@ -16,16 +16,17 @@ import (
// Parses flags, parses config and executes Run(). // Parses flags, parses config and executes Run().
func Start() error { func Start() error {
log.SetFlags(log.LstdFlags) log.SetFlags(log.LstdFlags)
up := &UnifiPoller{Flag: &Flag{}, up := &UnifiPoller{
Flag: &Flag{},
Config: &Config{ Config: &Config{
// Preload our defaults. // Preload our defaults.
InfluxURL: defaultInfxURL, InfluxURL: defaultInfluxURL,
InfluxUser: defaultInfxUser, InfluxUser: defaultInfluxUser,
InfluxPass: defaultInfxPass, InfluxPass: defaultInfluxPass,
InfluxDB: defaultInfxDb, InfluxDB: defaultInfluxDB,
UnifiUser: defaultUnifUser, UnifiUser: defaultUnifiUser,
UnifiPass: os.Getenv("UNIFI_PASSWORD"), // deprecated name. UnifiPass: os.Getenv("UNIFI_PASSWORD"), // deprecated name.
UnifiBase: defaultUnifURL, UnifiBase: defaultUnifiURL,
Interval: Duration{defaultInterval}, Interval: Duration{defaultInterval},
Sites: []string{"all"}, Sites: []string{"all"},
}} }}
@ -53,14 +54,14 @@ func Start() error {
func (f *Flag) Parse(args []string) { func (f *Flag) Parse(args []string) {
f.FlagSet = pflag.NewFlagSet("unifi-poller", pflag.ExitOnError) f.FlagSet = pflag.NewFlagSet("unifi-poller", pflag.ExitOnError)
f.Usage = func() { 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.PrintDefaults()
} }
f.StringVarP(&f.DumpJSON, "dumpjson", "j", "", f.StringVarP(&f.DumpJSON, "dumpjson", "j", "",
"This debug option prints a json payload and exits. See man page for more info.") "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.StringVarP(&f.ConfigFile, "config", "c", DefaultConfFile, "Poller config file path.")
f.BoolVarP(&f.ShowVer, "version", "v", false, "Print the version and exit.") 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. // Run invokes all the application logic and routines.
@ -119,5 +120,6 @@ func (u *UnifiPoller) GetUnifi() (err error) {
if err != nil { if err != nil {
return fmt.Errorf("unifi controller: %v", err) return fmt.Errorf("unifi controller: %v", err)
} }
u.LogDebugf("Authenticated with controller successfully")
return u.CheckSites() return u.CheckSites()
} }

View File

@ -16,6 +16,7 @@ func (u *UnifiPoller) CheckSites() error {
if strings.Contains(strings.ToLower(u.Config.Mode), "lambda") { if strings.Contains(strings.ToLower(u.Config.Mode), "lambda") {
return nil // Skip this in lambda mode. return nil // Skip this in lambda mode.
} }
u.LogDebugf("Checking Controller Sites List")
sites, err := u.Unifi.GetSites() sites, err := u.Unifi.GetSites()
if err != nil { if err != nil {
return err return err
@ -116,8 +117,12 @@ func (u *UnifiPoller) CollectMetrics() (*Metrics, error) {
// This function currently adds parent device names to client metrics. // This function currently adds parent device names to client metrics.
func (u *UnifiPoller) AugmentMetrics(metrics *Metrics) error { func (u *UnifiPoller) AugmentMetrics(metrics *Metrics) error {
devices := make(map[string]string) devices := make(map[string]string)
bssdIDs := make(map[string]string)
for _, r := range metrics.UAPs { for _, r := range metrics.UAPs {
devices[r.Mac] = r.Name 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 { for _, r := range metrics.USGs {
devices[r.Mac] = r.Name 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].SwName = devices[c.SwMac]
metrics.Clients[i].ApName = devices[c.ApMac] metrics.Clients[i].ApName = devices[c.ApMac]
metrics.Clients[i].GwName = devices[c.GwMac] metrics.Clients[i].GwName = devices[c.GwMac]
metrics.Clients[i].RadioDescription = bssdIDs[metrics.Clients[i].Bssid] + metrics.Clients[i].RadioProto
} }
return nil 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! // still check&log it in case the data going is skewed up and causes errors!
func (m *Metrics) ProcessPoints() []error { func (m *Metrics) ProcessPoints() []error {
errs := []error{} errs := []error{}
processPoints := func(m *Metrics, p []*influx.Point, err error) error { processPoints := func(m *Metrics, p []*influx.Point, err error) {
if err != nil || p == nil { switch {
return err 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 { for _, asset := range m.Sites {
pts, err := SitePoints(asset, m.TS) pts, err := SitePoints(asset, m.TS)
errs = append(errs, processPoints(m, pts, err)) processPoints(m, pts, err)
} }
for _, asset := range m.Clients { for _, asset := range m.Clients {
pts, err := ClientPoints(asset, m.TS) pts, err := ClientPoints(asset, m.TS)
errs = append(errs, processPoints(m, pts, err)) processPoints(m, pts, err)
} }
for _, asset := range m.IDSList { for _, asset := range m.IDSList {
pts, err := IDSPoints(asset) // no m.TS. pts, err := IDSPoints(asset) // no m.TS.
errs = append(errs, processPoints(m, pts, err)) processPoints(m, pts, err)
} }
if m.Devices == nil { if m.Devices == nil {
@ -201,19 +209,19 @@ func (m *Metrics) ProcessPoints() []error {
} }
for _, asset := range m.Devices.UAPs { for _, asset := range m.Devices.UAPs {
pts, err := UAPPoints(asset, m.TS) pts, err := UAPPoints(asset, m.TS)
errs = append(errs, processPoints(m, pts, err)) processPoints(m, pts, err)
} }
for _, asset := range m.Devices.USGs { for _, asset := range m.Devices.USGs {
pts, err := USGPoints(asset, m.TS) pts, err := USGPoints(asset, m.TS)
errs = append(errs, processPoints(m, pts, err)) processPoints(m, pts, err)
} }
for _, asset := range m.Devices.USWs { for _, asset := range m.Devices.USWs {
pts, err := USWPoints(asset, m.TS) pts, err := USWPoints(asset, m.TS)
errs = append(errs, processPoints(m, pts, err)) processPoints(m, pts, err)
} }
for _, asset := range m.Devices.UDMs { for _, asset := range m.Devices.UDMs {
pts, err := UDMPoints(asset, m.TS) pts, err := UDMPoints(asset, m.TS)
errs = append(errs, processPoints(m, pts, err)) processPoints(m, pts, err)
} }
return errs return errs
} }