diff --git a/integrations/inputunifi/.metadata.sh b/integrations/inputunifi/.metadata.sh index e98a9718..65f0e677 100755 --- a/integrations/inputunifi/.metadata.sh +++ b/integrations/inputunifi/.metadata.sh @@ -11,7 +11,7 @@ HBREPO="golift/homebrew-mugs" MAINT="David Newhall II " VENDOR="Go Lift" DESC="Polls a UniFi controller and stores metrics in InfluxDB" -GOLANGCI_LINT_ARGS="--enable-all -D gochecknoglobals" +GOLANGCI_LINT_ARGS="--enable-all -D gochecknoglobals -e dupl" # Example must exist at examples/$CONFIG_FILE.example CONFIG_FILE="up.conf" LICENSE="MIT" diff --git a/integrations/inputunifi/Gopkg.lock b/integrations/inputunifi/Gopkg.lock index b005b0a3..3fe3c440 100644 --- a/integrations/inputunifi/Gopkg.lock +++ b/integrations/inputunifi/Gopkg.lock @@ -30,12 +30,12 @@ version = "v1.0.3" [[projects]] - digest = "1:b981b3d72f49bc38f7a9856ec8fab47abeb17fdba1da4a69b0a5b5237dced54c" + digest = "1:356d0d631d02440e90ca29b31496b547d8e28f239eaee033fdf053c3c38d22db" name = "golift.io/unifi" packages = ["."] pruneopts = "UT" - revision = "0ac64b3ef5f855592abb1b95b062b254a184203c" - version = "v3.4.0" + revision = "3f34e772e708a6cb7e838d6babb5928009bc96cc" + version = "v4.0.0" [[projects]] digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96" diff --git a/integrations/inputunifi/unifipoller/clients_influx.go b/integrations/inputunifi/unifipoller/clients_influx.go new file mode 100644 index 00000000..ea9079ca --- /dev/null +++ b/integrations/inputunifi/unifipoller/clients_influx.go @@ -0,0 +1,108 @@ +package unifipoller + +import ( + "time" + + influx "github.com/influxdata/influxdb1-client/v2" + "golift.io/unifi" +) + +// ClientPoints 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) { + 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, + } + fields := map[string]interface{}{ + "anomalies": c.Anomalies, + "ip": c.IP, + "essid": c.Essid, + "bssid": c.Bssid, + "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_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, + } + pt, err := influx.NewPoint("clients", tags, fields, now) + if err != nil { + return nil, err + } + return []*influx.Point{pt}, nil +} diff --git a/integrations/inputunifi/unifipoller/config.go b/integrations/inputunifi/unifipoller/config.go index dcd385f5..dad19c3d 100644 --- a/integrations/inputunifi/unifipoller/config.go +++ b/integrations/inputunifi/unifipoller/config.go @@ -22,12 +22,6 @@ const ( defaultUnifURL = "https://127.0.0.1:8443" ) -// Asset is used to give all devices and clients a common interface. -type Asset interface { - Points() ([]*influx.Point, error) - PointsAt(time.Time) ([]*influx.Point, error) -} - // UnifiPoller contains the application startup data, and auth info for UniFi & Influx. type UnifiPoller struct { ConfigFile string diff --git a/integrations/inputunifi/unifipoller/dumper.go b/integrations/inputunifi/unifipoller/dumper.go index d2cc35a7..bb0fb0d8 100644 --- a/integrations/inputunifi/unifipoller/dumper.go +++ b/integrations/inputunifi/unifipoller/dumper.go @@ -11,7 +11,12 @@ import ( // DumpJSONPayload prints raw json from the UniFi Controller. func (u *UnifiPoller) DumpJSONPayload() (err error) { u.Quiet = true - u.Unifi, err = unifi.NewUnifi(u.UnifiUser, u.UnifiPass, u.UnifiBase, u.VerifySSL) + u.Unifi, err = unifi.NewUnifi(&unifi.Config{ + User: u.UnifiUser, + Pass: u.UnifiPass, + URL: u.UnifiBase, + VerifySSL: u.VerifySSL, + }) if err != nil { return err } diff --git a/integrations/inputunifi/unifipoller/ids_inflix.go b/integrations/inputunifi/unifipoller/ids_inflix.go new file mode 100644 index 00000000..2e78cc28 --- /dev/null +++ b/integrations/inputunifi/unifipoller/ids_inflix.go @@ -0,0 +1,44 @@ +package unifipoller + +import ( + influx "github.com/influxdata/influxdb1-client/v2" + "golift.io/unifi" +) + +// IDSPoints generates intrusion detection datapoints for InfluxDB. +// These points can be passed directly to influx. +func IDSPoints(i *unifi.IDS) ([]*influx.Point, error) { + tags := map[string]string{ + "in_iface": i.InIface, + "event_type": i.EventType, + "proto": i.Proto, + "app_proto": i.AppProto, + "usgip": i.Usgip, + "country_code": i.SrcipGeo.CountryCode, + "country_name": i.SrcipGeo.CountryName, + "region": i.SrcipGeo.Region, + "city": i.SrcipGeo.City, + "postal_code": i.SrcipGeo.PostalCode, + "srcipASN": i.SrcipASN, + "usgipASN": i.UsgipASN, + "alert_category": i.InnerAlertCategory, + "subsystem": i.Subsystem, + "catname": i.Catname, + } + fields := map[string]interface{}{ + "event_type": i.EventType, + "proto": i.Proto, + "app_proto": i.AppProto, + "usgip": i.Usgip, + "country_name": i.SrcipGeo.CountryName, + "city": i.SrcipGeo.City, + "postal_code": i.SrcipGeo.PostalCode, + "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 +} diff --git a/integrations/inputunifi/unifipoller/site_influx.go b/integrations/inputunifi/unifipoller/site_influx.go new file mode 100644 index 00000000..5cd45964 --- /dev/null +++ b/integrations/inputunifi/unifipoller/site_influx.go @@ -0,0 +1,83 @@ +package unifipoller + +import ( + "strings" + "time" + + influx "github.com/influxdata/influxdb1-client/v2" + "golift.io/unifi" +) + +// SitePoints 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 { + 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, + } + 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), + } + pt, err := influx.NewPoint("subsystems", tags, fields, time.Now()) + if err != nil { + return points, err + } + points = append(points, pt) + } + return points, nil +} diff --git a/integrations/inputunifi/unifipoller/start.go b/integrations/inputunifi/unifipoller/start.go index d8332ca2..c6d360cb 100644 --- a/integrations/inputunifi/unifipoller/start.go +++ b/integrations/inputunifi/unifipoller/start.go @@ -121,12 +121,17 @@ func (u *UnifiPoller) GetInfluxDB() (err error) { // GetUnifi returns a UniFi controller interface. func (u *UnifiPoller) GetUnifi() (err error) { // Create an authenticated session to the Unifi Controller. - u.Unifi, err = unifi.NewUnifi(u.UnifiUser, u.UnifiPass, u.UnifiBase, u.VerifySSL) + u.Unifi, err = unifi.NewUnifi(&unifi.Config{ + User: u.UnifiUser, + Pass: u.UnifiPass, + URL: u.UnifiBase, + VerifySSL: u.VerifySSL, + ErrorLog: u.LogErrorf, // Log all errors. + DebugLog: u.LogDebugf, // Log debug messages. + }) if err != nil { return fmt.Errorf("unifi controller: %v", err) } - u.Unifi.ErrorLog = u.LogErrorf // Log all errors. - u.Unifi.DebugLog = u.LogDebugf // Log debug messages. if err := u.CheckSites(); err != nil { return err } diff --git a/integrations/inputunifi/unifipoller/uap_influx.go b/integrations/inputunifi/unifipoller/uap_influx.go new file mode 100644 index 00000000..2a5df71e --- /dev/null +++ b/integrations/inputunifi/unifipoller/uap_influx.go @@ -0,0 +1,276 @@ +package unifipoller + +import ( + "time" + + influx "github.com/influxdata/influxdb1-client/v2" + "golift.io/unifi" +) + +// UAPPoints 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) { + tags := map[string]string{ + "id": u.ID, + "mac": u.Mac, + "device_type": u.Stat.O, + "device_oid": u.Stat.Oid, + "device_ap": u.Stat.Ap.Ap, + "site_id": u.SiteID, + "site_name": u.SiteName, + "name": u.Name, + "adopted": u.Adopted.Txt, + "cfgversion": u.Cfgversion, + "config_network_ip": u.ConfigNetwork.IP, + "config_network_type": u.ConfigNetwork.Type, + "connect_request_ip": u.ConnectRequestIP, + "device_id": u.DeviceID, + "has_eth1": u.HasEth1.Txt, + "inform_ip": u.InformIP, + "isolated": u.Isolated.Txt, + "known_cfgversion": u.KnownCfgversion, + "model": u.Model, + "outdoor_mode_override": u.OutdoorModeOverride, + "serial": u.Serial, + "type": u.Type, + "vwireEnabled": u.VwireEnabled.Txt, + } + fields := map[string]interface{}{ + "ip": u.IP, + "bytes": u.Bytes.Val, + "bytes_d": u.BytesD.Val, + "bytes_r": u.BytesR.Val, + "last_seen": u.LastSeen.Val, + "rx_bytes": u.RxBytes.Val, + "rx_bytes-d": u.RxBytesD.Val, + "tx_bytes": u.TxBytes.Val, + "tx_bytes-d": u.TxBytesD.Val, + "uptime": u.Uptime.Val, + "scanning": u.Scanning.Val, + "spectrum_scanning": u.SpectrumScanning.Val, + "roll_upgrade": u.Rollupgrade.Val, + "state": u.State, + "upgradable": u.Upgradable.Val, + "user-num_sta": u.UserNumSta, + "guest-num_sta": u.GuestNumSta, + "version": u.Version, + "loadavg_1": u.SysStats.Loadavg1.Val, + "loadavg_5": u.SysStats.Loadavg5.Val, + "loadavg_15": u.SysStats.Loadavg15.Val, + "mem_buffer": u.SysStats.MemBuffer.Val, + "mem_total": u.SysStats.MemTotal.Val, + "mem_used": u.SysStats.MemUsed.Val, + "cpu": u.SystemStats.CPU.Val, + "mem": u.SystemStats.Mem.Val, + "system_uptime": u.SystemStats.Uptime.Val, + "stat_guest-wifi0-rx_packets": u.Stat.GuestWifi0RxPackets.Val, + "stat_guest-wifi1-rx_packets": u.Stat.GuestWifi1RxPackets.Val, + "stat_user-wifi1-rx_packets": u.Stat.UserWifi1RxPackets.Val, + "stat_user-wifi0-rx_packets": u.Stat.UserWifi0RxPackets.Val, + "stat_user-rx_packets": u.Stat.UserRxPackets.Val, + "stat_guest-rx_packets": u.Stat.GuestRxPackets.Val, + "stat_wifi0-rx_packets": u.Stat.Wifi0RxPackets.Val, + "stat_wifi1-rx_packets": u.Stat.Wifi1RxPackets.Val, + "stat_rx_packets": u.Stat.RxPackets.Val, + "stat_guest-wifi0-rx_bytes": u.Stat.GuestWifi0RxBytes.Val, + "stat_guest-wifi1-rx_bytes": u.Stat.GuestWifi1RxBytes.Val, + "stat_user-wifi1-rx_bytes": u.Stat.UserWifi1RxBytes.Val, + "stat_user-wifi0-rx_bytes": u.Stat.UserWifi0RxBytes.Val, + "stat_user-rx_bytes": u.Stat.UserRxBytes.Val, + "stat_guest-rx_bytes": u.Stat.GuestRxBytes.Val, + "stat_wifi0-rx_bytes": u.Stat.Wifi0RxBytes.Val, + "stat_wifi1-rx_bytes": u.Stat.Wifi1RxBytes.Val, + "stat_rx_bytes": u.Stat.RxBytes.Val, + "stat_guest-wifi0-rx_errors": u.Stat.GuestWifi0RxErrors.Val, + "stat_guest-wifi1-rx_errors": u.Stat.GuestWifi1RxErrors.Val, + "stat_user-wifi1-rx_errors": u.Stat.UserWifi1RxErrors.Val, + "stat_user-wifi0-rx_errors": u.Stat.UserWifi0RxErrors.Val, + "stat_user-rx_errors": u.Stat.UserRxErrors.Val, + "stat_guest-rx_errors": u.Stat.GuestRxErrors.Val, + "stat_wifi0-rx_errors": u.Stat.Wifi0RxErrors.Val, + "stat_wifi1-rx_errors": u.Stat.Wifi1RxErrors.Val, + "stat_rx_errors": u.Stat.RxErrors.Val, + "stat_guest-wifi0-rx_dropped": u.Stat.GuestWifi0RxDropped.Val, + "stat_guest-wifi1-rx_dropped": u.Stat.GuestWifi1RxDropped.Val, + "stat_user-wifi1-rx_dropped": u.Stat.UserWifi1RxDropped.Val, + "stat_user-wifi0-rx_dropped": u.Stat.UserWifi0RxDropped.Val, + "stat_user-rx_dropped": u.Stat.UserRxDropped.Val, + "stat_guest-rx_dropped": u.Stat.GuestRxDropped.Val, + "stat_wifi0-rx_dropped": u.Stat.Wifi0RxDropped.Val, + "stat_wifi1-rx_dropped": u.Stat.Wifi1RxDropped.Val, + "stat_rx_dropped": u.Stat.RxDropped.Val, + "stat_guest-wifi0-rx_crypts": u.Stat.GuestWifi0RxCrypts.Val, + "stat_guest-wifi1-rx_crypts": u.Stat.GuestWifi1RxCrypts.Val, + "stat_user-wifi1-rx_crypts": u.Stat.UserWifi1RxCrypts.Val, + "stat_user-wifi0-rx_crypts": u.Stat.UserWifi0RxCrypts.Val, + "stat_user-rx_crypts": u.Stat.UserRxCrypts.Val, + "stat_guest-rx_crypts": u.Stat.GuestRxCrypts.Val, + "stat_wifi0-rx_crypts": u.Stat.Wifi0RxCrypts.Val, + "stat_wifi1-rx_crypts": u.Stat.Wifi1RxCrypts.Val, + "stat_rx_crypts": u.Stat.RxCrypts.Val, + "stat_guest-wifi0-rx_frags": u.Stat.GuestWifi0RxFrags.Val, + "stat_guest-wifi1-rx_frags": u.Stat.GuestWifi1RxFrags.Val, + "stat_user-wifi1-rx_frags": u.Stat.UserWifi1RxFrags.Val, + "stat_user-wifi0-rx_frags": u.Stat.UserWifi0RxFrags.Val, + "stat_user-rx_frags": u.Stat.UserRxFrags.Val, + "stat_guest-rx_frags": u.Stat.GuestRxFrags.Val, + "stat_wifi0-rx_frags": u.Stat.Wifi0RxFrags.Val, + "stat_wifi1-rx_frags": u.Stat.Wifi1RxFrags.Val, + "stat_rx_frags": u.Stat.RxFrags.Val, + "stat_guest-wifi0-tx_packets": u.Stat.GuestWifi0TxPackets.Val, + "stat_guest-wifi1-tx_packets": u.Stat.GuestWifi1TxPackets.Val, + "stat_user-wifi1-tx_packets": u.Stat.UserWifi1TxPackets.Val, + "stat_user-wifi0-tx_packets": u.Stat.UserWifi0TxPackets.Val, + "stat_user-tx_packets": u.Stat.UserTxPackets.Val, + "stat_guest-tx_packets": u.Stat.GuestTxPackets.Val, + "stat_wifi0-tx_packets": u.Stat.Wifi0TxPackets.Val, + "stat_wifi1-tx_packets": u.Stat.Wifi1TxPackets.Val, + "stat_tx_packets": u.Stat.TxPackets.Val, + "stat_guest-wifi0-tx_bytes": u.Stat.GuestWifi0TxBytes.Val, + "stat_guest-wifi1-tx_bytes": u.Stat.GuestWifi1TxBytes.Val, + "stat_user-wifi1-tx_bytes": u.Stat.UserWifi1TxBytes.Val, + "stat_user-wifi0-tx_bytes": u.Stat.UserWifi0TxBytes.Val, + "stat_user-tx_bytes": u.Stat.UserTxBytes.Val, + "stat_guest-tx_bytes": u.Stat.GuestTxBytes.Val, + "stat_wifi0-tx_bytes": u.Stat.Wifi0TxBytes.Val, + "stat_wifi1-tx_bytes": u.Stat.Wifi1TxBytes.Val, + "stat_tx_bytes": u.Stat.TxBytes.Val, + "stat_guest-wifi0-tx_errors": u.Stat.GuestWifi0TxErrors.Val, + "stat_guest-wifi1-tx_errors": u.Stat.GuestWifi1TxErrors.Val, + "stat_user-wifi1-tx_errors": u.Stat.UserWifi1TxErrors.Val, + "stat_user-wifi0-tx_errors": u.Stat.UserWifi0TxErrors.Val, + "stat_user-tx_errors": u.Stat.UserTxErrors.Val, + "stat_guest-tx_errors": u.Stat.GuestTxErrors.Val, + "stat_wifi0-tx_errors": u.Stat.Wifi0TxErrors.Val, + "stat_wifi1-tx_errors": u.Stat.Wifi1TxErrors.Val, + "stat_tx_errors": u.Stat.TxErrors.Val, + "stat_guest-wifi0-tx_dropped": u.Stat.GuestWifi0TxDropped.Val, + "stat_guest-wifi1-tx_dropped": u.Stat.GuestWifi1TxDropped.Val, + "stat_user-wifi1-tx_dropped": u.Stat.UserWifi1TxDropped.Val, + "stat_user-wifi0-tx_dropped": u.Stat.UserWifi0TxDropped.Val, + "stat_user-tx_dropped": u.Stat.UserTxDropped.Val, + "stat_guest-tx_dropped": u.Stat.GuestTxDropped.Val, + "stat_wifi0-tx_dropped": u.Stat.Wifi0TxDropped.Val, + "stat_wifi1-tx_dropped": u.Stat.Wifi1TxDropped.Val, + "stat_tx_dropped": u.Stat.TxDropped.Val, + "stat_guest-wifi0-tx_retries": u.Stat.GuestWifi0TxRetries.Val, + "stat_guest-wifi1-tx_retries": u.Stat.GuestWifi1TxRetries.Val, + "stat_user-wifi1-tx_retries": u.Stat.UserWifi1TxRetries.Val, + "stat_user-wifi0-tx_retries": u.Stat.UserWifi0TxRetries.Val, + "stat_user-tx_retries": u.Stat.UserTxRetries.Val, + "stat_guest-tx_retries": u.Stat.GuestTxRetries.Val, + "stat_wifi0-tx_retries": u.Stat.Wifi0TxRetries.Val, + "stat_wifi1-tx_retries": u.Stat.Wifi1TxRetries.Val, + } + pt, err := influx.NewPoint("uap", tags, fields, now) + if err != nil { + return nil, err + } + points := []*influx.Point{pt} + + tags = make(map[string]string) + fields = make(map[string]interface{}) + // Loop each virtual AP (ESSID) and extract data for it + // from radio_tables and radio_table_stats. + for _, s := range u.VapTable { + tags["device_name"] = u.Name + tags["device_id"] = u.ID + tags["device_mac"] = u.Mac + tags["site_name"] = u.SiteName + 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 u.RadioTable { + 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 + 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 + } + + for _, p := range u.RadioTableStats { + 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 + } + + pt, err := influx.NewPoint("uap_vaps", tags, fields, now) + if err != nil { + return points, err + } + points = append(points, pt) + } + return points, nil +} diff --git a/integrations/inputunifi/unifipoller/udm_influx.go b/integrations/inputunifi/unifipoller/udm_influx.go new file mode 100644 index 00000000..c7ad73df --- /dev/null +++ b/integrations/inputunifi/unifipoller/udm_influx.go @@ -0,0 +1,319 @@ +package unifipoller + +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) { + 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, + } + 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, + "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} + 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_priority": u.StpPriority, + "stp_version": u.StpVersion, + } + fields = map[string]interface{}{ + "fw_caps": u.FwCaps.Val, + "guest-num_sta": u.GuestNumSta.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.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, + "system_uptime": u.SystemStats.Uptime.Val, + "stat_bytes": u.Stat.Bytes.Val, + "stat_rx_bytes": u.Stat.RxBytes.Val, + "stat_rx_crypts": u.Stat.RxCrypts.Val, + "stat_rx_dropped": u.Stat.RxDropped.Val, + "stat_rx_errors": u.Stat.RxErrors.Val, + "stat_rx_frags": u.Stat.RxFrags.Val, + "stat_rx_packets": u.Stat.TxPackets.Val, + "stat_tx_bytes": u.Stat.TxBytes.Val, + "stat_tx_dropped": u.Stat.TxDropped.Val, + "stat_tx_errors": u.Stat.TxErrors.Val, + "stat_tx_packets": u.Stat.TxPackets.Val, + "stat_tx_retries": u.Stat.TxRetries.Val, + "uplink_depth": "0", + } + pt, err = influx.NewPoint("usw", tags, fields, now) + if err != nil { + return nil, err + } + points = append(points, pt) + + 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) + } + return points, nil +} diff --git a/integrations/inputunifi/unifipoller/unifi.go b/integrations/inputunifi/unifipoller/unifi.go index 7c80ebaf..a6399d87 100644 --- a/integrations/inputunifi/unifipoller/unifi.go +++ b/integrations/inputunifi/unifipoller/unifi.go @@ -51,7 +51,7 @@ func (u *UnifiPoller) PollController() error { var err error if u.ReAuth { // Some users need to re-auth every interval because the cookie times out. - if err = u.GetUnifi(); err != nil { + if err = u.Login(); err != nil { u.LogError(err, "re-authenticating") } } @@ -167,42 +167,45 @@ func (u *UnifiPoller) ReportMetrics(metrics *Metrics) 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() (errs []error) { - for _, asset := range m.Sites { - errs = append(errs, m.processPoints(asset)) - } - for _, asset := range m.Clients { - errs = append(errs, m.processPoints(asset)) - } - for _, asset := range m.IDSList { - errs = append(errs, m.processPoints(asset)) - } - if m.Devices == nil { - return - } - for _, asset := range m.UAPs { - errs = append(errs, m.processPoints(asset)) - } - for _, asset := range m.USGs { - errs = append(errs, m.processPoints(asset)) - } - for _, asset := range m.USWs { - errs = append(errs, m.processPoints(asset)) - } - return -} - -// processPoints is helper function for ProcessPoints. -func (m *Metrics) processPoints(asset Asset) error { - if asset == nil { +func (m *Metrics) ProcessPoints() []error { + errs := []error{} + processPoints := func(m *Metrics, p []*influx.Point, err error) error { + if err != nil || p == nil { + return err + } + m.BatchPoints.AddPoints(p) return nil } - points, err := asset.PointsAt(m.TS) - if err != nil || points == nil { - return err + + for _, asset := range m.Sites { + pts, err := SitePoints(asset, m.TS) + errs = append(errs, processPoints(m, pts, err)) } - m.BatchPoints.AddPoints(points) - return nil + for _, asset := range m.Clients { + pts, err := ClientPoints(asset, m.TS) + errs = append(errs, processPoints(m, pts, err)) + } + for _, asset := range m.IDSList { + pts, err := IDSPoints(asset) // no m.TS. + errs = append(errs, processPoints(m, pts, err)) + } + + if m.Devices == nil { + return errs + } + for _, asset := range m.UAPs { + pts, err := UAPPoints(asset, m.TS) + errs = append(errs, processPoints(m, pts, err)) + } + for _, asset := range m.USGs { + pts, err := USGPoints(asset, m.TS) + errs = append(errs, processPoints(m, pts, err)) + } + for _, asset := range m.USWs { + pts, err := USWPoints(asset, m.TS) + errs = append(errs, processPoints(m, pts, err)) + } + return errs } // GetFilteredSites returns a list of sites to fetch data for. diff --git a/integrations/inputunifi/unifipoller/usg_influx.go b/integrations/inputunifi/unifipoller/usg_influx.go new file mode 100644 index 00000000..32a4000c --- /dev/null +++ b/integrations/inputunifi/unifipoller/usg_influx.go @@ -0,0 +1,228 @@ +package unifipoller + +import ( + "strings" + "time" + + influx "github.com/influxdata/influxdb1-client/v2" + "golift.io/unifi" +) + +// USGPoints 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) { + 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, + } + 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 { + 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{ + "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 +} diff --git a/integrations/inputunifi/unifipoller/usw_influx.go b/integrations/inputunifi/unifipoller/usw_influx.go new file mode 100644 index 00000000..becd06c6 --- /dev/null +++ b/integrations/inputunifi/unifipoller/usw_influx.go @@ -0,0 +1,145 @@ +package unifipoller + +import ( + "time" + + influx "github.com/influxdata/influxdb1-client/v2" + "golift.io/unifi" +) + +// USWPoints 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) { + 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_priority": u.StpPriority, + "stp_version": u.StpVersion, + } + 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, + "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 { + 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) + } + return points, nil +}