diff --git a/examples/up.conf.example b/examples/up.conf.example index db3b14ad..fb397501 100644 --- a/examples/up.conf.example +++ b/examples/up.conf.example @@ -61,6 +61,7 @@ pass = "unifipoller" sites = ["all"] save_ids = false + save_dpi = false save_sites = true verify_ssl = false @@ -85,6 +86,14 @@ # Only useful if IDS or IPS are enabled on one of the sites. save_ids = false + # Enable collection of Deep Packet Inspection data. This data breaks down traffic + # types for each client and site, it powers a dedicated DPI dashboard. + # Enabling this adds roughly 150 data points per client. That's 6000 metrics for + # 40 clients. This adds a little bit of poller run time per interval and causes + # more API requests to your controller(s). Don't let these "cons" sway you: + # it's cool data. Please provide feedback on your experience with this feature. + save_dpi = 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 diff --git a/examples/up.json.example b/examples/up.json.example index 6e8c8c66..4675bf61 100644 --- a/examples/up.json.example +++ b/examples/up.json.example @@ -30,6 +30,7 @@ "url": "https://127.0.0.1:8443", "sites": ["all"], "save_ids": false, + "save_dpi": false, "save_sites": true, "verify_ssl": false }, @@ -40,6 +41,7 @@ "pass": "unifipoller", "url": "https://127.0.0.1:8443", "sites": ["all"], + "save_dpi": false, "save_ids": false, "save_sites": true, "verify_ssl": false diff --git a/examples/up.xml.example b/examples/up.xml.example index d1a1be3b..2ff1eecf 100644 --- a/examples/up.xml.example +++ b/examples/up.xml.example @@ -32,6 +32,7 @@ https://127.0.0.1:8443 false false + false true @@ -43,6 +44,7 @@ https://127.0.0.1:8443 false false + false true diff --git a/examples/up.yaml.example b/examples/up.yaml.example index 33cc5088..4ed27193 100644 --- a/examples/up.yaml.example +++ b/examples/up.yaml.example @@ -34,6 +34,7 @@ unifi: - all verify_ssl: false save_ids: false + save_dpi: false save_sites: true @@ -42,9 +43,10 @@ unifi: - role: "" user: "unifipoller" pass: "unifipoller" - url: "https://127.0.0.1:8443" + url: "https://127.0.0.1:8443" sites: - all verify_ssl: false - save_ids: false + save_ids: false + save_dpi: false save_sites: true diff --git a/go.mod b/go.mod index ffc8b47f..b5cb3c39 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,6 @@ require ( github.com/prometheus/client_golang v1.3.0 github.com/prometheus/common v0.7.0 github.com/spf13/pflag v1.0.5 - golang.org/x/sys v0.0.0-20191224085550-c709ea063b76 // indirect golift.io/cnfg v0.0.5 - golift.io/unifi v4.1.7-0.20191215214413-4d78625be4cd+incompatible - gopkg.in/yaml.v2 v2.2.7 // indirect + golift.io/unifi v0.0.400 ) diff --git a/go.sum b/go.sum index b2fbc010..f9e33d08 100644 --- a/go.sum +++ b/go.sum @@ -22,13 +22,11 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -45,8 +43,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -54,12 +50,10 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -82,26 +76,16 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f h1:68K/z8GLUxV76xGSqwTWw2gyk/jwn79LUL43rES2g8o= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191224085550-c709ea063b76 h1:Dho5nD6R3PcW2SH1or8vS0dszDaXRxIw55lBX7XiE5g= -golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golift.io/cnfg v0.0.0-20191225081851-bec8d8f51fc4 h1:lCMyrYNLbSBxOiGDnn0ZKWmafS0OEBvaiu7qUJZFrwA= -golift.io/cnfg v0.0.0-20191225081851-bec8d8f51fc4/go.mod h1:ScFDIJg/rJGHbRaed/i7g1lBhywEjB0JiP2uZr3xC3A= golift.io/cnfg v0.0.5 h1:HnMU8Z9C/igKvir1dqaHx5BPuNGZrp99FCtdJyP2Z4I= golift.io/cnfg v0.0.5/go.mod h1:ScFDIJg/rJGHbRaed/i7g1lBhywEjB0JiP2uZr3xC3A= -golift.io/unifi v0.0.0-20191215214413-4d78625be4cd h1:d4wPilxOdtcVqwv7WhAXsrSp9/gvMc0ff4xYBTxcqSs= -golift.io/unifi v0.0.0-20191215214413-4d78625be4cd/go.mod h1:Zjw57ZAzTzCMw784pE8CdCFgkYSzVZzmJ++WUttbjto= +golift.io/unifi v0.0.400 h1:r8FlE+p+zmm8jnQdT367H2aGVMTgxZTrHSwbsHBcayA= +golift.io/unifi v0.0.400/go.mod h1:4BjegFlwA3am3mPlY0qHAnSKli4eexLQV42QKaRx9OY= golift.io/unifi v4.1.6+incompatible h1:Yhb/+obX2vT9i6PElGislSuQ1WUtOf+l+sRjVxlY6nM= golift.io/unifi v4.1.6+incompatible/go.mod h1:Zjw57ZAzTzCMw784pE8CdCFgkYSzVZzmJ++WUttbjto= -golift.io/unifi v4.1.7-0.20191215214413-4d78625be4cd+incompatible h1:PBa6XT7PYrYUULBON83Owjv8cUhyu1e13lgl+zAxwHo= -golift.io/unifi v4.1.7-0.20191215214413-4d78625be4cd+incompatible/go.mod h1:Zjw57ZAzTzCMw784pE8CdCFgkYSzVZzmJ++WUttbjto= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/influxunifi/clients.go b/pkg/influxunifi/clients.go index 9e15ec19..8ac00a4d 100644 --- a/pkg/influxunifi/clients.go +++ b/pkg/influxunifi/clients.go @@ -71,3 +71,25 @@ func (u *InfluxUnifi) batchClient(r report, s *unifi.Client) { r.send(&metric{Table: "clients", Tags: tags, Fields: fields}) } + +func (u *InfluxUnifi) batchClientDPI(r report, s *unifi.DPITable) { + for _, dpi := range s.ByApp { + r.send(&metric{ + Table: "clientdpi", + Tags: map[string]string{ + "category": unifi.DPICats.Get(dpi.Cat), + "application": unifi.DPIApps.GetApp(dpi.Cat, dpi.App), + "name": s.Name, + "mac": s.MAC, + "site_name": s.SiteName, + "source": s.SourceName, + }, + Fields: map[string]interface{}{ + "tx_packets": dpi.TxPackets, + "rx_packets": dpi.RxPackets, + "tx_bytes": dpi.TxBytes, + "rx_bytes": dpi.RxBytes, + }}, + ) + } +} diff --git a/pkg/influxunifi/influxdb.go b/pkg/influxunifi/influxdb.go index 280e94a9..61d63ce1 100644 --- a/pkg/influxunifi/influxdb.go +++ b/pkg/influxunifi/influxdb.go @@ -194,6 +194,16 @@ func (u *InfluxUnifi) loopPoints(r report) { r.add() r.add() r.add() + r.add() + r.add() + + go func() { + defer r.done() + + for _, s := range m.SitesDPI { + u.batchSiteDPI(r, s) + } + }() go func() { defer r.done() @@ -203,6 +213,14 @@ func (u *InfluxUnifi) loopPoints(r report) { } }() + go func() { + defer r.done() + + for _, s := range m.ClientsDPI { + u.batchClientDPI(r, s) + } + }() + go func() { defer r.done() @@ -219,15 +237,14 @@ func (u *InfluxUnifi) loopPoints(r report) { } }() - if m.Devices == nil { - return - } - u.loopDevicePoints(r) } func (u *InfluxUnifi) loopDevicePoints(r report) { m := r.metrics() + if m.Devices == nil { + return + } r.add() r.add() diff --git a/pkg/influxunifi/site.go b/pkg/influxunifi/site.go index 49715e5a..1ae313c4 100644 --- a/pkg/influxunifi/site.go +++ b/pkg/influxunifi/site.go @@ -56,3 +56,23 @@ func (u *InfluxUnifi) batchSite(r report, s *unifi.Site) { r.send(&metric{Table: "subsystems", Tags: tags, Fields: fields}) } } + +func (u *InfluxUnifi) batchSiteDPI(r report, s *unifi.DPITable) { + for _, dpi := range s.ByApp { + r.send(&metric{ + Table: "sitedpi", + Tags: map[string]string{ + "category": unifi.DPICats.Get(dpi.Cat), + "application": unifi.DPIApps.GetApp(dpi.Cat, dpi.App), + "site_name": s.SiteName, + "source": s.SourceName, + }, + Fields: map[string]interface{}{ + "tx_packets": dpi.TxPackets, + "rx_packets": dpi.RxPackets, + "tx_bytes": dpi.TxBytes, + "rx_bytes": dpi.RxBytes, + }}, + ) + } +} diff --git a/pkg/inputunifi/collector.go b/pkg/inputunifi/collector.go index 85941fee..f044401f 100644 --- a/pkg/inputunifi/collector.go +++ b/pkg/inputunifi/collector.go @@ -80,6 +80,16 @@ func (u *InputUnifi) pollController(c *Controller) (*poller.Metrics, error) { return m, fmt.Errorf("unifi.GetSites(%v): %v", c.URL, err) } + if c.SaveDPI { + if m.SitesDPI, err = c.Unifi.GetSiteDPI(m.Sites); err != nil { + return m, fmt.Errorf("unifi.GetSiteDPI(%v): %v", c.URL, err) + } + + if m.ClientsDPI, err = c.Unifi.GetClientsDPI(m.Sites); err != nil { + return m, fmt.Errorf("unifi.GetClientsDPI(%v): %v", c.URL, err) + } + } + if c.SaveIDS { m.IDSList, err = c.Unifi.GetIDS(m.Sites, time.Now().Add(2*time.Minute), time.Now()) if err != nil { @@ -132,12 +142,23 @@ func (u *InputUnifi) augmentMetrics(c *Controller, metrics *poller.Metrics) *pol // These come blank, so set them here. for i, c := range metrics.Clients { + if devices[c.Mac] = c.Name; c.Name == "" { + devices[c.Mac] = c.Hostname + } metrics.Clients[i].SwName = devices[c.SwMac] metrics.Clients[i].ApName = devices[c.ApMac] metrics.Clients[i].GwName = devices[c.GwMac] metrics.Clients[i].RadioDescription = bssdIDs[metrics.Clients[i].Bssid] + metrics.Clients[i].RadioProto } + for i := range metrics.ClientsDPI { + // Name on Client DPI data also comes blank, find it based on MAC address. + metrics.ClientsDPI[i].Name = devices[metrics.ClientsDPI[i].MAC] + if metrics.ClientsDPI[i].Name == "" { + metrics.ClientsDPI[i].Name = metrics.ClientsDPI[i].MAC + } + } + if !*c.SaveSites { metrics.Sites = nil } diff --git a/pkg/inputunifi/input.go b/pkg/inputunifi/input.go index 45d3e4e9..d6540d83 100644 --- a/pkg/inputunifi/input.go +++ b/pkg/inputunifi/input.go @@ -33,6 +33,7 @@ type InputUnifi struct { type Controller struct { VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"` SaveIDS bool `json:"save_ids" toml:"save_ids" xml:"save_ids" yaml:"save_ids"` + SaveDPI bool `json:"save_dpi" toml:"save_dpi" xml:"save_dpi" yaml:"save_dpi"` SaveSites *bool `json:"save_sites" toml:"save_sites" xml:"save_sites" yaml:"save_sites"` Role string `json:"role" toml:"role" xml:"role,attr" yaml:"role"` User string `json:"user" toml:"user" xml:"user" yaml:"user"` diff --git a/pkg/poller/config.go b/pkg/poller/config.go index 7d706060..b40c8938 100644 --- a/pkg/poller/config.go +++ b/pkg/poller/config.go @@ -49,6 +49,8 @@ type Metrics struct { unifi.IDSList unifi.Clients *unifi.Devices + SitesDPI []*unifi.DPITable + ClientsDPI []*unifi.DPITable } // Config represents the core library input data. diff --git a/pkg/poller/inputs.go b/pkg/poller/inputs.go index a637239c..897a8d0d 100644 --- a/pkg/poller/inputs.go +++ b/pkg/poller/inputs.go @@ -95,23 +95,7 @@ func (u *UnifiPoller) Metrics() (*Metrics, bool, error) { } ok = true - - metrics.Sites = append(metrics.Sites, m.Sites...) - metrics.Clients = append(metrics.Clients, m.Clients...) - metrics.IDSList = append(metrics.IDSList, m.IDSList...) - - if m.Devices == nil { - continue - } - - if metrics.Devices == nil { - metrics.Devices = &unifi.Devices{} - } - - metrics.UAPs = append(metrics.UAPs, m.UAPs...) - metrics.USGs = append(metrics.USGs, m.USGs...) - metrics.USWs = append(metrics.USWs, m.USWs...) - metrics.UDMs = append(metrics.UDMs, m.UDMs...) + metrics = AppendMetrics(metrics, m) } var err error @@ -158,7 +142,9 @@ func (u *UnifiPoller) MetricsFrom(filter *Filter) (*Metrics, bool, error) { // AppendMetrics combined the metrics from two sources. func AppendMetrics(existing *Metrics, m *Metrics) *Metrics { + existing.SitesDPI = append(existing.SitesDPI, m.SitesDPI...) existing.Sites = append(existing.Sites, m.Sites...) + existing.ClientsDPI = append(existing.ClientsDPI, m.ClientsDPI...) existing.Clients = append(existing.Clients, m.Clients...) existing.IDSList = append(existing.IDSList, m.IDSList...) diff --git a/pkg/promunifi/clients.go b/pkg/promunifi/clients.go index b24b2d62..844d899d 100644 --- a/pkg/promunifi/clients.go +++ b/pkg/promunifi/clients.go @@ -6,44 +6,43 @@ import ( ) type uclient struct { - Anomalies *prometheus.Desc - BytesR *prometheus.Desc - CCQ *prometheus.Desc - Satisfaction *prometheus.Desc - Noise *prometheus.Desc - RoamCount *prometheus.Desc - RSSI *prometheus.Desc - RxBytes *prometheus.Desc - RxBytesR *prometheus.Desc - RxPackets *prometheus.Desc - RxRate *prometheus.Desc - Signal *prometheus.Desc - TxBytes *prometheus.Desc - TxBytesR *prometheus.Desc - TxPackets *prometheus.Desc - TxRetries *prometheus.Desc - TxPower *prometheus.Desc - TxRate *prometheus.Desc - Uptime *prometheus.Desc - WifiTxAttempts *prometheus.Desc - WiredRxBytes *prometheus.Desc - WiredRxBytesR *prometheus.Desc - WiredRxPackets *prometheus.Desc - WiredTxBytes *prometheus.Desc - WiredTxBytesR *prometheus.Desc - WiredTxPackets *prometheus.Desc - DpiStatsApp *prometheus.Desc - DpiStatsCat *prometheus.Desc - DpiStatsRxBytes *prometheus.Desc - DpiStatsRxPackets *prometheus.Desc - DpiStatsTxBytes *prometheus.Desc - DpiStatsTxPackets *prometheus.Desc + Anomalies *prometheus.Desc + BytesR *prometheus.Desc + CCQ *prometheus.Desc + Satisfaction *prometheus.Desc + Noise *prometheus.Desc + RoamCount *prometheus.Desc + RSSI *prometheus.Desc + RxBytes *prometheus.Desc + RxBytesR *prometheus.Desc + RxPackets *prometheus.Desc + RxRate *prometheus.Desc + Signal *prometheus.Desc + TxBytes *prometheus.Desc + TxBytesR *prometheus.Desc + TxPackets *prometheus.Desc + TxRetries *prometheus.Desc + TxPower *prometheus.Desc + TxRate *prometheus.Desc + Uptime *prometheus.Desc + WifiTxAttempts *prometheus.Desc + WiredRxBytes *prometheus.Desc + WiredRxBytesR *prometheus.Desc + WiredRxPackets *prometheus.Desc + WiredTxBytes *prometheus.Desc + WiredTxBytesR *prometheus.Desc + WiredTxPackets *prometheus.Desc + DPITxPackets *prometheus.Desc + DPIRxPackets *prometheus.Desc + DPITxBytes *prometheus.Desc + DPIRxBytes *prometheus.Desc } func descClient(ns string) *uclient { labels := []string{"name", "mac", "site_name", "gw_name", "sw_name", "vlan", "ip", "oui", "network", "sw_port", "ap_name", "source", "wired"} labelW := append([]string{"radio_name", "radio", "radio_proto", "channel", "essid", "bssid", "radio_desc"}, labels...) + labelDPI := []string{"name", "mac", "site_name", "source", "category", "application"} return &uclient{ Anomalies: prometheus.NewDesc(ns+"anomalies", "Client Anomalies", labelW, nil), @@ -66,20 +65,25 @@ func descClient(ns string) *uclient { TxRate: prometheus.NewDesc(ns+"radio_transmit_rate_bps", "Client Transmit Rate", labelW, nil), WifiTxAttempts: prometheus.NewDesc(ns+"wifi_attempts_transmit_total", "Client Wifi Transmit Attempts", labelW, nil), Uptime: prometheus.NewDesc(ns+"uptime_seconds", "Client Uptime", labelW, nil), - /* needs more "looking into" - DpiStatsApp: prometheus.NewDesc(ns+"dpi_stats_app", - "Client DPI Stats App", labels, nil), - DpiStatsCat: prometheus.NewDesc(ns+"dpi_stats_cat", - "Client DPI Stats Cat", labels, nil), - DpiStatsRxBytes: prometheus.NewDesc(ns+"dpi_stats_receive_bytes_total", - "Client DPI Stats Receive Bytes", labels, nil), - DpiStatsRxPackets: prometheus.NewDesc(ns+"dpi_stats_receive_packets_total", - "Client DPI Stats Receive Packets", labels, nil), - DpiStatsTxBytes: prometheus.NewDesc(ns+"dpi_stats_transmit_bytes_total", - "Client DPI Stats Transmit Bytes", labels, nil), - DpiStatsTxPackets: prometheus.NewDesc(ns+"dpi_stats_transmit_packets_total", - "Client DPI Stats Transmit Packets", labels, nil), - */ + DPITxPackets: prometheus.NewDesc(ns+"dpi_transmit_packets", "Client DPI Transmit Packets", labelDPI, nil), + DPIRxPackets: prometheus.NewDesc(ns+"dpi_receive_packets", "Client DPI Receive Packets", labelDPI, nil), + DPITxBytes: prometheus.NewDesc(ns+"dpi_transmit_bytes", "Client DPI Transmit Bytes", labelDPI, nil), + DPIRxBytes: prometheus.NewDesc(ns+"dpi_receive_bytes", "Client DPI Receive Bytes", labelDPI, nil), + } +} + +func (u *promUnifi) exportClientDPI(r report, s *unifi.DPITable) { + for _, dpi := range s.ByApp { + labelDPI := []string{s.Name, s.MAC, s.SiteName, s.SourceName, + unifi.DPICats.Get(dpi.Cat), unifi.DPIApps.GetApp(dpi.Cat, dpi.App)} + + // log.Println(labelDPI, dpi.Cat, dpi.App, dpi.TxBytes, dpi.RxBytes, dpi.TxPackets, dpi.RxPackets) + r.send([]*metric{ + {u.Client.DPITxPackets, gauge, dpi.TxPackets, labelDPI}, + {u.Client.DPIRxPackets, gauge, dpi.RxPackets, labelDPI}, + {u.Client.DPITxBytes, gauge, dpi.TxBytes, labelDPI}, + {u.Client.DPIRxBytes, gauge, dpi.RxBytes, labelDPI}, + }) } } @@ -130,12 +134,3 @@ func (u *promUnifi) exportClient(r report, c *unifi.Client) { r.send([]*metric{{u.Client.Uptime, gauge, c.Uptime, labelW}}) } - -/* needs more "looking into" -{u.Client.DpiStatsApp, gauge, c.DpiStats.App, labels}, -{u.Client.DpiStatsCat, gauge, c.DpiStats.Cat, labels}, -{u.Client.DpiStatsRxBytes, counter, c.DpiStats.RxBytes, labels}, -{u.Client.DpiStatsRxPackets, counter, c.DpiStats.RxPackets, labels}, -{u.Client.DpiStatsTxBytes, counter, c.DpiStats.TxBytes, labels}, -{u.Client.DpiStatsTxPackets, counter, c.DpiStats.TxPackets, labels}, -*/ diff --git a/pkg/promunifi/collector.go b/pkg/promunifi/collector.go index 49be737a..7fae2ccc 100644 --- a/pkg/promunifi/collector.go +++ b/pkg/promunifi/collector.go @@ -277,6 +277,8 @@ func (u *promUnifi) loopExports(r report) { r.add() r.add() r.add() + r.add() + r.add() go func() { defer r.done() @@ -286,6 +288,30 @@ func (u *promUnifi) loopExports(r report) { } }() + go func() { + defer r.done() + + for _, s := range m.SitesDPI { + u.exportSiteDPI(r, s) + } + }() + + go func() { + defer r.done() + + for _, c := range m.Clients { + u.exportClient(r, c) + } + }() + + go func() { + defer r.done() + + for _, c := range m.ClientsDPI { + u.exportClientDPI(r, c) + } + }() + go func() { defer r.done() @@ -317,12 +343,4 @@ func (u *promUnifi) loopExports(r report) { u.exportUSW(r, d) } }() - - go func() { - defer r.done() - - for _, c := range m.Clients { - u.exportClient(r, c) - } - }() } diff --git a/pkg/promunifi/site.go b/pkg/promunifi/site.go index cdae55c8..c515b8a4 100644 --- a/pkg/promunifi/site.go +++ b/pkg/promunifi/site.go @@ -31,10 +31,15 @@ type site struct { RemoteUserTxBytes *prometheus.Desc RemoteUserRxPackets *prometheus.Desc RemoteUserTxPackets *prometheus.Desc + DPITxPackets *prometheus.Desc + DPIRxPackets *prometheus.Desc + DPITxBytes *prometheus.Desc + DPIRxBytes *prometheus.Desc } func descSite(ns string) *site { labels := []string{"subsystem", "status", "site_name", "source"} + labelDPI := []string{"category", "application", "site_name", "source"} nd := prometheus.NewDesc return &site{ @@ -63,6 +68,24 @@ func descSite(ns string) *site { RemoteUserTxBytes: nd(ns+"remote_user_transmit_bytes_total", "Remote Users Transmit Bytes", labels, nil), RemoteUserRxPackets: nd(ns+"remote_user_receive_packets_total", "Remote Users Receive Packets", labels, nil), RemoteUserTxPackets: nd(ns+"remote_user_transmit_packets_total", "Remote Users Transmit Packets", labels, nil), + DPITxPackets: nd(ns+"dpi_transmit_packets", "Site DPI Transmit Packets", labelDPI, nil), + DPIRxPackets: nd(ns+"dpi_receive_packets", "Site DPI Receive Packets", labelDPI, nil), + DPITxBytes: nd(ns+"dpi_transmit_bytes", "Site DPI Transmit Bytes", labelDPI, nil), + DPIRxBytes: nd(ns+"dpi_receive_bytes", "Site DPI Receive Bytes", labelDPI, nil), + } +} + +func (u *promUnifi) exportSiteDPI(r report, s *unifi.DPITable) { + for _, dpi := range s.ByApp { + labelDPI := []string{unifi.DPICats.Get(dpi.Cat), unifi.DPIApps.GetApp(dpi.Cat, dpi.App), s.SiteName, s.SourceName} + + // log.Println(labelsDPI, dpi.Cat, dpi.App, dpi.TxBytes, dpi.RxBytes, dpi.TxPackets, dpi.RxPackets) + r.send([]*metric{ + {u.Site.DPITxPackets, gauge, dpi.TxPackets, labelDPI}, + {u.Site.DPIRxPackets, gauge, dpi.RxPackets, labelDPI}, + {u.Site.DPITxBytes, gauge, dpi.TxBytes, labelDPI}, + {u.Site.DPIRxBytes, gauge, dpi.RxBytes, labelDPI}, + }) } }