Merge pull request #142 from davidnewhall/dn2_moremoremore
Giving Influx some love on this one.
This commit is contained in:
commit
00794f8561
|
|
@ -56,10 +56,6 @@ unifi_user = "influx"
|
|||
unifi_pass = "4BB9345C-2341-48D7-99F5-E01B583FF77F"
|
||||
unifi_url = "https://127.0.0.1:8443"
|
||||
|
||||
# Enable collection of Intrusion Detection System Data (InfluxDB only).
|
||||
# Only useful if IDS or IPS are enabled on one of the sites.
|
||||
collect_ids = false
|
||||
|
||||
# Some controllers or reverse proxy configurations do not allow cookies to be
|
||||
# re-user on every request (every interval). This setting provides a workaround
|
||||
# That causes the poller to re-auth (login) to the controller on every interval.
|
||||
|
|
@ -67,6 +63,14 @@ collect_ids = false
|
|||
# a few more requests to your controller every interval.
|
||||
reauthenticate = false
|
||||
|
||||
# Enable collection of Intrusion Detection System Data (InfluxDB only).
|
||||
# Only useful if IDS or IPS are enabled on one of the sites.
|
||||
save_ids = false
|
||||
|
||||
# Enable collection of site data. This data powers the Network Sites dashboard.
|
||||
# It's not valuable to everyone and setting this to false will save resources.
|
||||
save_sites = true
|
||||
|
||||
# If your UniFi controller has a valid SSL certificate (like lets encrypt),
|
||||
# you can enable this option to validate it. Otherwise, any SSL certificate is
|
||||
# valid. If you don't know if you have a valid SSL cert, then you don't have one.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
"unifi_user": "influx",
|
||||
"unifi_pass": "",
|
||||
"unifi_url": "https://127.0.0.1:8443",
|
||||
"collect_ids": false,
|
||||
"save_ids": false,
|
||||
"save_sites": true,
|
||||
"reauthenticate": false,
|
||||
"verify_ssl": false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,99 +2,33 @@
|
|||
<!--
|
||||
#######################################################
|
||||
# UniFi Poller primary configuration file. XML FORMAT #
|
||||
# provided values are defaults #
|
||||
# provided values are defaults. See up.conf.example! #
|
||||
#######################################################
|
||||
-->
|
||||
<unifi-poller>
|
||||
<!--
|
||||
# If the controller has more than one site, specify which sites to poll here.
|
||||
# Set this to "default" to poll only the first site on the controller.
|
||||
# A setting of "all" will poll all sites; this works if you only have 1 site too.
|
||||
Add more sites by adding additional lines:
|
||||
<sites>site1</sites>
|
||||
<sites>site2</sites>
|
||||
-->
|
||||
|
||||
<sites>all</sites>
|
||||
<interval>60s</interval>
|
||||
|
||||
<!--
|
||||
# The UniFi Controller only updates traffic stats about every 30 seconds.
|
||||
# Setting this to something lower may lead to "zeros" in your data.
|
||||
# If you're getting zeros now, set this to "1m"
|
||||
-->
|
||||
<interval>30s</interval>
|
||||
|
||||
<!--
|
||||
# Turns on line numbers, microsecond logging, and a per-device log.
|
||||
# The default is false, but I personally leave this on at home (four devices).
|
||||
# This may be noisy if you have a lot of devices. It adds one line per device.
|
||||
-->
|
||||
<debug>false</debug>
|
||||
|
||||
<!--
|
||||
# Turns off per-interval logs. Only startup and error logs will be emitted.
|
||||
# Recommend enabling debug with this setting for better error logging.
|
||||
-->
|
||||
<quiet>false</quiet>
|
||||
|
||||
<!--
|
||||
# Which mode to run this application in. The default mode is "influx". Providing
|
||||
# an invalid mode will also result in "influx". In this default mode the application
|
||||
# runs as a daemon and polls the controller at the configured interval.
|
||||
#
|
||||
# There are two other options at this time: "influxlambda" and "prometheus"
|
||||
#
|
||||
# Mode "influxlambda" makes the application exit after collecting and reporting metrics
|
||||
# to InfluxDB one time. This mode requires an external process like an AWS Lambda
|
||||
# or a simple crontab to keep the timings accurate on UniFi Poller run intervals.
|
||||
#
|
||||
# Mode "prometheus" opens an HTTP server on port 9130 and exports the metrics at
|
||||
# /metrics for polling collection by a prometheus server. This disables influxdb.
|
||||
# IMPORTANT: The prometheus mode is still beta.
|
||||
# Please help us test and provide your feedback on the github repo!
|
||||
-->
|
||||
<mode>influx</mode>
|
||||
|
||||
<!--
|
||||
# This controls on which ip and port /metrics is exported when mode is "prometheus".
|
||||
# This has no effect in other modes. Must contain a colon and port.
|
||||
-->
|
||||
<http_listen>0.0.0.0:9130</http_listen>
|
||||
|
||||
<!--
|
||||
# InfluxDB does not require auth by default, so the user/password are probably unimportant.
|
||||
-->
|
||||
<influx_db>unifi</influx_db>
|
||||
<influx_pass>unifi</influx_pass>
|
||||
<influx_url>http://127.0.0.1:8086</influx_url>
|
||||
<influx_user>unifi</influx_user>
|
||||
<!--
|
||||
# If your InfluxDB uses an invalid SSL cert, set this to true.
|
||||
-->
|
||||
<influx_insecure_ssl>false</influx_insecure_ssl>
|
||||
|
||||
<!--
|
||||
# Make a read-only user in the UniFi Admin Settings.
|
||||
-->
|
||||
<unifi_user>influx</unifi_user>
|
||||
<unifi_pass></unifi_pass>
|
||||
<unifi_url>https://127.0.0.1:8443</unifi_url>
|
||||
<!--
|
||||
# Enable collection of Intrusion Detection System Data (InfluxDB only).
|
||||
# Only useful if IDS or IPS are enabled on one of the sites.
|
||||
-->
|
||||
<collect_ids>false</collect_ids>
|
||||
<!--
|
||||
# Some controllers or reverse proxy configurations do not allow cookies to be
|
||||
# re-user on every request (every interval). This setting provides a workaround
|
||||
# That causes the poller to re-auth (login) to the controller on every interval.
|
||||
# Only enable this if you get login errors after 30 seconds. This will generate
|
||||
# a few more requests to your controller every interval.
|
||||
-->
|
||||
<reauthenticate>false</reauthenticate>
|
||||
<!--
|
||||
# If your UniFi controller has a valid SSL certificate, you can enable
|
||||
# this option to validate it. Otherwise, any SSL certificate is valid.
|
||||
-->
|
||||
<verify_ssl>false</verify_ssl>
|
||||
|
||||
<save_ids>false</save_ids>
|
||||
<save_sites>true</save_sites>
|
||||
|
||||
</unifi-poller>
|
||||
|
|
|
|||
|
|
@ -1,73 +1,28 @@
|
|||
########################################################
|
||||
# UniFi Poller primary configuration file. YAML FORMAT #
|
||||
# provided values are defaults #
|
||||
# provided values are defaults. See up.conf.example! #
|
||||
########################################################
|
||||
---
|
||||
# If the controller has more than one site, specify which sites to poll here.
|
||||
# Set this to "default" to poll only the first site on the controller.
|
||||
# A setting of "all" will poll all sites; this works if you only have 1 site too.
|
||||
sites:
|
||||
- all
|
||||
|
||||
# The UniFi Controller only updates traffic stats about every 30 seconds.
|
||||
# Setting this to something lower may lead to "zeros" in your data.
|
||||
# If you're getting zeros now, set this to "1m"
|
||||
# Only has effect if "mode" (below) is "influx" - other modes do not use interval.
|
||||
interval: "30s"
|
||||
|
||||
# Turns on line numbers, microsecond logging, and a per-device log.
|
||||
# The default is false, but I personally leave this on at home (four devices).
|
||||
# This may be noisy if you have a lot of devices. It adds one line per device.
|
||||
debug: false
|
||||
|
||||
# Turns off per-interval logs. Only startup and error logs will be emitted.
|
||||
# Recommend enabling debug with this setting for better error logging.
|
||||
quiet: false
|
||||
|
||||
# Which mode to run this application in. The default mode is "influx". Providing
|
||||
# an invalid mode will also result in "influx". In this default mode the application
|
||||
# runs as a daemon and polls the controller at the configured interval.
|
||||
#
|
||||
# There are two other options at this time: "influxlambda" and "prometheus"
|
||||
#
|
||||
# Mode "influxlambda" makes the application exit after collecting and reporting metrics
|
||||
# to InfluxDB one time. This mode requires an external process like an AWS Lambda
|
||||
# or a simple crontab to keep the timings accurate on UniFi Poller run intervals.
|
||||
#
|
||||
# Mode "prometheus" opens an HTTP server on port 9130 and exports the metrics at
|
||||
# /metrics for polling collection by a prometheus server. This disables influxdb.
|
||||
# IMPORTANT: The prometheus mode is still beta.
|
||||
# Please help us test and provide your feedback on the github repo!
|
||||
mode: "influx"
|
||||
|
||||
# This controls on which ip and port /metrics is exported when mode is "prometheus".
|
||||
# This has no effect in other modes. Must contain a colon and port.
|
||||
http_listen: "0.0.0.0:9130"
|
||||
|
||||
# InfluxDB does not require auth by default, so the user/password are probably unimportant.
|
||||
influx_url: "http://127.0.0.1:8086"
|
||||
influx_user: "unifi"
|
||||
influx_pass: "unifi"
|
||||
# Be sure to create this database.
|
||||
influx_db: "unifi"
|
||||
# If your InfluxDB uses an invalid SSL cert, set this to true.
|
||||
influx_insecure_ssl: false
|
||||
|
||||
# Make a read-only user in the UniFi Admin Settings.
|
||||
unifi_user: "influx"
|
||||
unifi_pass: ""
|
||||
unifi_url: "https://127.0.0.1:8443"
|
||||
|
||||
# Enable collection of Intrusion Detection System Data (InfluxDB only).
|
||||
# Only useful if IDS or IPS are enabled on one of the sites.
|
||||
collect_ids: false
|
||||
|
||||
# Some controllers or reverse proxy configurations do not allow cookies to be
|
||||
# re-user on every request (every interval). This setting provides a workaround
|
||||
# That causes the poller to re-auth (login) to the controller on every interval.
|
||||
# Only enable this if you get login errors after 30 seconds. This will generate
|
||||
# a few more requests to your controller every interval.
|
||||
reauthenticate: false
|
||||
|
||||
# If your UniFi controller has a valid SSL certificate, you can enable
|
||||
# this option to validate it. Otherwise, any SSL certificate is valid.
|
||||
verify_ssl: false
|
||||
save_ids: false
|
||||
save_sites: true
|
||||
|
|
|
|||
|
|
@ -1,111 +1,79 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// ClientPoints generates Unifi Client datapoints for InfluxDB.
|
||||
// batchClient generates Unifi Client datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func ClientPoints(c *unifi.Client, now time.Time) ([]*influx.Point, error) {
|
||||
func (u *InfluxUnifi) batchClient(r report, s *unifi.Client) {
|
||||
tags := map[string]string{
|
||||
"id": c.ID,
|
||||
"mac": c.Mac,
|
||||
"user_id": c.UserID,
|
||||
"site_id": c.SiteID,
|
||||
"site_name": c.SiteName,
|
||||
"network_id": c.NetworkID,
|
||||
"usergroup_id": c.UserGroupID,
|
||||
"ap_mac": c.ApMac,
|
||||
"gw_mac": c.GwMac,
|
||||
"sw_mac": c.SwMac,
|
||||
"ap_name": c.ApName,
|
||||
"gw_name": c.GwName,
|
||||
"sw_name": c.SwName,
|
||||
"oui": c.Oui,
|
||||
"radio_name": c.RadioName,
|
||||
"radio": c.Radio,
|
||||
"radio_proto": c.RadioProto,
|
||||
"name": c.Name,
|
||||
"fixed_ip": c.FixedIP,
|
||||
"sw_port": c.SwPort.Txt,
|
||||
"os_class": c.OsClass.Txt,
|
||||
"os_name": c.OsName.Txt,
|
||||
"dev_cat": c.DevCat.Txt,
|
||||
"dev_id": c.DevID.Txt,
|
||||
"dev_vendor": c.DevVendor.Txt,
|
||||
"dev_family": c.DevFamily.Txt,
|
||||
"is_11r": c.Is11R.Txt,
|
||||
"is_wired": c.IsWired.Txt,
|
||||
"is_guest": c.IsGuest.Txt,
|
||||
"is_guest_by_uap": c.IsGuestByUAP.Txt,
|
||||
"is_guest_by_ugw": c.IsGuestByUGW.Txt,
|
||||
"is_guest_by_usw": c.IsGuestByUSW.Txt,
|
||||
"noted": c.Noted.Txt,
|
||||
"powersave_enabled": c.PowersaveEnabled.Txt,
|
||||
"qos_policy_applied": c.QosPolicyApplied.Txt,
|
||||
"use_fixedip": c.UseFixedIP.Txt,
|
||||
"channel": c.Channel.Txt,
|
||||
"vlan": c.Vlan.Txt,
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
"ap_name": s.ApName,
|
||||
"gw_name": s.GwName,
|
||||
"sw_name": s.SwName,
|
||||
"oui": s.Oui,
|
||||
"radio_name": s.RadioName,
|
||||
"radio": s.Radio,
|
||||
"radio_proto": s.RadioProto,
|
||||
"name": s.Name,
|
||||
"fixed_ip": s.FixedIP,
|
||||
"sw_port": s.SwPort.Txt,
|
||||
"os_class": s.OsClass.Txt,
|
||||
"os_name": s.OsName.Txt,
|
||||
"dev_cat": s.DevCat.Txt,
|
||||
"dev_id": s.DevID.Txt,
|
||||
"dev_vendor": s.DevVendor.Txt,
|
||||
"dev_family": s.DevFamily.Txt,
|
||||
"is_wired": s.IsWired.Txt,
|
||||
"is_guest": s.IsGuest.Txt,
|
||||
"use_fixedip": s.UseFixedIP.Txt,
|
||||
"channel": s.Channel.Txt,
|
||||
"vlan": s.Vlan.Txt,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"anomalies": c.Anomalies,
|
||||
"ip": c.IP,
|
||||
"essid": c.Essid,
|
||||
"bssid": c.Bssid,
|
||||
"radio_desc": c.RadioDescription,
|
||||
"satisfaction": c.Satisfaction.Val,
|
||||
"hostname": c.Hostname,
|
||||
"dpi_stats_last_updated": c.DpiStatsLastUpdated,
|
||||
"last_seen_by_uap": c.LastSeenByUAP,
|
||||
"last_seen_by_ugw": c.LastSeenByUGW,
|
||||
"last_seen_by_usw": c.LastSeenByUSW,
|
||||
"uptime_by_uap": c.UptimeByUAP,
|
||||
"uptime_by_ugw": c.UptimeByUGW,
|
||||
"uptime_by_usw": c.UptimeByUSW,
|
||||
"assoc_time": c.AssocTime,
|
||||
"bytes_r": c.BytesR,
|
||||
"ccq": c.Ccq,
|
||||
"first_seen": c.FirstSeen,
|
||||
"idle_time": c.IdleTime,
|
||||
"last_seen": c.LastSeen,
|
||||
"latest_assoc_time": c.LatestAssocTime,
|
||||
"network": c.Network,
|
||||
"noise": c.Noise,
|
||||
"note": c.Note,
|
||||
"roam_count": c.RoamCount,
|
||||
"rssi": c.Rssi,
|
||||
"rx_bytes": c.RxBytes,
|
||||
"rx_bytes_r": c.RxBytesR,
|
||||
"rx_packets": c.RxPackets,
|
||||
"rx_rate": c.RxRate,
|
||||
"signal": c.Signal,
|
||||
"tx_bytes": c.TxBytes,
|
||||
"tx_bytes_r": c.TxBytesR,
|
||||
"tx_packets": c.TxPackets,
|
||||
"tx_retries": c.TxRetries,
|
||||
"tx_power": c.TxPower,
|
||||
"tx_rate": c.TxRate,
|
||||
"uptime": c.Uptime,
|
||||
"wifi_tx_attempts": c.WifiTxAttempts,
|
||||
"wired-rx_bytes": c.WiredRxBytes,
|
||||
"wired-rx_bytes-r": c.WiredRxBytesR,
|
||||
"wired-rx_packets": c.WiredRxPackets,
|
||||
"wired-tx_bytes": c.WiredTxBytes,
|
||||
"wired-tx_bytes-r": c.WiredTxBytesR,
|
||||
"wired-tx_packets": c.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,
|
||||
"anomalies": s.Anomalies,
|
||||
"ip": s.IP,
|
||||
"essid": s.Essid,
|
||||
"bssid": s.Bssid,
|
||||
"channel": s.Channel.Val,
|
||||
"hostname": s.Name,
|
||||
"radio_desc": s.RadioDescription,
|
||||
"satisfaction": s.Satisfaction.Val,
|
||||
"bytes_r": s.BytesR,
|
||||
"ccq": s.Ccq,
|
||||
"noise": s.Noise,
|
||||
"note": s.Note,
|
||||
"roam_count": s.RoamCount,
|
||||
"rssi": s.Rssi,
|
||||
"rx_bytes": s.RxBytes,
|
||||
"rx_bytes_r": s.RxBytesR,
|
||||
"rx_packets": s.RxPackets,
|
||||
"rx_rate": s.RxRate,
|
||||
"signal": s.Signal,
|
||||
"tx_bytes": s.TxBytes,
|
||||
"tx_bytes_r": s.TxBytesR,
|
||||
"tx_packets": s.TxPackets,
|
||||
"tx_retries": s.TxRetries,
|
||||
"tx_power": s.TxPower,
|
||||
"tx_rate": s.TxRate,
|
||||
"uptime": s.Uptime,
|
||||
"wifi_tx_attempts": s.WifiTxAttempts,
|
||||
"wired-rx_bytes": s.WiredRxBytes,
|
||||
"wired-rx_bytes-r": s.WiredRxBytesR,
|
||||
"wired-rx_packets": s.WiredRxPackets,
|
||||
"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,
|
||||
*/
|
||||
}
|
||||
pt, err := influx.NewPoint("clients", tags, fields, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []*influx.Point{pt}, nil
|
||||
r.send(&metric{Table: "clients", Tags: tags, Fields: fields})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// IDSPoints generates intrusion detection datapoints for InfluxDB.
|
||||
// batchIDS generates intrusion detection datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func IDSPoints(i *unifi.IDS) ([]*influx.Point, error) {
|
||||
func (u *InfluxUnifi) batchIDS(r report, i *unifi.IDS) {
|
||||
tags := map[string]string{
|
||||
"in_iface": i.InIface,
|
||||
"event_type": i.EventType,
|
||||
|
|
@ -36,9 +35,5 @@ func IDSPoints(i *unifi.IDS) ([]*influx.Point, error) {
|
|||
"srcipASN": i.SrcipASN,
|
||||
"usgipASN": i.UsgipASN,
|
||||
}
|
||||
pt, err := influx.NewPoint("intrusion_detect", tags, fields, i.Datetime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []*influx.Point{pt}, nil
|
||||
r.send(&metric{Table: "intrusion_detect", Tags: tags, Fields: fields})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,67 +3,140 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/davidnewhall/unifi-poller/pkg/metrics"
|
||||
client "github.com/influxdata/influxdb1-client/v2"
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
)
|
||||
|
||||
// Metrics contains all the data from the controller and an influx endpoint to send it to.
|
||||
type Metrics struct {
|
||||
*metrics.Metrics
|
||||
client.BatchPoints
|
||||
// Config defines the data needed to store metrics in InfluxDB
|
||||
type Config struct {
|
||||
Database string
|
||||
URL string
|
||||
User string
|
||||
Pass string
|
||||
BadSSL bool
|
||||
}
|
||||
|
||||
// ProcessPoints batches all device and client data into influxdb data points.
|
||||
// InfluxUnifi is returned by New() after you provide a Config.
|
||||
type InfluxUnifi struct {
|
||||
cf *Config
|
||||
influx influx.Client
|
||||
}
|
||||
|
||||
type metric struct {
|
||||
Table string
|
||||
Tags map[string]string
|
||||
Fields map[string]interface{}
|
||||
}
|
||||
|
||||
// New returns an InfluxDB interface.
|
||||
func New(c *Config) (*InfluxUnifi, error) {
|
||||
i, err := influx.NewHTTPClient(influx.HTTPConfig{
|
||||
Addr: c.URL,
|
||||
Username: c.User,
|
||||
Password: c.Pass,
|
||||
TLSConfig: &tls.Config{InsecureSkipVerify: c.BadSSL},
|
||||
})
|
||||
return &InfluxUnifi{cf: c, influx: i}, err
|
||||
}
|
||||
|
||||
// ReportMetrics batches all device and client data into influxdb data points.
|
||||
// Call this after you've collected all the data you care about.
|
||||
// This function is sorta weird and returns a slice of errors. The reasoning is
|
||||
// that some points may process while others fail, so we attempt to process them
|
||||
// all. This is (usually) run in a loop, so we can't really exit on error,
|
||||
// we just log the errors and tally them on a counter. In reality, this never
|
||||
// returns any errors because we control the data going in; cool right? But we
|
||||
// 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 []*client.Point, err error) {
|
||||
switch {
|
||||
case err != nil:
|
||||
errs = append(errs, err)
|
||||
case p == nil:
|
||||
default:
|
||||
m.AddPoints(p)
|
||||
}
|
||||
// Returns an error if influxdb calls fail, otherwise returns a report.
|
||||
func (u *InfluxUnifi) ReportMetrics(m *metrics.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
|
||||
r.bp, err = influx.NewBatchPoints(influx.BatchPointsConfig{Database: u.cf.Database})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("influx.NewBatchPoints: %v", err)
|
||||
}
|
||||
|
||||
for _, asset := range m.Sites {
|
||||
pts, err := SitePoints(asset, m.TS)
|
||||
processPoints(m, pts, err)
|
||||
}
|
||||
for _, asset := range m.Clients {
|
||||
pts, err := ClientPoints(asset, m.TS)
|
||||
processPoints(m, pts, err)
|
||||
}
|
||||
for _, asset := range m.IDSList {
|
||||
pts, err := IDSPoints(asset) // no m.TS.
|
||||
processPoints(m, pts, err)
|
||||
}
|
||||
go u.collect(r, r.ch)
|
||||
// Batch all the points.
|
||||
u.loopPoints(r)
|
||||
r.wg.Wait() // wait for all points to finish batching!
|
||||
|
||||
if m.Devices == nil {
|
||||
return errs
|
||||
// Send all the points.
|
||||
if err = u.influx.Write(r.bp); err != nil {
|
||||
return nil, fmt.Errorf("influxdb.Write(points): %v", err)
|
||||
}
|
||||
for _, asset := range m.Devices.UAPs {
|
||||
pts, err := UAPPoints(asset, m.TS)
|
||||
processPoints(m, pts, err)
|
||||
}
|
||||
for _, asset := range m.Devices.USGs {
|
||||
pts, err := USGPoints(asset, m.TS)
|
||||
processPoints(m, pts, err)
|
||||
}
|
||||
for _, asset := range m.Devices.USWs {
|
||||
pts, err := USWPoints(asset, m.TS)
|
||||
processPoints(m, pts, err)
|
||||
}
|
||||
for _, asset := range m.Devices.UDMs {
|
||||
pts, err := UDMPoints(asset, m.TS)
|
||||
processPoints(m, pts, err)
|
||||
}
|
||||
return errs
|
||||
r.Elapsed = time.Since(r.Start)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// collect runs in a go routine and batches all the points.
|
||||
func (u *InfluxUnifi) collect(r report, ch chan *metric) {
|
||||
for m := range ch {
|
||||
pt, err := influx.NewPoint(m.Table, m.Tags, m.Fields, r.metrics().TS)
|
||||
if err != nil {
|
||||
r.error(err)
|
||||
} else {
|
||||
r.batch(m, pt)
|
||||
}
|
||||
r.done()
|
||||
}
|
||||
}
|
||||
|
||||
// loopPoints kicks off 3 or 7 go routines to process metrics and send them
|
||||
// to the collect routine through the metric channel.
|
||||
func (u *InfluxUnifi) loopPoints(r report) {
|
||||
m := r.metrics()
|
||||
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)
|
||||
}
|
||||
}()
|
||||
if m.Devices == nil {
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/davidnewhall/unifi-poller/pkg/metrics"
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
)
|
||||
|
||||
// Report is returned to the calling procedure after everything is processed.
|
||||
type Report struct {
|
||||
Metrics *metrics.Metrics
|
||||
Errors []error
|
||||
Total int
|
||||
Fields int
|
||||
Start time.Time
|
||||
Elapsed time.Duration
|
||||
ch chan *metric
|
||||
wg sync.WaitGroup
|
||||
bp influx.BatchPoints
|
||||
}
|
||||
|
||||
// report is an internal interface that can be mocked and overrridden for tests.
|
||||
type report interface {
|
||||
add()
|
||||
done()
|
||||
send(m *metric)
|
||||
error(err error)
|
||||
batch(m *metric, pt *influx.Point)
|
||||
metrics() *metrics.Metrics
|
||||
}
|
||||
|
||||
func (r *Report) metrics() *metrics.Metrics {
|
||||
return r.Metrics
|
||||
}
|
||||
|
||||
// satisfy gomnd
|
||||
const one = 1
|
||||
|
||||
func (r *Report) add() {
|
||||
r.wg.Add(one)
|
||||
}
|
||||
|
||||
func (r *Report) done() {
|
||||
r.wg.Add(-one)
|
||||
}
|
||||
|
||||
func (r *Report) send(m *metric) {
|
||||
r.wg.Add(one)
|
||||
r.ch <- m
|
||||
}
|
||||
|
||||
/* The following methods are not thread safe. */
|
||||
|
||||
func (r *Report) error(err error) {
|
||||
r.Errors = append(r.Errors, err)
|
||||
}
|
||||
|
||||
func (r *Report) batch(m *metric, p *influx.Point) {
|
||||
r.Total++
|
||||
r.Fields += len(m.Fields)
|
||||
r.bp.AddPoint(p)
|
||||
}
|
||||
|
|
@ -1,83 +1,56 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// SitePoints generates Unifi Sites' datapoints for InfluxDB.
|
||||
// batchSite generates Unifi Sites' datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func SitePoints(u *unifi.Site, now time.Time) ([]*influx.Point, error) {
|
||||
points := []*influx.Point{}
|
||||
for _, s := range u.Health {
|
||||
func (u *InfluxUnifi) batchSite(r report, s *unifi.Site) {
|
||||
for _, h := range s.Health {
|
||||
tags := map[string]string{
|
||||
"id": u.ID,
|
||||
"name": u.Name,
|
||||
"site_name": u.SiteName,
|
||||
"desc": u.Desc,
|
||||
"status": s.Status,
|
||||
"subsystem": s.Subsystem,
|
||||
"wan_ip": s.WanIP,
|
||||
"netmask": s.Netmask,
|
||||
"gw_name": s.GwName,
|
||||
"gw_mac": s.GwMac,
|
||||
"gw_version": s.GwVersion,
|
||||
"speedtest_status": s.SpeedtestStatus,
|
||||
"lan_ip": s.LanIP,
|
||||
"remote_user_enabled": s.RemoteUserEnabled.Txt,
|
||||
"site_to_site_enabled": s.SiteToSiteEnabled.Txt,
|
||||
"nameservers": strings.Join(s.Nameservers, ","),
|
||||
"gateways": strings.Join(s.Gateways, ","),
|
||||
"num_new_alarms": u.NumNewAlarms.Txt,
|
||||
"attr_hidden_id": u.AttrHiddenID,
|
||||
"attr_no_delete": u.AttrNoDelete.Txt,
|
||||
"name": s.Name,
|
||||
"site_name": s.SiteName,
|
||||
"desc": s.Desc,
|
||||
"status": h.Status,
|
||||
"subsystem": h.Subsystem,
|
||||
"wan_ip": h.WanIP,
|
||||
"gw_name": h.GwName,
|
||||
"lan_ip": h.LanIP,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"attr_hidden_id": u.AttrHiddenID,
|
||||
"attr_no_delete": u.AttrNoDelete.Val,
|
||||
"num_user": s.NumUser.Val,
|
||||
"num_guest": s.NumGuest.Val,
|
||||
"num_iot": s.NumIot.Val,
|
||||
"tx_bytes-r": s.TxBytesR.Val,
|
||||
"rx_bytes-r": s.RxBytesR.Val,
|
||||
"status": s.Status,
|
||||
"num_ap": s.NumAp.Val,
|
||||
"num_adopted": s.NumAdopted.Val,
|
||||
"num_disabled": s.NumDisabled.Val,
|
||||
"num_disconnected": s.NumDisconnected.Val,
|
||||
"num_pending": s.NumPending.Val,
|
||||
"num_gw": s.NumGw.Val,
|
||||
"wan_ip": s.WanIP,
|
||||
"num_sta": s.NumSta.Val,
|
||||
"gw_cpu": s.GwSystemStats.CPU.Val,
|
||||
"gw_mem": s.GwSystemStats.Mem.Val,
|
||||
"gw_uptime": s.GwSystemStats.Uptime.Val,
|
||||
"latency": s.Latency.Val,
|
||||
"uptime": s.Uptime.Val,
|
||||
"drops": s.Drops.Val,
|
||||
"xput_up": s.XputUp.Val,
|
||||
"xput_down": s.XputDown.Val,
|
||||
"speedtest_ping": s.SpeedtestPing.Val,
|
||||
"speedtest_lastrun": s.SpeedtestLastrun.Val,
|
||||
"num_sw": s.NumSw.Val,
|
||||
"remote_user_num_active": s.RemoteUserNumActive.Val,
|
||||
"remote_user_num_inactive": s.RemoteUserNumInactive.Val,
|
||||
"remote_user_rx_bytes": s.RemoteUserRxBytes.Val,
|
||||
"remote_user_tx_bytes": s.RemoteUserTxBytes.Val,
|
||||
"remote_user_rx_packets": s.RemoteUserRxPackets.Val,
|
||||
"remote_user_tx_packets": s.RemoteUserTxPackets.Val,
|
||||
"num_new_alarms": u.NumNewAlarms.Val,
|
||||
"nameservers": len(s.Nameservers),
|
||||
"gateways": len(s.Gateways),
|
||||
"num_user": h.NumUser.Val,
|
||||
"num_guest": h.NumGuest.Val,
|
||||
"num_iot": h.NumIot.Val,
|
||||
"tx_bytes-r": h.TxBytesR.Val,
|
||||
"rx_bytes-r": h.RxBytesR.Val,
|
||||
"num_ap": h.NumAp.Val,
|
||||
"num_adopted": h.NumAdopted.Val,
|
||||
"num_disabled": h.NumDisabled.Val,
|
||||
"num_disconnected": h.NumDisconnected.Val,
|
||||
"num_pending": h.NumPending.Val,
|
||||
"num_gw": h.NumGw.Val,
|
||||
"wan_ip": h.WanIP,
|
||||
"num_sta": h.NumSta.Val,
|
||||
"gw_cpu": h.GwSystemStats.CPU.Val,
|
||||
"gw_mem": h.GwSystemStats.Mem.Val,
|
||||
"gw_uptime": h.GwSystemStats.Uptime.Val,
|
||||
"latency": h.Latency.Val,
|
||||
"uptime": h.Uptime.Val,
|
||||
"drops": h.Drops.Val,
|
||||
"xput_up": h.XputUp.Val,
|
||||
"xput_down": h.XputDown.Val,
|
||||
"speedtest_ping": h.SpeedtestPing.Val,
|
||||
"speedtest_lastrun": h.SpeedtestLastrun.Val,
|
||||
"num_sw": h.NumSw.Val,
|
||||
"remote_user_num_active": h.RemoteUserNumActive.Val,
|
||||
"remote_user_num_inactive": h.RemoteUserNumInactive.Val,
|
||||
"remote_user_rx_bytes": h.RemoteUserRxBytes.Val,
|
||||
"remote_user_tx_bytes": h.RemoteUserTxBytes.Val,
|
||||
"remote_user_rx_packets": h.RemoteUserRxPackets.Val,
|
||||
"remote_user_tx_packets": h.RemoteUserTxPackets.Val,
|
||||
"num_new_alarms": s.NumNewAlarms.Val,
|
||||
}
|
||||
pt, err := influx.NewPoint("subsystems", tags, fields, time.Now())
|
||||
if err != nil {
|
||||
return points, err
|
||||
}
|
||||
points = append(points, pt)
|
||||
r.send(&metric{Table: "subsystems", Tags: tags, Fields: fields})
|
||||
}
|
||||
return points, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,214 +1,176 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// UAPPoints generates Wireless-Access-Point datapoints for InfluxDB.
|
||||
// batchUAP generates Wireless-Access-Point datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func UAPPoints(u *unifi.UAP, now time.Time) ([]*influx.Point, error) {
|
||||
if u.Stat.Ap == nil {
|
||||
u.Stat.Ap = &unifi.Ap{}
|
||||
func (u *InfluxUnifi) batchUAP(r report, s *unifi.UAP) {
|
||||
if s.Stat.Ap == nil {
|
||||
s.Stat.Ap = &unifi.Ap{}
|
||||
}
|
||||
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,
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
"name": s.Name,
|
||||
"version": s.Version,
|
||||
"model": s.Model,
|
||||
"serial": s.Serial,
|
||||
"type": s.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": 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
|
||||
}
|
||||
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
|
||||
fields := Combine(u.processUAPstats(s.Stat.Ap), u.batchSysStats(s.SysStats, s.SystemStats))
|
||||
fields["ip"] = s.IP
|
||||
fields["bytes"] = s.Bytes.Val
|
||||
fields["last_seen"] = s.LastSeen.Val
|
||||
fields["rx_bytes"] = s.RxBytes.Val
|
||||
fields["tx_bytes"] = s.TxBytes.Val
|
||||
fields["uptime"] = s.Uptime.Val
|
||||
fields["state"] = s.State
|
||||
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)
|
||||
}
|
||||
|
||||
// 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{}
|
||||
func (u *InfluxUnifi) processUAPstats(ap *unifi.Ap) map[string]interface{} {
|
||||
// Accumulative Statistics.
|
||||
return map[string]interface{}{
|
||||
"stat_user-rx_packets": ap.UserRxPackets.Val,
|
||||
"stat_guest-rx_packets": ap.GuestRxPackets.Val,
|
||||
"stat_rx_packets": ap.RxPackets.Val,
|
||||
"stat_user-rx_bytes": ap.UserRxBytes.Val,
|
||||
"stat_guest-rx_bytes": ap.GuestRxBytes.Val,
|
||||
"stat_rx_bytes": ap.RxBytes.Val,
|
||||
"stat_user-rx_errors": ap.UserRxErrors.Val,
|
||||
"stat_guest-rx_errors": ap.GuestRxErrors.Val,
|
||||
"stat_rx_errors": ap.RxErrors.Val,
|
||||
"stat_user-rx_dropped": ap.UserRxDropped.Val,
|
||||
"stat_guest-rx_dropped": ap.GuestRxDropped.Val,
|
||||
"stat_rx_dropped": ap.RxDropped.Val,
|
||||
"stat_user-rx_crypts": ap.UserRxCrypts.Val,
|
||||
"stat_guest-rx_crypts": ap.GuestRxCrypts.Val,
|
||||
"stat_rx_crypts": ap.RxCrypts.Val,
|
||||
"stat_user-rx_frags": ap.UserRxFrags.Val,
|
||||
"stat_guest-rx_frags": ap.GuestRxFrags.Val,
|
||||
"stat_rx_frags": ap.RxFrags.Val,
|
||||
"stat_user-tx_packets": ap.UserTxPackets.Val,
|
||||
"stat_guest-tx_packets": ap.GuestTxPackets.Val,
|
||||
"stat_tx_packets": ap.TxPackets.Val,
|
||||
"stat_user-tx_bytes": ap.UserTxBytes.Val,
|
||||
"stat_guest-tx_bytes": ap.GuestTxBytes.Val,
|
||||
"stat_tx_bytes": ap.TxBytes.Val,
|
||||
"stat_user-tx_errors": ap.UserTxErrors.Val,
|
||||
"stat_guest-tx_errors": ap.GuestTxErrors.Val,
|
||||
"stat_tx_errors": ap.TxErrors.Val,
|
||||
"stat_user-tx_dropped": ap.UserTxDropped.Val,
|
||||
"stat_guest-tx_dropped": ap.GuestTxDropped.Val,
|
||||
"stat_tx_dropped": ap.TxDropped.Val,
|
||||
"stat_user-tx_retries": ap.UserTxRetries.Val,
|
||||
"stat_guest-tx_retries": ap.GuestTxRetries.Val,
|
||||
}
|
||||
}
|
||||
|
||||
// Loop each virtual AP (ESSID) and extract data for it
|
||||
// from radio_tables and radio_table_stats.
|
||||
// processVAPTable creates points for Wifi Radios. This works with several types of UAP-capable devices.
|
||||
func (u *InfluxUnifi) processVAPTable(r report, t map[string]string, vt unifi.VapTable) {
|
||||
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
|
||||
tags["name"] = s.Name
|
||||
tags["radio_name"] = s.RadioName
|
||||
tags["wlanconf_id"] = s.WlanconfID
|
||||
tags["essid"] = s.Essid
|
||||
tags["site_id"] = s.SiteID
|
||||
tags["usage"] = s.Usage
|
||||
tags["state"] = s.State
|
||||
tags["is_guest"] = s.IsGuest.Txt
|
||||
tags["is_wep"] = s.IsWep.Txt
|
||||
|
||||
fields["ccq"] = s.Ccq
|
||||
fields["extchannel"] = s.Extchannel
|
||||
fields["mac_filter_rejections"] = s.MacFilterRejections
|
||||
fields["num_satisfaction_sta"] = s.NumSatisfactionSta.Val
|
||||
fields["avg_client_signal"] = s.AvgClientSignal.Val
|
||||
fields["satisfaction"] = s.Satisfaction.Val
|
||||
fields["satisfaction_now"] = s.SatisfactionNow.Val
|
||||
fields["rx_bytes"] = s.RxBytes.Val
|
||||
fields["rx_crypts"] = s.RxCrypts.Val
|
||||
fields["rx_dropped"] = s.RxDropped.Val
|
||||
fields["rx_errors"] = s.RxErrors.Val
|
||||
fields["rx_frags"] = s.RxFrags.Val
|
||||
fields["rx_nwids"] = s.RxNwids.Val
|
||||
fields["rx_packets"] = s.RxPackets.Val
|
||||
fields["tx_bytes"] = s.TxBytes.Val
|
||||
fields["tx_dropped"] = s.TxDropped.Val
|
||||
fields["tx_errors"] = s.TxErrors.Val
|
||||
fields["tx_packets"] = s.TxPackets.Val
|
||||
fields["tx_power"] = s.TxPower.Val
|
||||
fields["tx_retries"] = s.TxRetries.Val
|
||||
fields["tx_combined_retries"] = s.TxCombinedRetries.Val
|
||||
fields["tx_data_mpdu_bytes"] = s.TxDataMpduBytes.Val
|
||||
fields["tx_rts_retries"] = s.TxRtsRetries.Val
|
||||
fields["tx_success"] = s.TxSuccess.Val
|
||||
fields["tx_total"] = s.TxTotal.Val
|
||||
fields["tx_tcp_goodbytes"] = s.TxTCPStats.Goodbytes.Val
|
||||
fields["tx_tcp_lat_avg"] = s.TxTCPStats.LatAvg.Val
|
||||
fields["tx_tcp_lat_max"] = s.TxTCPStats.LatMax.Val
|
||||
fields["tx_tcp_lat_min"] = s.TxTCPStats.LatMin.Val
|
||||
fields["rx_tcp_goodbytes"] = s.RxTCPStats.Goodbytes.Val
|
||||
fields["rx_tcp_lat_avg"] = s.RxTCPStats.LatAvg.Val
|
||||
fields["rx_tcp_lat_max"] = s.RxTCPStats.LatMax.Val
|
||||
fields["rx_tcp_lat_min"] = s.RxTCPStats.LatMin.Val
|
||||
fields["wifi_tx_latency_mov_avg"] = s.WifiTxLatencyMov.Avg.Val
|
||||
fields["wifi_tx_latency_mov_max"] = s.WifiTxLatencyMov.Max.Val
|
||||
fields["wifi_tx_latency_mov_min"] = s.WifiTxLatencyMov.Min.Val
|
||||
fields["wifi_tx_latency_mov_total"] = s.WifiTxLatencyMov.Total.Val
|
||||
fields["wifi_tx_latency_mov_cuont"] = s.WifiTxLatencyMov.TotalCount.Val
|
||||
|
||||
for _, p := range rt {
|
||||
if p.Name != s.RadioName {
|
||||
continue
|
||||
}
|
||||
tags["wlangroup_id"] = p.WlangroupID
|
||||
tags["channel"] = p.Channel.Txt
|
||||
tags["radio"] = p.Radio
|
||||
fields["current_antenna_gain"] = p.CurrentAntennaGain.Val
|
||||
fields["ht"] = p.Ht.Txt
|
||||
fields["max_txpower"] = p.MaxTxpower.Val
|
||||
fields["min_rssi_enabled"] = p.MinRssiEnabled.Val
|
||||
fields["min_txpower"] = p.MinTxpower.Val
|
||||
fields["nss"] = p.Nss.Val
|
||||
fields["radio_caps"] = p.RadioCaps.Val
|
||||
fields["tx_power"] = p.TxPower.Val
|
||||
tags := map[string]string{
|
||||
"device_name": t["name"],
|
||||
"site_name": t["site_name"],
|
||||
"ap_mac": s.ApMac,
|
||||
"bssid": s.Bssid,
|
||||
"id": s.ID,
|
||||
"name": s.Name,
|
||||
"radio_name": s.RadioName,
|
||||
"radio": s.Radio,
|
||||
"essid": s.Essid,
|
||||
"site_id": s.SiteID,
|
||||
"usage": s.Usage,
|
||||
"state": s.State,
|
||||
"is_guest": s.IsGuest.Txt,
|
||||
}
|
||||
|
||||
for _, p := range rts {
|
||||
if p.Name != s.RadioName {
|
||||
continue
|
||||
}
|
||||
fields["ast_be_xmit"] = p.AstBeXmit.Val
|
||||
fields["channel"] = p.Channel.Val
|
||||
fields["cu_self_rx"] = p.CuSelfRx.Val
|
||||
fields["cu_self_tx"] = p.CuSelfTx.Val
|
||||
fields["cu_total"] = p.CuTotal.Val
|
||||
fields["extchannel"] = p.Extchannel.Val
|
||||
fields["gain"] = p.Gain.Val
|
||||
fields["guest-num_sta"] = p.GuestNumSta.Val
|
||||
fields["num_sta"] = p.NumSta.Val
|
||||
fields["radio"] = p.Radio
|
||||
fields["tx_packets"] = p.TxPackets.Val
|
||||
fields["tx_power"] = p.TxPower.Val
|
||||
fields["tx_retries"] = p.TxRetries.Val
|
||||
fields["user-num_sta"] = p.UserNumSta.Val
|
||||
fields := map[string]interface{}{
|
||||
"ccq": s.Ccq,
|
||||
"mac_filter_rejections": s.MacFilterRejections,
|
||||
"num_satisfaction_sta": s.NumSatisfactionSta.Val,
|
||||
"avg_client_signal": s.AvgClientSignal.Val,
|
||||
"satisfaction": s.Satisfaction.Val,
|
||||
"satisfaction_now": s.SatisfactionNow.Val,
|
||||
"num_sta": s.NumSta,
|
||||
"channel": s.Channel,
|
||||
"rx_bytes": s.RxBytes.Val,
|
||||
"rx_crypts": s.RxCrypts.Val,
|
||||
"rx_dropped": s.RxDropped.Val,
|
||||
"rx_errors": s.RxErrors.Val,
|
||||
"rx_frags": s.RxFrags.Val,
|
||||
"rx_nwids": s.RxNwids.Val,
|
||||
"rx_packets": s.RxPackets.Val,
|
||||
"tx_bytes": s.TxBytes.Val,
|
||||
"tx_dropped": s.TxDropped.Val,
|
||||
"tx_errors": s.TxErrors.Val,
|
||||
"tx_packets": s.TxPackets.Val,
|
||||
"tx_power": s.TxPower.Val,
|
||||
"tx_retries": s.TxRetries.Val,
|
||||
"tx_combined_retries": s.TxCombinedRetries.Val,
|
||||
"tx_data_mpdu_bytes": s.TxDataMpduBytes.Val,
|
||||
"tx_rts_retries": s.TxRtsRetries.Val,
|
||||
"tx_success": s.TxSuccess.Val,
|
||||
"tx_total": s.TxTotal.Val,
|
||||
"tx_tcp_goodbytes": s.TxTCPStats.Goodbytes.Val,
|
||||
"tx_tcp_lat_avg": s.TxTCPStats.LatAvg.Val,
|
||||
"tx_tcp_lat_max": s.TxTCPStats.LatMax.Val,
|
||||
"tx_tcp_lat_min": s.TxTCPStats.LatMin.Val,
|
||||
"rx_tcp_goodbytes": s.RxTCPStats.Goodbytes.Val,
|
||||
"rx_tcp_lat_avg": s.RxTCPStats.LatAvg.Val,
|
||||
"rx_tcp_lat_max": s.RxTCPStats.LatMax.Val,
|
||||
"rx_tcp_lat_min": s.RxTCPStats.LatMin.Val,
|
||||
"wifi_tx_latency_mov_avg": s.WifiTxLatencyMov.Avg.Val,
|
||||
"wifi_tx_latency_mov_max": s.WifiTxLatencyMov.Max.Val,
|
||||
"wifi_tx_latency_mov_min": s.WifiTxLatencyMov.Min.Val,
|
||||
"wifi_tx_latency_mov_total": s.WifiTxLatencyMov.Total.Val,
|
||||
"wifi_tx_latency_mov_cuont": s.WifiTxLatencyMov.TotalCount.Val,
|
||||
}
|
||||
|
||||
pt, err := influx.NewPoint("uap_vaps", tags, fields, ts)
|
||||
if err != nil {
|
||||
return points, err
|
||||
}
|
||||
points = append(points, pt)
|
||||
r.send(&metric{Table: "uap_vaps", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
||||
func (u *InfluxUnifi) processRadTable(r report, t map[string]string, rt unifi.RadioTable, rts unifi.RadioTableStats) {
|
||||
for _, p := range rt {
|
||||
tags := map[string]string{
|
||||
"device_name": t["name"],
|
||||
"site_name": t["site_name"],
|
||||
"channel": p.Channel.Txt,
|
||||
"radio": p.Radio,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"current_antenna_gain": p.CurrentAntennaGain.Val,
|
||||
"ht": p.Ht.Txt,
|
||||
"max_txpower": p.MaxTxpower.Val,
|
||||
"min_txpower": p.MinTxpower.Val,
|
||||
"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
|
||||
fields["channel"] = t.Channel.Val
|
||||
fields["cu_self_rx"] = t.CuSelfRx.Val
|
||||
fields["cu_self_tx"] = t.CuSelfTx.Val
|
||||
fields["cu_total"] = t.CuTotal.Val
|
||||
fields["extchannel"] = t.Extchannel.Val
|
||||
fields["gain"] = t.Gain.Val
|
||||
fields["guest-num_sta"] = t.GuestNumSta.Val
|
||||
fields["num_sta"] = t.NumSta.Val
|
||||
fields["radio"] = t.Radio
|
||||
fields["tx_packets"] = t.TxPackets.Val
|
||||
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})
|
||||
}
|
||||
return points, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,416 +1,141 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// UDMPoints generates Unifi Gateway datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func UDMPoints(u *unifi.UDM, now time.Time) ([]*influx.Point, error) {
|
||||
if u.Stat.Sw == nil {
|
||||
u.Stat.Sw = &unifi.Sw{}
|
||||
// Combines 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]
|
||||
}
|
||||
}
|
||||
if u.Stat.Gw == nil {
|
||||
u.Stat.Gw = &unifi.Gw{}
|
||||
return out
|
||||
}
|
||||
|
||||
// batchSysStats is used by all device types.
|
||||
func (u *InfluxUnifi) batchSysStats(s unifi.SysStats, ss unifi.SystemStats) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"loadavg_1": s.Loadavg1.Val,
|
||||
"loadavg_5": s.Loadavg5.Val,
|
||||
"loadavg_15": s.Loadavg15.Val,
|
||||
"mem_used": s.MemUsed.Val,
|
||||
"mem_buffer": s.MemBuffer.Val,
|
||||
"mem_total": s.MemTotal.Val,
|
||||
"cpu": ss.CPU.Val,
|
||||
"mem": ss.Mem.Val,
|
||||
"system_uptime": ss.Uptime.Val,
|
||||
}
|
||||
}
|
||||
|
||||
// batchUDM generates Unifi Gateway datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func (u *InfluxUnifi) batchUDM(r report, s *unifi.UDM) {
|
||||
if s.Stat.Sw == nil {
|
||||
s.Stat.Sw = &unifi.Sw{}
|
||||
}
|
||||
if s.Stat.Gw == nil {
|
||||
s.Stat.Gw = &unifi.Gw{}
|
||||
}
|
||||
tags := map[string]string{
|
||||
"id": u.ID,
|
||||
"mac": u.Mac,
|
||||
"device_oid": u.Stat.Gw.Oid,
|
||||
"site_id": u.SiteID,
|
||||
"site_name": u.SiteName,
|
||||
"adopted": u.Adopted.Txt,
|
||||
"name": u.Name,
|
||||
"cfgversion": u.Cfgversion,
|
||||
"config_network_ip": u.ConfigNetwork.IP,
|
||||
"config_network_type": u.ConfigNetwork.Type,
|
||||
"connect_request_ip": u.ConnectRequestIP,
|
||||
"connect_request_port": u.ConnectRequestPort,
|
||||
"device_id": u.DeviceID,
|
||||
"guest_token": u.GuestToken,
|
||||
"inform_ip": u.InformIP,
|
||||
"known_cfgversion": u.KnownCfgversion,
|
||||
"model": u.Model,
|
||||
"serial": u.Serial,
|
||||
"type": u.Type,
|
||||
"usg_caps": u.UsgCaps.Txt,
|
||||
"speedtest-status-saved": u.SpeedtestStatusSaved.Txt,
|
||||
"wan1_up": u.Wan1.Up.Txt,
|
||||
"wan2_up": u.Wan2.Up.Txt,
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
"name": s.Name,
|
||||
"version": s.Version,
|
||||
"model": s.Model,
|
||||
"serial": s.Serial,
|
||||
"type": s.Type,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"ip": u.IP,
|
||||
"bytes": u.Bytes.Val,
|
||||
"last_seen": u.LastSeen.Val,
|
||||
"license_state": u.LicenseState,
|
||||
"fw_caps": u.FwCaps.Val,
|
||||
"guest-num_sta": u.GuestNumSta.Val,
|
||||
"rx_bytes": u.RxBytes.Val,
|
||||
"tx_bytes": u.TxBytes.Val,
|
||||
"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,
|
||||
"num_mobile": u.NumMobile.Val,
|
||||
"speedtest-status_latency": u.SpeedtestStatus.Latency.Val,
|
||||
"speedtest-status_rundate": u.SpeedtestStatus.Rundate.Val,
|
||||
"speedtest-status_runtime": u.SpeedtestStatus.Runtime.Val,
|
||||
"speedtest-status_download": u.SpeedtestStatus.StatusDownload.Val,
|
||||
"speedtest-status_ping": u.SpeedtestStatus.StatusPing.Val,
|
||||
"speedtest-status_summary": u.SpeedtestStatus.StatusSummary.Val,
|
||||
"speedtest-status_upload": u.SpeedtestStatus.StatusUpload.Val,
|
||||
"speedtest-status_xput_download": u.SpeedtestStatus.XputDownload.Val,
|
||||
"speedtest-status_xput_upload": u.SpeedtestStatus.XputUpload.Val,
|
||||
"config_network_wan_type": u.ConfigNetwork.Type,
|
||||
"wan1_bytes-r": u.Wan1.BytesR.Val,
|
||||
"wan1_enable": u.Wan1.Enable.Val,
|
||||
"wan1_full_duplex": u.Wan1.FullDuplex.Val,
|
||||
"wan1_gateway": u.Wan1.Gateway,
|
||||
"wan1_ifname": u.Wan1.Ifname,
|
||||
"wan1_ip": u.Wan1.IP,
|
||||
"wan1_mac": u.Wan1.Mac,
|
||||
"wan1_max_speed": u.Wan1.MaxSpeed.Val,
|
||||
"wan1_name": u.Wan1.Name,
|
||||
"wan1_netmask": u.Wan1.Netmask,
|
||||
"wan1_rx_bytes": u.Wan1.RxBytes.Val,
|
||||
"wan1_rx_bytes-r": u.Wan1.RxBytesR.Val,
|
||||
"wan1_rx_dropped": u.Wan1.RxDropped.Val,
|
||||
"wan1_rx_errors": u.Wan1.RxErrors.Val,
|
||||
"wan1_rx_multicast": u.Wan1.RxMulticast.Val,
|
||||
"wan1_rx_packets": u.Wan1.RxPackets.Val,
|
||||
"wan1_type": u.Wan1.Type,
|
||||
"wan1_speed": u.Wan1.Speed.Val,
|
||||
"wan1_up": u.Wan1.Up.Val,
|
||||
"wan1_tx_bytes": u.Wan1.TxBytes.Val,
|
||||
"wan1_tx_bytes-r": u.Wan1.TxBytesR.Val,
|
||||
"wan1_tx_dropped": u.Wan1.TxDropped.Val,
|
||||
"wan1_tx_errors": u.Wan1.TxErrors.Val,
|
||||
"wan1_tx_packets": u.Wan1.TxPackets.Val,
|
||||
"wan2_bytes-r": u.Wan2.BytesR.Val,
|
||||
"wan2_enable": u.Wan2.Enable.Val,
|
||||
"wan2_full_duplex": u.Wan2.FullDuplex.Val,
|
||||
"wan2_gateway": u.Wan2.Gateway,
|
||||
"wan2_ifname": u.Wan2.Ifname,
|
||||
"wan2_ip": u.Wan2.IP,
|
||||
"wan2_mac": u.Wan2.Mac,
|
||||
"wan2_max_speed": u.Wan2.MaxSpeed.Val,
|
||||
"wan2_name": u.Wan2.Name,
|
||||
"wan2_netmask": u.Wan2.Netmask,
|
||||
"wan2_rx_bytes": u.Wan2.RxBytes.Val,
|
||||
"wan2_rx_bytes-r": u.Wan2.RxBytesR.Val,
|
||||
"wan2_rx_dropped": u.Wan2.RxDropped.Val,
|
||||
"wan2_rx_errors": u.Wan2.RxErrors.Val,
|
||||
"wan2_rx_multicast": u.Wan2.RxMulticast.Val,
|
||||
"wan2_rx_packets": u.Wan2.RxPackets.Val,
|
||||
"wan2_type": u.Wan2.Type,
|
||||
"wan2_speed": u.Wan2.Speed.Val,
|
||||
"wan2_up": u.Wan2.Up.Val,
|
||||
"wan2_tx_bytes": u.Wan2.TxBytes.Val,
|
||||
"wan2_tx_bytes-r": u.Wan2.TxBytesR.Val,
|
||||
"wan2_tx_dropped": u.Wan2.TxDropped.Val,
|
||||
"wan2_tx_errors": u.Wan2.TxErrors.Val,
|
||||
"wan2_tx_packets": u.Wan2.TxPackets.Val,
|
||||
"loadavg_1": u.SysStats.Loadavg1.Val,
|
||||
"loadavg_5": u.SysStats.Loadavg5.Val,
|
||||
"loadavg_15": u.SysStats.Loadavg15.Val,
|
||||
"mem_used": u.SysStats.MemUsed.Val,
|
||||
"mem_buffer": u.SysStats.MemBuffer.Val,
|
||||
"mem_total": u.SysStats.MemTotal.Val,
|
||||
"cpu": u.SystemStats.CPU.Val,
|
||||
"mem": u.SystemStats.Mem.Val,
|
||||
"system_uptime": u.SystemStats.Uptime.Val,
|
||||
"gw": u.Stat.Gw,
|
||||
"lan-rx_bytes": u.Stat.LanRxBytes.Val,
|
||||
"lan-rx_packets": u.Stat.LanRxPackets.Val,
|
||||
"lan-tx_bytes": u.Stat.LanTxBytes.Val,
|
||||
"lan-tx_packets": u.Stat.LanTxPackets.Val,
|
||||
"wan-rx_bytes": u.Stat.WanRxBytes.Val,
|
||||
"wan-rx_dropped": u.Stat.WanRxDropped.Val,
|
||||
"wan-rx_packets": u.Stat.WanRxPackets.Val,
|
||||
"wan-tx_bytes": u.Stat.WanTxBytes.Val,
|
||||
"wan-tx_packets": u.Stat.WanTxPackets.Val,
|
||||
"uplink_name": u.Uplink.Name,
|
||||
"uplink_latency": u.Uplink.Latency.Val,
|
||||
"uplink_speed": u.Uplink.Speed.Val,
|
||||
"uplink_num_ports": u.Uplink.NumPort.Val,
|
||||
"uplink_max_speed": u.Uplink.MaxSpeed.Val,
|
||||
}
|
||||
pt, err := influx.NewPoint("usg", tags, fields, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
points := []*influx.Point{pt}
|
||||
fields := Combine(map[string]interface{}{
|
||||
"ip": s.IP,
|
||||
"bytes": s.Bytes.Val,
|
||||
"last_seen": s.LastSeen.Val,
|
||||
"license_state": s.LicenseState,
|
||||
"guest-num_sta": s.GuestNumSta.Val,
|
||||
"rx_bytes": s.RxBytes.Val,
|
||||
"tx_bytes": s.TxBytes.Val,
|
||||
"uptime": s.Uptime.Val,
|
||||
"state": s.State.Val,
|
||||
"user-num_sta": s.UserNumSta.Val,
|
||||
"version": s.Version,
|
||||
"num_desktop": s.NumDesktop.Val,
|
||||
"num_handheld": s.NumHandheld.Val,
|
||||
"num_mobile": s.NumMobile.Val,
|
||||
"speedtest-status_latency": s.SpeedtestStatus.Latency.Val,
|
||||
"speedtest-status_runtime": s.SpeedtestStatus.Runtime.Val,
|
||||
"speedtest-status_ping": s.SpeedtestStatus.StatusPing.Val,
|
||||
"speedtest-status_xput_download": s.SpeedtestStatus.XputDownload.Val,
|
||||
"speedtest-status_xput_upload": s.SpeedtestStatus.XputUpload.Val,
|
||||
"lan-rx_bytes": s.Stat.Gw.LanRxBytes.Val,
|
||||
"lan-rx_packets": s.Stat.Gw.LanRxPackets.Val,
|
||||
"lan-tx_bytes": s.Stat.Gw.LanTxBytes.Val,
|
||||
"lan-tx_packets": s.Stat.Gw.LanTxPackets.Val,
|
||||
}, u.batchSysStats(s.SysStats, s.SystemStats))
|
||||
r.send(&metric{Table: "usg", Tags: tags, Fields: fields})
|
||||
u.batchNetTable(r, tags, s.NetworkTable)
|
||||
u.batchUSGwans(r, tags, s.Wan1, s.Wan2)
|
||||
|
||||
tags = map[string]string{
|
||||
"id": u.ID,
|
||||
"mac": u.Mac,
|
||||
"device_oid": u.Stat.Sw.Oid,
|
||||
"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,
|
||||
"device_id": u.DeviceID,
|
||||
"inform_ip": u.InformIP,
|
||||
"known_cfgversion": u.KnownCfgversion,
|
||||
"locating": u.Locating.Txt,
|
||||
"model": u.Model,
|
||||
"serial": u.Serial,
|
||||
"type": u.Type,
|
||||
"dot1x_portctrl_enabled": u.Dot1XPortctrlEnabled.Txt,
|
||||
"flowctrl_enabled": u.FlowctrlEnabled.Txt,
|
||||
"has_fan": u.HasFan.Txt,
|
||||
"has_temperature": u.HasTemperature.Txt,
|
||||
"jumboframe_enabled": u.JumboframeEnabled.Txt,
|
||||
"stp_version": u.StpVersion,
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
"name": s.Name,
|
||||
"version": s.Version,
|
||||
"model": s.Model,
|
||||
"serial": s.Serial,
|
||||
"type": s.Type,
|
||||
}
|
||||
fields = map[string]interface{}{
|
||||
"fw_caps": u.FwCaps.Val,
|
||||
"guest-num_sta": u.GuestLanNumSta.Val,
|
||||
"ip": u.IP,
|
||||
"bytes": u.Bytes.Val,
|
||||
"fan_level": float64(0),
|
||||
"general_temperature": float64(0),
|
||||
"last_seen": u.LastSeen.Val,
|
||||
"license_state": u.LicenseState,
|
||||
"overheating": u.Overheating.Val,
|
||||
"rx_bytes": u.RxBytes.Val,
|
||||
"tx_bytes": u.TxBytes.Val,
|
||||
"uptime": u.Uptime.Val,
|
||||
"state": u.State.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,
|
||||
"loadavg_15": u.SysStats.Loadavg15.Val,
|
||||
"mem_buffer": u.SysStats.MemBuffer.Val,
|
||||
"mem_used": u.SysStats.MemUsed.Val,
|
||||
"mem_total": u.SysStats.MemTotal.Val,
|
||||
"cpu": u.SystemStats.CPU.Val,
|
||||
"mem": u.SystemStats.Mem.Val,
|
||||
"system_uptime": u.SystemStats.Uptime.Val,
|
||||
"stp_priority": u.StpPriority.Val,
|
||||
"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,
|
||||
"guest-num_sta": s.GuestNumSta.Val,
|
||||
"ip": s.IP,
|
||||
"bytes": s.Bytes.Val,
|
||||
"last_seen": s.LastSeen.Val,
|
||||
"rx_bytes": s.RxBytes.Val,
|
||||
"tx_bytes": s.TxBytes.Val,
|
||||
"uptime": s.Uptime.Val,
|
||||
"state": s.State.Val,
|
||||
"stat_bytes": s.Stat.Sw.Bytes.Val,
|
||||
"stat_rx_bytes": s.Stat.Sw.RxBytes.Val,
|
||||
"stat_rx_crypts": s.Stat.Sw.RxCrypts.Val,
|
||||
"stat_rx_dropped": s.Stat.Sw.RxDropped.Val,
|
||||
"stat_rx_errors": s.Stat.Sw.RxErrors.Val,
|
||||
"stat_rx_frags": s.Stat.Sw.RxFrags.Val,
|
||||
"stat_rx_packets": s.Stat.Sw.TxPackets.Val,
|
||||
"stat_tx_bytes": s.Stat.Sw.TxBytes.Val,
|
||||
"stat_tx_dropped": s.Stat.Sw.TxDropped.Val,
|
||||
"stat_tx_errors": s.Stat.Sw.TxErrors.Val,
|
||||
"stat_tx_packets": s.Stat.Sw.TxPackets.Val,
|
||||
"stat_tx_retries": s.Stat.Sw.TxRetries.Val,
|
||||
}
|
||||
pt, err = influx.NewPoint("usw", tags, fields, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
points = append(points, pt)
|
||||
r.send(&metric{Table: "usw", Tags: tags, Fields: fields})
|
||||
u.batchPortTable(r, tags, s.PortTable)
|
||||
|
||||
for _, p := range u.NetworkTable {
|
||||
tags := map[string]string{
|
||||
"device_name": u.Name,
|
||||
"device_id": u.ID,
|
||||
"device_mac": u.Mac,
|
||||
"site_name": u.SiteName,
|
||||
"up": p.Up.Txt,
|
||||
"dhcpd_dns_enabled": p.DhcpdDNSEnabled.Txt,
|
||||
"dhcpd_enabled": p.DhcpdEnabled.Txt,
|
||||
"dhcpd_time_offset_enabled": p.DhcpdTimeOffsetEnabled.Txt,
|
||||
"dhcp_relay_enabledy": p.DhcpRelayEnabled.Txt,
|
||||
"dhcpd_gateway_enabled": p.DhcpdGatewayEnabled.Txt,
|
||||
"enabled": p.Enabled.Txt,
|
||||
"vlan_enabled": p.VlanEnabled.Txt,
|
||||
"attr_no_delete": p.AttrNoDelete.Txt,
|
||||
"is_guest": p.IsGuest.Txt,
|
||||
"is_nat": p.IsNat.Txt,
|
||||
"networkgroup": p.Networkgroup,
|
||||
"site_id": p.SiteID,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"domain_name": p.DomainName,
|
||||
"dhcpd_start": p.DhcpdStart,
|
||||
"dhcpd_stop": p.DhcpdStop,
|
||||
"ip": p.IP,
|
||||
"ip_subnet": p.IPSubnet,
|
||||
"mac": p.Mac,
|
||||
"name": p.Name,
|
||||
"num_sta": p.NumSta.Val,
|
||||
"purpose": p.Purpose,
|
||||
"rx_bytes": p.RxBytes.Val,
|
||||
"rx_packets": p.RxPackets.Val,
|
||||
"tx_bytes": p.TxBytes.Val,
|
||||
"tx_packets": p.TxPackets.Val,
|
||||
"ipv6_interface_type": p.Ipv6InterfaceType,
|
||||
"attr_hidden_id": p.AttrHiddenID,
|
||||
}
|
||||
pt, err = influx.NewPoint("usg_networks", tags, fields, now)
|
||||
if err != nil {
|
||||
return points, err
|
||||
}
|
||||
points = append(points, pt)
|
||||
}
|
||||
|
||||
for _, p := range u.PortTable {
|
||||
tags := map[string]string{
|
||||
"site_id": u.SiteID,
|
||||
"site_name": u.SiteName,
|
||||
"device_name": u.Name,
|
||||
"name": p.Name,
|
||||
"enable": p.Enable.Txt,
|
||||
"is_uplink": p.IsUplink.Txt,
|
||||
"up": p.Up.Txt,
|
||||
"portconf_id": p.PortconfID,
|
||||
"dot1x_mode": p.Dot1XMode,
|
||||
"dot1x_status": p.Dot1XStatus,
|
||||
"stp_state": p.StpState,
|
||||
"sfp_found": p.SfpFound.Txt,
|
||||
"op_mode": p.OpMode,
|
||||
"poe_mode": p.PoeMode,
|
||||
"port_poe": p.PortPoe.Txt,
|
||||
"port_idx": p.PortIdx.Txt,
|
||||
"port_id": u.Name + " Port " + p.PortIdx.Txt,
|
||||
"poe_enable": p.PoeEnable.Txt,
|
||||
"flowctrl_rx": p.FlowctrlRx.Txt,
|
||||
"flowctrl_tx": p.FlowctrlTx.Txt,
|
||||
"autoneg": p.Autoneg.Txt,
|
||||
"full_duplex": p.FullDuplex.Txt,
|
||||
"jumbo": p.Jumbo.Txt,
|
||||
"masked": p.Masked.Txt,
|
||||
"poe_good": p.PoeGood.Txt,
|
||||
"media": p.Media,
|
||||
"poe_class": p.PoeClass,
|
||||
"poe_caps": p.PoeCaps.Txt,
|
||||
"aggregated_by": p.AggregatedBy.Txt,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"dbytes_r": p.BytesR.Val,
|
||||
"rx_broadcast": p.RxBroadcast.Val,
|
||||
"rx_bytes": p.RxBytes.Val,
|
||||
"rx_bytes-r": p.RxBytesR.Val,
|
||||
"rx_dropped": p.RxDropped.Val,
|
||||
"rx_errors": p.RxErrors.Val,
|
||||
"rx_multicast": p.RxMulticast.Val,
|
||||
"rx_packets": p.RxPackets.Val,
|
||||
"speed": p.Speed.Val,
|
||||
"stp_pathcost": p.StpPathcost.Val,
|
||||
"tx_broadcast": p.TxBroadcast.Val,
|
||||
"tx_bytes": p.TxBytes.Val,
|
||||
"tx_bytes-r": p.TxBytesR.Val,
|
||||
"tx_dropped": p.TxDropped.Val,
|
||||
"tx_errors": p.TxErrors.Val,
|
||||
"tx_multicast": p.TxMulticast.Val,
|
||||
"tx_packets": p.TxPackets.Val,
|
||||
"poe_current": p.PoeCurrent.Val,
|
||||
"poe_power": p.PoePower.Val,
|
||||
"poe_voltage": p.PoeVoltage.Val,
|
||||
"full_duplex": p.FullDuplex.Val,
|
||||
}
|
||||
pt, err = influx.NewPoint("usw_ports", tags, fields, now)
|
||||
if err != nil {
|
||||
return points, err
|
||||
}
|
||||
points = append(points, pt)
|
||||
}
|
||||
if u.Stat.Ap == nil {
|
||||
return points, nil
|
||||
if s.Stat.Ap == nil {
|
||||
return
|
||||
// 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,
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
"name": s.Name,
|
||||
"version": s.Version,
|
||||
"model": s.Model,
|
||||
"serial": s.Serial,
|
||||
"type": s.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
|
||||
fields = u.processUAPstats(s.Stat.Ap)
|
||||
fields["ip"] = s.IP
|
||||
fields["bytes"] = s.Bytes.Val
|
||||
fields["last_seen"] = s.LastSeen.Val
|
||||
fields["rx_bytes"] = s.RxBytes.Val
|
||||
fields["tx_bytes"] = s.TxBytes.Val
|
||||
fields["uptime"] = s.Uptime.Val
|
||||
fields["state"] = s.State
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,185 +1,140 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// USGPoints generates Unifi Gateway datapoints for InfluxDB.
|
||||
// batchUSG generates Unifi Gateway datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func USGPoints(u *unifi.USG, now time.Time) ([]*influx.Point, error) {
|
||||
if u.Stat.Gw == nil {
|
||||
u.Stat.Gw = &unifi.Gw{}
|
||||
func (u *InfluxUnifi) batchUSG(r report, s *unifi.USG) {
|
||||
if s.Stat.Gw == nil {
|
||||
s.Stat.Gw = &unifi.Gw{}
|
||||
}
|
||||
tags := map[string]string{
|
||||
"id": u.ID,
|
||||
"mac": u.Mac,
|
||||
"device_type": u.Stat.O,
|
||||
"device_oid": u.Stat.Oid,
|
||||
"site_id": u.SiteID,
|
||||
"site_name": u.SiteName,
|
||||
"adopted": u.Adopted.Txt,
|
||||
"name": u.Name,
|
||||
"cfgversion": u.Cfgversion,
|
||||
"config_network_ip": u.ConfigNetwork.IP,
|
||||
"config_network_type": u.ConfigNetwork.Type,
|
||||
"connect_request_ip": u.ConnectRequestIP,
|
||||
"connect_request_port": u.ConnectRequestPort,
|
||||
"device_id": u.DeviceID,
|
||||
"guest_token": u.GuestToken,
|
||||
"inform_ip": u.InformIP,
|
||||
"known_cfgversion": u.KnownCfgversion,
|
||||
"led_override": u.LedOverride,
|
||||
"locating": u.Locating.Txt,
|
||||
"model": u.Model,
|
||||
"outdoor_mode_override": u.OutdoorModeOverride,
|
||||
"serial": u.Serial,
|
||||
"type": u.Type,
|
||||
"usg_caps": u.UsgCaps.Txt,
|
||||
"speedtest-status-saved": u.SpeedtestStatusSaved.Txt,
|
||||
"wan1_up": u.Wan1.Up.Txt,
|
||||
"wan2_up": u.Wan2.Up.Txt,
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
"name": s.Name,
|
||||
"version": s.Version,
|
||||
"model": s.Model,
|
||||
"serial": s.Serial,
|
||||
"type": s.Type,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"ip": u.IP,
|
||||
"bytes": u.Bytes.Val,
|
||||
"last_seen": u.LastSeen.Val,
|
||||
"license_state": u.LicenseState,
|
||||
"fw_caps": u.FwCaps.Val,
|
||||
"guest-num_sta": u.GuestNumSta.Val,
|
||||
"rx_bytes": u.RxBytes.Val,
|
||||
"tx_bytes": u.TxBytes.Val,
|
||||
"uptime": u.Uptime.Val,
|
||||
"roll_upgrade": u.Rollupgrade.Val,
|
||||
"state": u.State.Val,
|
||||
"upgradable": u.Upgradable.Val,
|
||||
"user-num_sta": u.UserNumSta.Val,
|
||||
"version": u.Version,
|
||||
"num_desktop": u.NumDesktop.Val,
|
||||
"num_handheld": u.NumHandheld.Val,
|
||||
"num_mobile": u.NumMobile.Val,
|
||||
"speedtest-status_latency": u.SpeedtestStatus.Latency.Val,
|
||||
"speedtest-status_rundate": u.SpeedtestStatus.Rundate.Val,
|
||||
"speedtest-status_runtime": u.SpeedtestStatus.Runtime.Val,
|
||||
"speedtest-status_download": u.SpeedtestStatus.StatusDownload.Val,
|
||||
"speedtest-status_ping": u.SpeedtestStatus.StatusPing.Val,
|
||||
"speedtest-status_summary": u.SpeedtestStatus.StatusSummary.Val,
|
||||
"speedtest-status_upload": u.SpeedtestStatus.StatusUpload.Val,
|
||||
"speedtest-status_xput_download": u.SpeedtestStatus.XputDownload.Val,
|
||||
"speedtest-status_xput_upload": u.SpeedtestStatus.XputUpload.Val,
|
||||
"config_network_wan_type": u.ConfigNetwork.Type,
|
||||
"wan1_bytes-r": u.Wan1.BytesR.Val,
|
||||
"wan1_enable": u.Wan1.Enable.Val,
|
||||
"wan1_full_duplex": u.Wan1.FullDuplex.Val,
|
||||
"wan1_gateway": u.Wan1.Gateway,
|
||||
"wan1_ifname": u.Wan1.Ifname,
|
||||
"wan1_ip": u.Wan1.IP,
|
||||
"wan1_mac": u.Wan1.Mac,
|
||||
"wan1_max_speed": u.Wan1.MaxSpeed.Val,
|
||||
"wan1_name": u.Wan1.Name,
|
||||
"wan1_netmask": u.Wan1.Netmask,
|
||||
"wan1_rx_bytes": u.Wan1.RxBytes.Val,
|
||||
"wan1_rx_bytes-r": u.Wan1.RxBytesR.Val,
|
||||
"wan1_rx_dropped": u.Wan1.RxDropped.Val,
|
||||
"wan1_rx_errors": u.Wan1.RxErrors.Val,
|
||||
"wan1_rx_multicast": u.Wan1.RxMulticast.Val,
|
||||
"wan1_rx_packets": u.Wan1.RxPackets.Val,
|
||||
"wan1_type": u.Wan1.Type,
|
||||
"wan1_speed": u.Wan1.Speed.Val,
|
||||
"wan1_up": u.Wan1.Up.Val,
|
||||
"wan1_tx_bytes": u.Wan1.TxBytes.Val,
|
||||
"wan1_tx_bytes-r": u.Wan1.TxBytesR.Val,
|
||||
"wan1_tx_dropped": u.Wan1.TxDropped.Val,
|
||||
"wan1_tx_errors": u.Wan1.TxErrors.Val,
|
||||
"wan1_tx_packets": u.Wan1.TxPackets.Val,
|
||||
"wan2_bytes-r": u.Wan2.BytesR.Val,
|
||||
"wan2_enable": u.Wan2.Enable.Val,
|
||||
"wan2_full_duplex": u.Wan2.FullDuplex.Val,
|
||||
"wan2_gateway": u.Wan2.Gateway,
|
||||
"wan2_ifname": u.Wan2.Ifname,
|
||||
"wan2_ip": u.Wan2.IP,
|
||||
"wan2_mac": u.Wan2.Mac,
|
||||
"wan2_max_speed": u.Wan2.MaxSpeed.Val,
|
||||
"wan2_name": u.Wan2.Name,
|
||||
"wan2_netmask": u.Wan2.Netmask,
|
||||
"wan2_rx_bytes": u.Wan2.RxBytes.Val,
|
||||
"wan2_rx_bytes-r": u.Wan2.RxBytesR.Val,
|
||||
"wan2_rx_dropped": u.Wan2.RxDropped.Val,
|
||||
"wan2_rx_errors": u.Wan2.RxErrors.Val,
|
||||
"wan2_rx_multicast": u.Wan2.RxMulticast.Val,
|
||||
"wan2_rx_packets": u.Wan2.RxPackets.Val,
|
||||
"wan2_type": u.Wan2.Type,
|
||||
"wan2_speed": u.Wan2.Speed.Val,
|
||||
"wan2_up": u.Wan2.Up.Val,
|
||||
"wan2_tx_bytes": u.Wan2.TxBytes.Val,
|
||||
"wan2_tx_bytes-r": u.Wan2.TxBytesR.Val,
|
||||
"wan2_tx_dropped": u.Wan2.TxDropped.Val,
|
||||
"wan2_tx_errors": u.Wan2.TxErrors.Val,
|
||||
"wan2_tx_packets": u.Wan2.TxPackets.Val,
|
||||
"loadavg_1": u.SysStats.Loadavg1.Val,
|
||||
"loadavg_5": u.SysStats.Loadavg5.Val,
|
||||
"loadavg_15": u.SysStats.Loadavg15.Val,
|
||||
"mem_used": u.SysStats.MemUsed.Val,
|
||||
"mem_buffer": u.SysStats.MemBuffer.Val,
|
||||
"mem_total": u.SysStats.MemTotal.Val,
|
||||
"cpu": u.SystemStats.CPU.Val,
|
||||
"mem": u.SystemStats.Mem.Val,
|
||||
"system_uptime": u.SystemStats.Uptime.Val,
|
||||
"stat_duration": u.Stat.Duration.Val,
|
||||
"stat_datetime": u.Stat.Datetime,
|
||||
"gw": u.Stat.Gw,
|
||||
"lan-rx_bytes": u.Stat.LanRxBytes.Val,
|
||||
"lan-rx_packets": u.Stat.LanRxPackets.Val,
|
||||
"lan-tx_bytes": u.Stat.LanTxBytes.Val,
|
||||
"lan-tx_packets": u.Stat.LanTxPackets.Val,
|
||||
"wan-rx_bytes": u.Stat.WanRxBytes.Val,
|
||||
"wan-rx_dropped": u.Stat.WanRxDropped.Val,
|
||||
"wan-rx_packets": u.Stat.WanRxPackets.Val,
|
||||
"wan-tx_bytes": u.Stat.WanTxBytes.Val,
|
||||
"wan-tx_packets": u.Stat.WanTxPackets.Val,
|
||||
"uplink_name": u.Uplink.Name,
|
||||
"uplink_latency": u.Uplink.Latency.Val,
|
||||
"uplink_speed": u.Uplink.Speed.Val,
|
||||
"uplink_num_ports": u.Uplink.NumPort.Val,
|
||||
"uplink_max_speed": u.Uplink.MaxSpeed.Val,
|
||||
}
|
||||
pt, err := influx.NewPoint("usg", tags, fields, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
points := []*influx.Point{pt}
|
||||
for _, p := range u.NetworkTable {
|
||||
fields := Combine(map[string]interface{}{
|
||||
"ip": s.IP,
|
||||
"bytes": s.Bytes.Val,
|
||||
"last_seen": s.LastSeen.Val,
|
||||
"license_state": s.LicenseState,
|
||||
"guest-num_sta": s.GuestNumSta.Val,
|
||||
"rx_bytes": s.RxBytes.Val,
|
||||
"tx_bytes": s.TxBytes.Val,
|
||||
"uptime": s.Uptime.Val,
|
||||
"state": s.State.Val,
|
||||
"user-num_sta": s.UserNumSta.Val,
|
||||
"version": s.Version,
|
||||
"num_desktop": s.NumDesktop.Val,
|
||||
"num_handheld": s.NumHandheld.Val,
|
||||
"uplink_latency": s.Uplink.Latency.Val,
|
||||
"uplink_speed": s.Uplink.Speed.Val,
|
||||
"num_mobile": s.NumMobile.Val,
|
||||
"speedtest-status_latency": s.SpeedtestStatus.Latency.Val,
|
||||
"speedtest-status_runtime": s.SpeedtestStatus.Runtime.Val,
|
||||
"speedtest-status_ping": s.SpeedtestStatus.StatusPing.Val,
|
||||
"speedtest-status_xput_download": s.SpeedtestStatus.XputDownload.Val,
|
||||
"speedtest-status_xput_upload": s.SpeedtestStatus.XputUpload.Val,
|
||||
"lan-rx_bytes": s.Stat.Gw.LanRxBytes.Val,
|
||||
"lan-rx_packets": s.Stat.Gw.LanRxPackets.Val,
|
||||
"lan-tx_bytes": s.Stat.Gw.LanTxBytes.Val,
|
||||
"lan-tx_packets": s.Stat.Gw.LanTxPackets.Val,
|
||||
"lan-rx_dropped": s.Stat.Gw.LanRxDropped.Val,
|
||||
}, u.batchSysStats(s.SysStats, s.SystemStats))
|
||||
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) 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": u.Name,
|
||||
"device_id": u.ID,
|
||||
"device_mac": u.Mac,
|
||||
"site_name": u.SiteName,
|
||||
"up": p.Up.Txt,
|
||||
"dhcpd_dns_enabled": p.DhcpdDNSEnabled.Txt,
|
||||
"dhcpd_enabled": p.DhcpdEnabled.Txt,
|
||||
"dhcpd_time_offset_enabled": p.DhcpdTimeOffsetEnabled.Txt,
|
||||
"dhcp_relay_enabledy": p.DhcpRelayEnabled.Txt,
|
||||
"dhcpd_gateway_enabled": p.DhcpdGatewayEnabled.Txt,
|
||||
"enabled": p.Enabled.Txt,
|
||||
"vlan_enabled": p.VlanEnabled.Txt,
|
||||
"attr_no_delete": p.AttrNoDelete.Txt,
|
||||
"is_guest": p.IsGuest.Txt,
|
||||
"is_nat": p.IsNat.Txt,
|
||||
"networkgroup": p.Networkgroup,
|
||||
"site_id": p.SiteID,
|
||||
"ip": p.IP,
|
||||
"ip_subnet": p.IPSubnet,
|
||||
"mac": p.Mac,
|
||||
"name": p.Name,
|
||||
"domain_name": p.DomainName,
|
||||
"dhcpd_start": p.DhcpdStart,
|
||||
"dhcpd_stop": p.DhcpdStop,
|
||||
"ipv6_interface_type": p.Ipv6InterfaceType,
|
||||
"attr_hidden_id": p.AttrHiddenID,
|
||||
"purpose": p.Purpose,
|
||||
"device_name": tags["name"],
|
||||
"site_name": tags["site_name"],
|
||||
"ip": wan.IP,
|
||||
"purpose": wan.Name,
|
||||
"mac": wan.Mac,
|
||||
"ifname": wan.Ifname,
|
||||
"type": wan.Type,
|
||||
"up": wan.Up.Txt,
|
||||
"enabled": wan.Enable.Txt,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"bytes-r": wan.BytesR.Val,
|
||||
"full_duplex": wan.FullDuplex.Val,
|
||||
"gateway": wan.Gateway,
|
||||
"max_speed": wan.MaxSpeed.Val,
|
||||
"rx_bytes": wan.RxBytes.Val,
|
||||
"rx_bytes-r": wan.RxBytesR.Val,
|
||||
"rx_dropped": wan.RxDropped.Val,
|
||||
"rx_errors": wan.RxErrors.Val,
|
||||
"rx_broadcast": wan.RxBroadcast.Val,
|
||||
"rx_multicast": wan.RxMulticast.Val,
|
||||
"rx_packets": wan.RxPackets.Val,
|
||||
"speed": wan.Speed.Val,
|
||||
"tx_bytes": wan.TxBytes.Val,
|
||||
"tx_bytes-r": wan.TxBytesR.Val,
|
||||
"tx_dropped": wan.TxDropped.Val,
|
||||
"tx_errors": wan.TxErrors.Val,
|
||||
"tx_packets": wan.TxPackets.Val,
|
||||
"tx_broadcast": wan.TxBroadcast.Val,
|
||||
"tx_multicast": wan.TxMulticast.Val,
|
||||
}
|
||||
r.send(&metric{Table: "usg_wan_ports", Tags: tags, Fields: fields})
|
||||
}
|
||||
}
|
||||
|
||||
func (u *InfluxUnifi) batchNetTable(r report, tags map[string]string, nt unifi.NetworkTable) {
|
||||
for _, p := range nt {
|
||||
tags := map[string]string{
|
||||
"device_name": tags["name"],
|
||||
"site_name": tags["site_name"],
|
||||
"up": p.Up.Txt,
|
||||
"enabled": p.Enabled.Txt,
|
||||
"ip": p.IP,
|
||||
"mac": p.Mac,
|
||||
"name": p.Name,
|
||||
"domain_name": p.DomainName,
|
||||
"purpose": p.Purpose,
|
||||
"is_guest": p.IsGuest.Txt,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"num_sta": p.NumSta.Val,
|
||||
|
|
@ -188,44 +143,6 @@ func USGPoints(u *unifi.USG, now time.Time) ([]*influx.Point, error) {
|
|||
"tx_bytes": p.TxBytes.Val,
|
||||
"tx_packets": p.TxPackets.Val,
|
||||
}
|
||||
pt, err = influx.NewPoint("usg_networks", tags, fields, now)
|
||||
if err != nil {
|
||||
return points, err
|
||||
}
|
||||
points = append(points, pt)
|
||||
r.send(&metric{Table: "usg_networks", Tags: tags, Fields: fields})
|
||||
}
|
||||
for _, p := range u.PortTable {
|
||||
tags := map[string]string{
|
||||
"device_name": u.Name,
|
||||
"device_id": u.ID,
|
||||
"device_mac": u.Mac,
|
||||
"site_name": u.SiteName,
|
||||
"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,
|
||||
}
|
||||
fields := 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, ","),
|
||||
}
|
||||
pt, err = influx.NewPoint("usg_ports", tags, fields, now)
|
||||
if err != nil {
|
||||
return points, err
|
||||
}
|
||||
points = append(points, pt)
|
||||
}
|
||||
return points, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,119 +1,70 @@
|
|||
package influxunifi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"golift.io/unifi"
|
||||
)
|
||||
|
||||
// USWPoints generates Unifi Switch datapoints for InfluxDB.
|
||||
// batchUSW generates Unifi Switch datapoints for InfluxDB.
|
||||
// These points can be passed directly to influx.
|
||||
func USWPoints(u *unifi.USW, now time.Time) ([]*influx.Point, error) {
|
||||
if u.Stat.Sw == nil {
|
||||
u.Stat.Sw = &unifi.Sw{}
|
||||
func (u *InfluxUnifi) batchUSW(r report, s *unifi.USW) {
|
||||
if s.Stat.Sw == nil {
|
||||
s.Stat.Sw = &unifi.Sw{}
|
||||
}
|
||||
tags := map[string]string{
|
||||
"id": u.ID,
|
||||
"mac": u.Mac,
|
||||
"device_oid": u.Stat.Oid,
|
||||
"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,
|
||||
"device_id": u.DeviceID,
|
||||
"inform_ip": u.InformIP,
|
||||
"known_cfgversion": u.KnownCfgversion,
|
||||
"locating": u.Locating.Txt,
|
||||
"model": u.Model,
|
||||
"serial": u.Serial,
|
||||
"type": u.Type,
|
||||
"dot1x_portctrl_enabled": u.Dot1XPortctrlEnabled.Txt,
|
||||
"flowctrl_enabled": u.FlowctrlEnabled.Txt,
|
||||
"has_fan": u.HasFan.Txt,
|
||||
"has_temperature": u.HasTemperature.Txt,
|
||||
"jumboframe_enabled": u.JumboframeEnabled.Txt,
|
||||
"stp_version": u.StpVersion,
|
||||
"mac": s.Mac,
|
||||
"site_name": s.SiteName,
|
||||
"name": s.Name,
|
||||
"version": s.Version,
|
||||
"model": s.Model,
|
||||
"serial": s.Serial,
|
||||
"type": s.Type,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"fw_caps": u.FwCaps.Val,
|
||||
"guest-num_sta": u.GuestNumSta.Val,
|
||||
"ip": u.IP,
|
||||
"bytes": u.Bytes.Val,
|
||||
"fan_level": u.FanLevel.Val,
|
||||
"general_temperature": u.GeneralTemperature.Val,
|
||||
"last_seen": u.LastSeen.Val,
|
||||
"license_state": u.LicenseState,
|
||||
"overheating": u.Overheating.Val,
|
||||
"rx_bytes": u.RxBytes.Val,
|
||||
"tx_bytes": u.TxBytes.Val,
|
||||
"uptime": u.Uptime.Val,
|
||||
"state": u.State.Val,
|
||||
"user-num_sta": u.UserNumSta.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_used": u.SysStats.MemUsed.Val,
|
||||
"mem_total": u.SysStats.MemTotal.Val,
|
||||
"cpu": u.SystemStats.CPU.Val,
|
||||
"mem": u.SystemStats.Mem.Val,
|
||||
"stp_priority": u.StpPriority.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": u.UplinkDepth.Txt,
|
||||
}
|
||||
pt, err := influx.NewPoint("usw", tags, fields, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
points := []*influx.Point{pt}
|
||||
for _, p := range u.PortTable {
|
||||
fields := Combine(map[string]interface{}{
|
||||
"guest-num_sta": s.GuestNumSta.Val,
|
||||
"ip": s.IP,
|
||||
"bytes": s.Bytes.Val,
|
||||
"fan_level": s.FanLevel.Val,
|
||||
"general_temperature": s.GeneralTemperature.Val,
|
||||
"last_seen": s.LastSeen.Val,
|
||||
"rx_bytes": s.RxBytes.Val,
|
||||
"tx_bytes": s.TxBytes.Val,
|
||||
"uptime": s.Uptime.Val,
|
||||
"state": s.State.Val,
|
||||
"user-num_sta": s.UserNumSta.Val,
|
||||
"stat_bytes": s.Stat.Sw.Bytes.Val,
|
||||
"stat_rx_bytes": s.Stat.Sw.RxBytes.Val,
|
||||
"stat_rx_crypts": s.Stat.Sw.RxCrypts.Val,
|
||||
"stat_rx_dropped": s.Stat.Sw.RxDropped.Val,
|
||||
"stat_rx_errors": s.Stat.Sw.RxErrors.Val,
|
||||
"stat_rx_frags": s.Stat.Sw.RxFrags.Val,
|
||||
"stat_rx_packets": s.Stat.Sw.TxPackets.Val,
|
||||
"stat_tx_bytes": s.Stat.Sw.TxBytes.Val,
|
||||
"stat_tx_dropped": s.Stat.Sw.TxDropped.Val,
|
||||
"stat_tx_errors": s.Stat.Sw.TxErrors.Val,
|
||||
"stat_tx_packets": s.Stat.Sw.TxPackets.Val,
|
||||
"stat_tx_retries": s.Stat.Sw.TxRetries.Val,
|
||||
}, u.batchSysStats(s.SysStats, s.SystemStats))
|
||||
r.send(&metric{Table: "usw", Tags: tags, Fields: fields})
|
||||
u.batchPortTable(r, tags, s.PortTable)
|
||||
}
|
||||
|
||||
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_id": u.SiteID,
|
||||
"site_name": u.SiteName,
|
||||
"device_name": u.Name,
|
||||
"name": p.Name,
|
||||
"enable": p.Enable.Txt,
|
||||
"is_uplink": p.IsUplink.Txt,
|
||||
"up": p.Up.Txt,
|
||||
"portconf_id": p.PortconfID,
|
||||
"dot1x_mode": p.Dot1XMode,
|
||||
"dot1x_status": p.Dot1XStatus,
|
||||
"stp_state": p.StpState,
|
||||
"sfp_found": p.SfpFound.Txt,
|
||||
"op_mode": p.OpMode,
|
||||
"poe_mode": p.PoeMode,
|
||||
"port_poe": p.PortPoe.Txt,
|
||||
"port_idx": p.PortIdx.Txt,
|
||||
"port_id": u.Name + " Port " + p.PortIdx.Txt,
|
||||
"poe_enable": p.PoeEnable.Txt,
|
||||
"flowctrl_rx": p.FlowctrlRx.Txt,
|
||||
"flowctrl_tx": p.FlowctrlTx.Txt,
|
||||
"autoneg": p.Autoneg.Txt,
|
||||
"full_duplex": p.FullDuplex.Txt,
|
||||
"jumbo": p.Jumbo.Txt,
|
||||
"masked": p.Masked.Txt,
|
||||
"poe_good": p.PoeGood.Txt,
|
||||
"media": p.Media,
|
||||
"poe_class": p.PoeClass,
|
||||
"poe_caps": p.PoeCaps.Txt,
|
||||
"aggregated_by": p.AggregatedBy.Txt,
|
||||
"site_name": t["site_name"],
|
||||
"device_name": t["name"],
|
||||
"name": p.Name,
|
||||
"poe_mode": p.PoeMode,
|
||||
"port_poe": p.PortPoe.Txt,
|
||||
"port_idx": p.PortIdx.Txt,
|
||||
"port_id": t["name"] + " Port " + p.PortIdx.Txt,
|
||||
"poe_enable": p.PoeEnable.Txt,
|
||||
"flowctrl_rx": p.FlowctrlRx.Txt,
|
||||
"flowctrl_tx": p.FlowctrlTx.Txt,
|
||||
"media": p.Media,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"dbytes_r": p.BytesR.Val,
|
||||
|
|
@ -133,16 +84,12 @@ func USWPoints(u *unifi.USW, now time.Time) ([]*influx.Point, error) {
|
|||
"tx_errors": p.TxErrors.Val,
|
||||
"tx_multicast": p.TxMulticast.Val,
|
||||
"tx_packets": p.TxPackets.Val,
|
||||
"poe_current": p.PoeCurrent.Val,
|
||||
"poe_power": p.PoePower.Val,
|
||||
"poe_voltage": p.PoeVoltage.Val,
|
||||
"full_duplex": p.FullDuplex.Val,
|
||||
}
|
||||
pt, err = influx.NewPoint("usw_ports", tags, fields, now)
|
||||
if err != nil {
|
||||
return points, err
|
||||
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
|
||||
}
|
||||
points = append(points, pt)
|
||||
r.send(&metric{Table: "usw_ports", Tags: tags, Fields: fields})
|
||||
}
|
||||
return points, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"github.com/davidnewhall/unifi-poller/pkg/influxunifi"
|
||||
"github.com/spf13/pflag"
|
||||
"golift.io/unifi"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
|
@ -41,7 +41,7 @@ const ENVConfigPrefix = "UP_"
|
|||
|
||||
// UnifiPoller contains the application startup data, and auth info for UniFi & Influx.
|
||||
type UnifiPoller struct {
|
||||
Influx influx.Client
|
||||
Influx *influxunifi.InfluxUnifi
|
||||
Unifi *unifi.Unifi
|
||||
Flag *Flag
|
||||
Config *Config
|
||||
|
|
@ -65,9 +65,10 @@ type Config struct {
|
|||
Debug bool `json:"debug" toml:"debug" xml:"debug" yaml:"debug"`
|
||||
Quiet bool `json:"quiet,omitempty" toml:"quiet,omitempty" xml:"quiet" yaml:"quiet"`
|
||||
VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"`
|
||||
CollectIDS bool `json:"collect_ids" toml:"collect_ids" xml:"collect_ids" yaml:"collect_ids"`
|
||||
SaveIDS bool `json:"save_ids" toml:"save_ids" xml:"save_ids" yaml:"save_ids"`
|
||||
ReAuth bool `json:"reauthenticate" toml:"reauthenticate" xml:"reauthenticate" yaml:"reauthenticate"`
|
||||
InfxBadSSL bool `json:"influx_insecure_ssl" toml:"influx_insecure_ssl" xml:"influx_insecure_ssl" yaml:"influx_insecure_ssl"`
|
||||
SaveSites bool `json:"save_sites,omitempty" toml:"save_sites,omitempty" xml:"save_sites" yaml:"save_sites"`
|
||||
Mode string `json:"mode" toml:"mode" xml:"mode" yaml:"mode"`
|
||||
HTTPListen string `json:"http_listen" toml:"http_listen" xml:"http_listen" yaml:"http_listen"`
|
||||
Namespace string `json:"namespace" toml:"namespace" xml:"namespace" yaml:"namespace"`
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
package poller
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/davidnewhall/unifi-poller/pkg/influxunifi"
|
||||
"github.com/davidnewhall/unifi-poller/pkg/metrics"
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
)
|
||||
|
||||
// GetInfluxDB returns an InfluxDB interface.
|
||||
func (u *UnifiPoller) GetInfluxDB() (err error) {
|
||||
u.Influx, err = influx.NewHTTPClient(influx.HTTPConfig{
|
||||
Addr: u.Config.InfluxURL,
|
||||
Username: u.Config.InfluxUser,
|
||||
Password: u.Config.InfluxPass,
|
||||
TLSConfig: &tls.Config{InsecureSkipVerify: u.Config.InfxBadSSL},
|
||||
if u.Influx != nil {
|
||||
return nil
|
||||
}
|
||||
u.Influx, err = influxunifi.New(&influxunifi.Config{
|
||||
Database: u.Config.InfluxDB,
|
||||
User: u.Config.InfluxUser,
|
||||
Pass: u.Config.InfluxPass,
|
||||
BadSSL: u.Config.InfxBadSSL,
|
||||
URL: u.Config.InfluxURL,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("influxdb: %v", err)
|
||||
|
|
@ -30,51 +32,32 @@ func (u *UnifiPoller) GetInfluxDB() (err error) {
|
|||
// determine if there was a read or write error and act on it. This is currently
|
||||
// called in two places in this library. One returns an error, one does not.
|
||||
func (u *UnifiPoller) CollectAndProcess() error {
|
||||
if err := u.GetInfluxDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
metrics, err := u.CollectMetrics()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.AugmentMetrics(metrics)
|
||||
err = u.ReportMetrics(metrics)
|
||||
u.LogError(err, "processing metrics")
|
||||
return err
|
||||
}
|
||||
|
||||
// ReportMetrics batches all the metrics and writes them to InfluxDB.
|
||||
// This creates an InfluxDB writer, and returns an error if the write fails.
|
||||
func (u *UnifiPoller) ReportMetrics(metrics *metrics.Metrics) error {
|
||||
// Batch (and send) all the points.
|
||||
m := &influxunifi.Metrics{Metrics: metrics}
|
||||
// Make a new Influx Points Batcher.
|
||||
var err error
|
||||
m.BatchPoints, err = influx.NewBatchPoints(influx.BatchPointsConfig{Database: u.Config.InfluxDB})
|
||||
report, err := u.Influx.ReportMetrics(metrics)
|
||||
if err != nil {
|
||||
return fmt.Errorf("influx.NewBatchPoints: %v", err)
|
||||
u.LogError(err, "processing metrics")
|
||||
return err
|
||||
}
|
||||
for _, err := range m.ProcessPoints() {
|
||||
u.LogError(err, "influx.ProcessPoints")
|
||||
}
|
||||
if err = u.Influx.Write(m.BatchPoints); err != nil {
|
||||
return fmt.Errorf("influxdb.Write(points): %v", err)
|
||||
}
|
||||
u.LogInfluxReport(m)
|
||||
u.LogInfluxReport(report)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LogInfluxReport writes a log message after exporting to influxdb.
|
||||
func (u *UnifiPoller) LogInfluxReport(m *influxunifi.Metrics) {
|
||||
var fields, points int
|
||||
for _, p := range m.Points() {
|
||||
points++
|
||||
i, _ := p.Fields()
|
||||
fields += len(i)
|
||||
}
|
||||
func (u *UnifiPoller) LogInfluxReport(r *influxunifi.Report) {
|
||||
idsMsg := ""
|
||||
if u.Config.CollectIDS {
|
||||
idsMsg = fmt.Sprintf("IDS Events: %d, ", len(m.IDSList))
|
||||
if u.Config.SaveIDS {
|
||||
idsMsg = fmt.Sprintf("IDS Events: %d, ", len(r.Metrics.IDSList))
|
||||
}
|
||||
u.Logf("UniFi Measurements Recorded. Sites: %d, Clients: %d, "+
|
||||
"Wireless APs: %d, Gateways: %d, Switches: %d, %sPoints: %d, Fields: %d",
|
||||
len(m.Sites), len(m.Clients), len(m.UAPs),
|
||||
len(m.UDMs)+len(m.USGs), len(m.USWs), idsMsg, points, fields)
|
||||
u.Logf("UniFi Metrics Recorded. Sites: %d, Clients: %d, "+
|
||||
"UAP: %d, USG/UDM: %d, USW: %d, %sPoints: %d, Fields: %d, Errs: %d, Elapsed: %v",
|
||||
len(r.Metrics.Sites), len(r.Metrics.Clients), len(r.Metrics.UAPs),
|
||||
len(r.Metrics.UDMs)+len(r.Metrics.USGs), len(r.Metrics.USWs), idsMsg, r.Total,
|
||||
r.Fields, len(r.Errors), r.Elapsed.Round(time.Millisecond))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package poller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -54,16 +53,11 @@ func (u *UnifiPoller) ExportMetrics() (*metrics.Metrics, error) {
|
|||
// This is run by Prometheus as LoggingFn
|
||||
func (u *UnifiPoller) LogExportReport(report *promunifi.Report) {
|
||||
m := report.Metrics
|
||||
idsMsg := ""
|
||||
if u.Config.CollectIDS {
|
||||
idsMsg = fmt.Sprintf(", IDS Events: %d, ", len(m.IDSList))
|
||||
}
|
||||
|
||||
u.Logf("UniFi Measurements Exported. Site: %d, Client: %d, "+
|
||||
"UAP: %d, USG/UDM: %d, USW: %d%s, Descs: %d, "+
|
||||
"UAP: %d, USG/UDM: %d, USW: %d, Descs: %d, "+
|
||||
"Metrics: %d, Errs: %d, 0s: %d, Reqs/Total: %v / %v",
|
||||
len(m.Sites), len(m.Clients), len(m.UAPs), len(m.UDMs)+len(m.USGs), len(m.USWs),
|
||||
idsMsg, report.Descs, report.Total, report.Errors, report.Zeros,
|
||||
report.Descs, report.Total, report.Errors, report.Zeros,
|
||||
report.Fetch.Round(time.Millisecond/oneDecimalPoint),
|
||||
report.Elapsed.Round(time.Millisecond/oneDecimalPoint))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,13 +21,14 @@ func New() *UnifiPoller {
|
|||
InfluxPass: defaultInfluxPass,
|
||||
InfluxDB: defaultInfluxDB,
|
||||
UnifiUser: defaultUnifiUser,
|
||||
UnifiPass: defaultUnifiUser,
|
||||
UnifiPass: "",
|
||||
UnifiBase: defaultUnifiURL,
|
||||
Interval: Duration{defaultInterval},
|
||||
Sites: []string{"all"},
|
||||
SaveSites: true,
|
||||
HTTPListen: defaultHTTPListen,
|
||||
Namespace: appName,
|
||||
}, Flag: &Flag{},
|
||||
}, Flag: &Flag{ConfigFile: DefaultConfFile},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,43 +100,52 @@ func (u *UnifiPoller) Run() error {
|
|||
|
||||
switch strings.ToLower(u.Config.Mode) {
|
||||
default:
|
||||
if err := u.GetInfluxDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.PollController()
|
||||
|
||||
case "influxlambda", "lambdainflux", "lambda_influx", "influx_lambda":
|
||||
if err := u.GetInfluxDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
u.LastCheck = time.Now()
|
||||
return u.CollectAndProcess()
|
||||
|
||||
case "prometheus", "exporter":
|
||||
return u.RunPrometheus()
|
||||
case "both":
|
||||
return u.RunBoth()
|
||||
}
|
||||
}
|
||||
|
||||
// RunBoth starts the prometheus exporter and influxdb exporter at the same time.
|
||||
// This will likely double the amount of polls your controller receives.
|
||||
func (u *UnifiPoller) RunBoth() error {
|
||||
e := make(chan error)
|
||||
defer close(e)
|
||||
go func() {
|
||||
e <- u.RunPrometheus()
|
||||
}()
|
||||
go func() {
|
||||
e <- u.PollController()
|
||||
}()
|
||||
// If either method returns an error (even nil), bail out.
|
||||
return <-e
|
||||
}
|
||||
|
||||
// PollController runs forever, polling UniFi and pushing to InfluxDB
|
||||
// This is started by Run() after everything checks out.
|
||||
// This is started by Run() or RunBoth() after everything checks out.
|
||||
func (u *UnifiPoller) PollController() error {
|
||||
interval := u.Config.Interval.Round(time.Second)
|
||||
log.Printf("[INFO] Everything checks out! Poller started, interval: %v", interval)
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for u.LastCheck = range ticker.C {
|
||||
var err error
|
||||
// Some users need to re-auth every interval because the cookie times out.
|
||||
if u.Config.ReAuth {
|
||||
u.LogDebugf("Re-authenticating to UniFi Controller")
|
||||
// Some users need to re-auth every interval because the cookie times out.
|
||||
if err = u.Unifi.Login(); err != nil {
|
||||
u.LogError(err, "re-authenticating")
|
||||
if err := u.Unifi.Login(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
// Only run this if the authentication procedure didn't return error.
|
||||
_ = u.CollectAndProcess()
|
||||
if err := u.CollectAndProcess(); err != nil {
|
||||
return err
|
||||
}
|
||||
// check for errors from the unifi polls.
|
||||
if u.errorCount > 0 {
|
||||
return fmt.Errorf("too many errors, stopping poller")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ func (u *UnifiPoller) CollectMetrics() (*metrics.Metrics, error) {
|
|||
// Get the sites we care about.
|
||||
m.Sites, err = u.GetFilteredSites()
|
||||
u.LogError(err, "unifi.GetSites()")
|
||||
if u.Config.CollectIDS {
|
||||
if u.Config.SaveIDS {
|
||||
m.IDSList, err = u.Unifi.GetIDS(m.Sites, time.Now().Add(u.Config.Interval.Duration), time.Now())
|
||||
u.LogError(err, "unifi.GetIDS()")
|
||||
}
|
||||
|
|
@ -111,6 +111,9 @@ func (u *UnifiPoller) AugmentMetrics(metrics *metrics.Metrics) {
|
|||
metrics.Clients[i].GwName = devices[c.GwMac]
|
||||
metrics.Clients[i].RadioDescription = bssdIDs[metrics.Clients[i].Bssid] + metrics.Clients[i].RadioProto
|
||||
}
|
||||
if !u.Config.SaveSites {
|
||||
metrics.Sites = nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetFilteredSites returns a list of sites to fetch data for.
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func (u *promUnifi) exportSite(r report, s *unifi.Site) {
|
|||
r.send([]*metric{
|
||||
{u.Site.TxBytesR, prometheus.GaugeValue, h.TxBytesR, labels},
|
||||
{u.Site.RxBytesR, prometheus.GaugeValue, h.RxBytesR, labels},
|
||||
{u.Site.Uptime, prometheus.GaugeValue, h.Latency, labels},
|
||||
{u.Site.Uptime, prometheus.GaugeValue, h.Uptime, labels},
|
||||
{u.Site.Latency, prometheus.GaugeValue, h.Latency.Val / 1000, labels},
|
||||
{u.Site.XputUp, prometheus.GaugeValue, h.XputUp, labels},
|
||||
{u.Site.XputDown, prometheus.GaugeValue, h.XputDown, labels},
|
||||
|
|
|
|||
|
|
@ -152,16 +152,16 @@ func descUAP(ns string) *uap {
|
|||
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", "Radio Channel Utilization Receive", labelR, nil),
|
||||
RadioCuSelfTx: prometheus.NewDesc(ns+"radio_channel_utilization_transmit", "Radio Channel Utilization Transmit", labelR, nil),
|
||||
RadioCuTotal: prometheus.NewDesc(ns+"radio_channel_utilization_total", "Radio Channel Utilization", labelR, nil),
|
||||
RadioCuSelfRx: prometheus.NewDesc(ns+"radio_channel_utilization_receive_percent", "Radio Channel Utilization Receive", labelR, nil),
|
||||
RadioCuSelfTx: prometheus.NewDesc(ns+"radio_channel_utilization_transmit_percent", "Radio Channel Utilization Transmit", labelR, nil),
|
||||
RadioCuTotal: prometheus.NewDesc(ns+"radio_channel_utilization_percent", "Radio Channel Utilization", labelR, nil),
|
||||
RadioExtchannel: prometheus.NewDesc(ns+"radio_ext_channel", "Radio Ext Channel", labelR, nil),
|
||||
RadioGain: prometheus.NewDesc(ns+"radio_gain", "Radio Gain", labelR, nil),
|
||||
RadioGuestNumSta: prometheus.NewDesc(ns+"radio_guest_stations", "Radio Guest Station Count", labelR, nil),
|
||||
RadioNumSta: prometheus.NewDesc(ns+"radio_stations", "Radio Total Station Count", labelR, nil),
|
||||
RadioUserNumSta: prometheus.NewDesc(ns+"radio_user_stations", "Radio User Station Count", labelR, nil),
|
||||
RadioTxPackets: prometheus.NewDesc(ns+"radio_transmit_packets_total", "Radio Transmitted Packets", labelR, nil),
|
||||
RadioTxRetries: prometheus.NewDesc(ns+"radio_transmit_retries_total", "Radio Transmit Retries", labelR, 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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ func (u *promUnifi) exportUDM(r report, d *unifi.UDM) {
|
|||
u.exportUSWstats(r, labels, d.Stat.Sw)
|
||||
u.exportPortTable(r, labels, d.PortTable)
|
||||
// Gateway Data
|
||||
u.exportUSGstats(r, labels, d.Stat.Gw, d.SpeedtestStatus)
|
||||
u.exportUSGstats(r, labels, d.Stat.Gw, d.SpeedtestStatus, d.Uplink)
|
||||
u.exportWANPorts(r, labels, d.Wan1, d.Wan2)
|
||||
// Wireless Data - UDM (non-pro) only
|
||||
if d.Stat.Ap != nil && d.VapTable != nil {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ type usg struct {
|
|||
WanTxMulticast *prometheus.Desc
|
||||
WanBytesR *prometheus.Desc
|
||||
Latency *prometheus.Desc
|
||||
UplinkLatency *prometheus.Desc
|
||||
UplinkSpeed *prometheus.Desc
|
||||
Runtime *prometheus.Desc
|
||||
XputDownload *prometheus.Desc
|
||||
XputUpload *prometheus.Desc
|
||||
|
|
@ -60,6 +62,8 @@ func descUSG(ns string) *usg {
|
|||
LanTxPackets: prometheus.NewDesc(ns+"lan_transmit_packets_total", "LAN Transmit Packets Total", labels, nil),
|
||||
LanTxBytes: prometheus.NewDesc(ns+"lan_transmit_bytes_total", "LAN Transmit Bytes Total", labels, nil),
|
||||
Latency: prometheus.NewDesc(ns+"speedtest_latency_seconds", "Speedtest Latency", labels, nil),
|
||||
UplinkLatency: prometheus.NewDesc(ns+"uplink_latency_seconds", "Uplink Latency", labels, nil),
|
||||
UplinkSpeed: prometheus.NewDesc(ns+"uplink_speed_mbps", "Uplink Speed", labels, nil),
|
||||
Runtime: prometheus.NewDesc(ns+"speedtest_runtime", "Speedtest Run Time", labels, nil),
|
||||
XputDownload: prometheus.NewDesc(ns+"speedtest_download", "Speedtest Download Rate", labels, nil),
|
||||
XputUpload: prometheus.NewDesc(ns+"speedtest_upload", "Speedtest Upload Rate", labels, nil),
|
||||
|
|
@ -90,10 +94,10 @@ func (u *promUnifi) exportUSG(r report, d *unifi.USG) {
|
|||
{u.Device.Mem, prometheus.GaugeValue, d.SystemStats.Mem, labels},
|
||||
})
|
||||
u.exportWANPorts(r, labels, d.Wan1, d.Wan2)
|
||||
u.exportUSGstats(r, labels, d.Stat.Gw, d.SpeedtestStatus)
|
||||
u.exportUSGstats(r, labels, d.Stat.Gw, d.SpeedtestStatus, d.Uplink)
|
||||
}
|
||||
|
||||
func (u *promUnifi) exportUSGstats(r report, labels []string, gw *unifi.Gw, st unifi.SpeedtestStatus) {
|
||||
func (u *promUnifi) exportUSGstats(r report, labels []string, gw *unifi.Gw, st unifi.SpeedtestStatus, ul unifi.Uplink) {
|
||||
labelLan := []string{"lan", labels[6], labels[7]}
|
||||
labelWan := []string{"all", labels[6], labels[7]}
|
||||
r.send([]*metric{
|
||||
|
|
@ -110,6 +114,8 @@ func (u *promUnifi) exportUSGstats(r report, labels []string, gw *unifi.Gw, st u
|
|||
{u.USG.LanTxPackets, prometheus.CounterValue, gw.LanTxPackets, labelLan},
|
||||
{u.USG.LanTxBytes, prometheus.CounterValue, gw.LanTxBytes, labelLan},
|
||||
{u.USG.LanRxDropped, prometheus.CounterValue, gw.LanRxDropped, labelLan},
|
||||
{u.USG.UplinkLatency, prometheus.GaugeValue, ul.Latency.Val / 1000, labelWan},
|
||||
{u.USG.UplinkSpeed, prometheus.GaugeValue, ul.Speed, labelWan},
|
||||
// Speed Test Stats
|
||||
{u.USG.Latency, prometheus.GaugeValue, st.Latency.Val / 1000, labelWan},
|
||||
{u.USG.Runtime, prometheus.GaugeValue, st.Runtime, labelWan},
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ func descUSW(ns string) *usw {
|
|||
pns := ns + "port_"
|
||||
// labels := []string{"ip", "version", "model", "serial", "type", "mac", "site_name", "name"}
|
||||
labelS := []string{"site_name", "name"} // labels[6:]
|
||||
labelP := []string{"port_num", "port_name", "port_mac", "port_ip", "site_name", "name"}
|
||||
labelP := []string{"port_id", "port_num", "port_name", "port_mac", "port_ip", "site_name", "name"}
|
||||
return &usw{
|
||||
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),
|
||||
|
|
@ -147,11 +147,11 @@ func (u *promUnifi) exportUSWstats(r report, labels []string, sw *unifi.Sw) {
|
|||
func (u *promUnifi) exportPortTable(r report, labels []string, pt []unifi.Port) {
|
||||
// Per-port data on a switch
|
||||
for _, p := range pt {
|
||||
if !p.Up.Val {
|
||||
if !p.Up.Val || !p.Enable.Val {
|
||||
continue
|
||||
}
|
||||
// Copy labels, and add four new ones.
|
||||
labelP := []string{p.PortIdx.Txt, p.Name, p.Mac, p.IP, labels[6], labels[7]}
|
||||
labelP := []string{labels[7] + " Port " + p.PortIdx.Txt, p.PortIdx.Txt, p.Name, p.Mac, p.IP, labels[6], labels[7]}
|
||||
if p.PoeEnable.Val && p.PortPoe.Val {
|
||||
r.send([]*metric{
|
||||
{u.USW.PoeCurrent, prometheus.GaugeValue, p.PoeCurrent, labelP},
|
||||
|
|
@ -176,6 +176,7 @@ func (u *promUnifi) exportPortTable(r report, labels []string, pt []unifi.Port)
|
|||
{u.USW.TxDropped, prometheus.CounterValue, p.TxDropped, labelP},
|
||||
{u.USW.TxErrors, prometheus.CounterValue, p.TxErrors, labelP},
|
||||
{u.USW.TxMulticast, prometheus.CounterValue, p.TxMulticast, labelP},
|
||||
{u.USW.TxPackets, prometheus.CounterValue, p.TxPackets, labelP},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue