diff --git a/collector/fixtures/e2e-64k-page-output.txt b/collector/fixtures/e2e-64k-page-output.txt index 0bd39b43..c0f5acb2 100644 --- a/collector/fixtures/e2e-64k-page-output.txt +++ b/collector/fixtures/e2e-64k-page-output.txt @@ -2307,31 +2307,39 @@ node_wifi_interface_frequency_hertz{device="wlan0"} 2.412e+09 node_wifi_interface_frequency_hertz{device="wlan1"} 2.412e+09 # HELP node_wifi_station_beacon_loss_total The total number of times a station has detected a beacon loss. # TYPE node_wifi_station_beacon_loss_total counter -node_wifi_station_beacon_loss_total{device="wlan0"} 1 +node_wifi_station_beacon_loss_total{device="wlan0",mac_address="01:02:03:04:05:06"} 2 +node_wifi_station_beacon_loss_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 1 # HELP node_wifi_station_connected_seconds_total The total number of seconds a station has been connected to an access point. # TYPE node_wifi_station_connected_seconds_total counter -node_wifi_station_connected_seconds_total{device="wlan0"} 30 +node_wifi_station_connected_seconds_total{device="wlan0",mac_address="01:02:03:04:05:06"} 60 +node_wifi_station_connected_seconds_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 30 # HELP node_wifi_station_inactive_seconds The number of seconds since any wireless activity has occurred on a station. # TYPE node_wifi_station_inactive_seconds gauge -node_wifi_station_inactive_seconds{device="wlan0"} 0.4 +node_wifi_station_inactive_seconds{device="wlan0",mac_address="01:02:03:04:05:06"} 0.8 +node_wifi_station_inactive_seconds{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 0.4 # HELP node_wifi_station_info Labeled WiFi interface station information as provided by the operating system. # TYPE node_wifi_station_info gauge node_wifi_station_info{bssid="00:11:22:33:44:55",device="wlan0",mode="client",ssid="Example"} 1 # HELP node_wifi_station_receive_bits_per_second The current WiFi receive bitrate of a station, in bits per second. # TYPE node_wifi_station_receive_bits_per_second gauge -node_wifi_station_receive_bits_per_second{device="wlan0"} 1.28e+08 +node_wifi_station_receive_bits_per_second{device="wlan0",mac_address="01:02:03:04:05:06"} 2.56e+08 +node_wifi_station_receive_bits_per_second{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 1.28e+08 # HELP node_wifi_station_signal_dbm The current WiFi signal strength, in decibel-milliwatts (dBm). # TYPE node_wifi_station_signal_dbm gauge -node_wifi_station_signal_dbm{device="wlan0"} -52 +node_wifi_station_signal_dbm{device="wlan0",mac_address="01:02:03:04:05:06"} -26 +node_wifi_station_signal_dbm{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} -52 # HELP node_wifi_station_transmit_bits_per_second The current WiFi transmit bitrate of a station, in bits per second. # TYPE node_wifi_station_transmit_bits_per_second gauge -node_wifi_station_transmit_bits_per_second{device="wlan0"} 1.64e+08 +node_wifi_station_transmit_bits_per_second{device="wlan0",mac_address="01:02:03:04:05:06"} 3.28e+08 +node_wifi_station_transmit_bits_per_second{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 1.64e+08 # HELP node_wifi_station_transmit_failed_total The total number of times a station has failed to send a packet. # TYPE node_wifi_station_transmit_failed_total counter -node_wifi_station_transmit_failed_total{device="wlan0"} 2 +node_wifi_station_transmit_failed_total{device="wlan0",mac_address="01:02:03:04:05:06"} 4 +node_wifi_station_transmit_failed_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 2 # HELP node_wifi_station_transmit_retries_total The total number of times a station has had to retry while sending a packet. # TYPE node_wifi_station_transmit_retries_total counter -node_wifi_station_transmit_retries_total{device="wlan0"} 10 +node_wifi_station_transmit_retries_total{device="wlan0",mac_address="01:02:03:04:05:06"} 20 +node_wifi_station_transmit_retries_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 10 # HELP node_xfs_allocation_btree_compares_total Number of allocation B-tree compares for a filesystem. # TYPE node_xfs_allocation_btree_compares_total counter node_xfs_allocation_btree_compares_total{device="sda1"} 0 diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index dc601e0b..326890f5 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -2307,31 +2307,39 @@ node_wifi_interface_frequency_hertz{device="wlan0"} 2.412e+09 node_wifi_interface_frequency_hertz{device="wlan1"} 2.412e+09 # HELP node_wifi_station_beacon_loss_total The total number of times a station has detected a beacon loss. # TYPE node_wifi_station_beacon_loss_total counter -node_wifi_station_beacon_loss_total{device="wlan0"} 1 +node_wifi_station_beacon_loss_total{device="wlan0",mac_address="01:02:03:04:05:06"} 2 +node_wifi_station_beacon_loss_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 1 # HELP node_wifi_station_connected_seconds_total The total number of seconds a station has been connected to an access point. # TYPE node_wifi_station_connected_seconds_total counter -node_wifi_station_connected_seconds_total{device="wlan0"} 30 +node_wifi_station_connected_seconds_total{device="wlan0",mac_address="01:02:03:04:05:06"} 60 +node_wifi_station_connected_seconds_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 30 # HELP node_wifi_station_inactive_seconds The number of seconds since any wireless activity has occurred on a station. # TYPE node_wifi_station_inactive_seconds gauge -node_wifi_station_inactive_seconds{device="wlan0"} 0.4 +node_wifi_station_inactive_seconds{device="wlan0",mac_address="01:02:03:04:05:06"} 0.8 +node_wifi_station_inactive_seconds{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 0.4 # HELP node_wifi_station_info Labeled WiFi interface station information as provided by the operating system. # TYPE node_wifi_station_info gauge node_wifi_station_info{bssid="00:11:22:33:44:55",device="wlan0",mode="client",ssid="Example"} 1 # HELP node_wifi_station_receive_bits_per_second The current WiFi receive bitrate of a station, in bits per second. # TYPE node_wifi_station_receive_bits_per_second gauge -node_wifi_station_receive_bits_per_second{device="wlan0"} 1.28e+08 +node_wifi_station_receive_bits_per_second{device="wlan0",mac_address="01:02:03:04:05:06"} 2.56e+08 +node_wifi_station_receive_bits_per_second{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 1.28e+08 # HELP node_wifi_station_signal_dbm The current WiFi signal strength, in decibel-milliwatts (dBm). # TYPE node_wifi_station_signal_dbm gauge -node_wifi_station_signal_dbm{device="wlan0"} -52 +node_wifi_station_signal_dbm{device="wlan0",mac_address="01:02:03:04:05:06"} -26 +node_wifi_station_signal_dbm{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} -52 # HELP node_wifi_station_transmit_bits_per_second The current WiFi transmit bitrate of a station, in bits per second. # TYPE node_wifi_station_transmit_bits_per_second gauge -node_wifi_station_transmit_bits_per_second{device="wlan0"} 1.64e+08 +node_wifi_station_transmit_bits_per_second{device="wlan0",mac_address="01:02:03:04:05:06"} 3.28e+08 +node_wifi_station_transmit_bits_per_second{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 1.64e+08 # HELP node_wifi_station_transmit_failed_total The total number of times a station has failed to send a packet. # TYPE node_wifi_station_transmit_failed_total counter -node_wifi_station_transmit_failed_total{device="wlan0"} 2 +node_wifi_station_transmit_failed_total{device="wlan0",mac_address="01:02:03:04:05:06"} 4 +node_wifi_station_transmit_failed_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 2 # HELP node_wifi_station_transmit_retries_total The total number of times a station has had to retry while sending a packet. # TYPE node_wifi_station_transmit_retries_total counter -node_wifi_station_transmit_retries_total{device="wlan0"} 10 +node_wifi_station_transmit_retries_total{device="wlan0",mac_address="01:02:03:04:05:06"} 20 +node_wifi_station_transmit_retries_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 10 # HELP node_xfs_allocation_btree_compares_total Number of allocation B-tree compares for a filesystem. # TYPE node_xfs_allocation_btree_compares_total counter node_xfs_allocation_btree_compares_total{device="sda1"} 0 diff --git a/collector/fixtures/wifi/wlan0/stationinfo.json b/collector/fixtures/wifi/wlan0/stationinfo.json index 84bcb695..8bb0f35c 100644 --- a/collector/fixtures/wifi/wlan0/stationinfo.json +++ b/collector/fixtures/wifi/wlan0/stationinfo.json @@ -1,10 +1,25 @@ -{ - "connected": 30000000000, - "inactive": 400000000, - "receivebitrate": 128000000, - "transmitbitrate": 164000000, - "signal": -52, - "transmitretries": 10, - "transmitfailed": 2, - "beaconloss": 1 -} +[ + { + "hardwareaddr": "qrvM3e7/", + "connected": 30000000000, + "inactive": 400000000, + "receivebitrate": 128000000, + "transmitbitrate": 164000000, + "signal": -52, + "transmitretries": 10, + "transmitfailed": 2, + "beaconloss": 1 + }, + { + "hardwareaddr": "AQIDBAUG", + "connected": 60000000000, + "inactive": 800000000, + "receivebitrate": 256000000, + "transmitbitrate": 328000000, + "signal": -26, + "transmitretries": 20, + "transmitfailed": 4, + "beaconloss": 2 + } +] + diff --git a/collector/wifi_linux.go b/collector/wifi_linux.go index b3a1cf49..c2855a15 100644 --- a/collector/wifi_linux.go +++ b/collector/wifi_linux.go @@ -55,7 +55,7 @@ type wifiStater interface { BSS(ifi *wifi.Interface) (*wifi.BSS, error) Close() error Interfaces() ([]*wifi.Interface, error) - StationInfo(ifi *wifi.Interface) (*wifi.StationInfo, error) + StationInfo(ifi *wifi.Interface) ([]*wifi.StationInfo, error) } // NewWifiCollector returns a new Collector exposing Wifi statistics. @@ -65,14 +65,14 @@ func NewWifiCollector() (Collector, error) { ) var ( - labels = []string{"device"} + labels = []string{"device", "mac_address"} ) return &wifiCollector{ interfaceFrequencyHertz: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "interface_frequency_hertz"), "The current frequency a WiFi interface is operating at, in hertz.", - labels, + []string{"device"}, nil, ), @@ -193,10 +193,12 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error { ifi.Name, err) } - info, err := stat.StationInfo(ifi) + stations, err := stat.StationInfo(ifi) switch { case err == nil: - c.updateStationStats(ch, ifi.Name, info) + for _, station := range stations { + c.updateStationStats(ch, ifi.Name, station) + } case os.IsNotExist(err): log.Debugf("station information not found for wifi device %q", ifi.Name) default: @@ -227,6 +229,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.CounterValue, info.Connected.Seconds(), device, + info.HardwareAddr.String(), ) ch <- prometheus.MustNewConstMetric( @@ -234,6 +237,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.GaugeValue, info.Inactive.Seconds(), device, + info.HardwareAddr.String(), ) ch <- prometheus.MustNewConstMetric( @@ -241,6 +245,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.GaugeValue, float64(info.ReceiveBitrate), device, + info.HardwareAddr.String(), ) ch <- prometheus.MustNewConstMetric( @@ -248,6 +253,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.GaugeValue, float64(info.TransmitBitrate), device, + info.HardwareAddr.String(), ) ch <- prometheus.MustNewConstMetric( @@ -255,6 +261,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.GaugeValue, float64(info.Signal), device, + info.HardwareAddr.String(), ) ch <- prometheus.MustNewConstMetric( @@ -262,6 +269,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.CounterValue, float64(info.TransmitRetries), device, + info.HardwareAddr.String(), ) ch <- prometheus.MustNewConstMetric( @@ -269,6 +277,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.CounterValue, float64(info.TransmitFailed), device, + info.HardwareAddr.String(), ) ch <- prometheus.MustNewConstMetric( @@ -276,6 +285,7 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s prometheus.CounterValue, float64(info.BeaconLoss), device, + info.HardwareAddr.String(), ) } @@ -346,13 +356,13 @@ func (s *mockWifiStater) Interfaces() ([]*wifi.Interface, error) { return ifis, nil } -func (s *mockWifiStater) StationInfo(ifi *wifi.Interface) (*wifi.StationInfo, error) { +func (s *mockWifiStater) StationInfo(ifi *wifi.Interface) ([]*wifi.StationInfo, error) { p := filepath.Join(ifi.Name, "stationinfo.json") - var info wifi.StationInfo - if err := s.unmarshalJSONFile(p, &info); err != nil { + var stations []*wifi.StationInfo + if err := s.unmarshalJSONFile(p, &stations); err != nil { return nil, err } - return &info, nil + return stations, nil } diff --git a/vendor/github.com/mdlayher/wifi/client.go b/vendor/github.com/mdlayher/wifi/client.go index 735843df..ff79a542 100644 --- a/vendor/github.com/mdlayher/wifi/client.go +++ b/vendor/github.com/mdlayher/wifi/client.go @@ -45,8 +45,8 @@ func (c *Client) BSS(ifi *Interface) (*BSS, error) { return c.c.BSS(ifi) } -// StationInfo retrieves station statistics about a WiFi interface. -func (c *Client) StationInfo(ifi *Interface) (*StationInfo, error) { +// StationInfo retrieves all station statistics about a WiFi interface. +func (c *Client) StationInfo(ifi *Interface) ([]*StationInfo, error) { return c.c.StationInfo(ifi) } @@ -55,5 +55,5 @@ type osClient interface { Close() error Interfaces() ([]*Interface, error) BSS(ifi *Interface) (*BSS, error) - StationInfo(ifi *Interface) (*StationInfo, error) + StationInfo(ifi *Interface) ([]*StationInfo, error) } diff --git a/vendor/github.com/mdlayher/wifi/client_linux.go b/vendor/github.com/mdlayher/wifi/client_linux.go index 5a4055b6..4edb9bc9 100644 --- a/vendor/github.com/mdlayher/wifi/client_linux.go +++ b/vendor/github.com/mdlayher/wifi/client_linux.go @@ -18,7 +18,6 @@ import ( // Errors which may occur when interacting with generic netlink. var ( - errMultipleMessages = errors.New("expected only one generic netlink message") errInvalidCommand = errors.New("invalid generic netlink response command") errInvalidFamilyVersion = errors.New("invalid generic netlink response family version") ) @@ -120,9 +119,9 @@ func (c *client) BSS(ifi *Interface) (*BSS, error) { return parseBSS(msgs) } -// StationInfo requests that nl80211 return station info for the specified +// StationInfo requests that nl80211 return all station info for the specified // Interface. -func (c *client) StationInfo(ifi *Interface) (*StationInfo, error) { +func (c *client) StationInfo(ifi *Interface) ([]*StationInfo, error) { b, err := netlink.MarshalAttributes(ifi.idAttrs()) if err != nil { return nil, err @@ -147,22 +146,25 @@ func (c *client) StationInfo(ifi *Interface) (*StationInfo, error) { return nil, err } - switch len(msgs) { - case 0: + if len(msgs) == 0 { return nil, os.ErrNotExist - case 1: - break - default: - return nil, errMultipleMessages } - if err := c.checkMessages(msgs, nl80211.CmdNewStation); err != nil { - return nil, err + stations := make([]*StationInfo, len(msgs)) + for i := range msgs { + if err := c.checkMessages(msgs, nl80211.CmdNewStation); err != nil { + return nil, err + } + + if stations[i], err = parseStationInfo(msgs[i].Data); err != nil { + return nil, err + } } - return parseStationInfo(msgs[0].Data) + return stations, nil } + // checkMessages verifies that response messages from generic netlink contain // the command and family version we expect. func (c *client) checkMessages(msgs []genetlink.Message, command uint8) error { @@ -323,25 +325,32 @@ func parseStationInfo(b []byte) (*StationInfo, error) { return nil, err } + var info StationInfo for _, a := range attrs { - // The other attributes that are returned here appear to indicate the - // interface index and MAC address, which is information we already - // possess. No need to parse them for now. - if a.Type != nl80211.AttrStaInfo { - continue - } - nattrs, err := netlink.UnmarshalAttributes(a.Data) - if err != nil { - return nil, err - } + switch a.Type { + case nl80211.AttrMac: + info.HardwareAddr = net.HardwareAddr(a.Data) - var info StationInfo - if err := (&info).parseAttributes(nattrs); err != nil { - return nil, err - } + case nl80211.AttrStaInfo: + nattrs, err := netlink.UnmarshalAttributes(a.Data) + if err != nil { + return nil, err + } - return &info, nil + if err := (&info).parseAttributes(nattrs); err != nil { + return nil, err + } + + // nl80211.AttrStaInfo is last attibute we are interested in + return &info, nil + + default: + // The other attributes that are returned here appear + // nl80211.AttrIfindex, nl80211.AttrGeneration + // No need to parse them for now. + continue + } } // No station info found diff --git a/vendor/github.com/mdlayher/wifi/client_others.go b/vendor/github.com/mdlayher/wifi/client_others.go index 1848b88d..0cbc728c 100644 --- a/vendor/github.com/mdlayher/wifi/client_others.go +++ b/vendor/github.com/mdlayher/wifi/client_others.go @@ -28,6 +28,6 @@ func (c *client) BSS(ifi *Interface) (*BSS, error) { } // StationInfo always returns an error. -func (c *client) StationInfo(ifi *Interface) (*StationInfo, error) { +func (c *client) StationInfo(ifi *Interface) ([]*StationInfo, error) { return nil, errUnimplemented } diff --git a/vendor/github.com/mdlayher/wifi/wifi.go b/vendor/github.com/mdlayher/wifi/wifi.go index e16bcc4d..83aed178 100644 --- a/vendor/github.com/mdlayher/wifi/wifi.go +++ b/vendor/github.com/mdlayher/wifi/wifi.go @@ -128,6 +128,9 @@ type Interface struct { // StationInfo contains statistics about a WiFi interface operating in // station mode. type StationInfo struct { + // The hardware address of the station. + HardwareAddr net.HardwareAddr + // The time since the station last connected. Connected time.Duration diff --git a/vendor/vendor.json b/vendor/vendor.json index 983a3788..8dbff89d 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -103,10 +103,10 @@ "revisionTime": "2017-12-14T18:12:53Z" }, { - "checksumSHA1": "6HM95OVqE3M27obRphrlXgXIHNw=", + "checksumSHA1": "Y7cjrOeOvA/ic+B8WCp2JyLEuvs=", "path": "github.com/mdlayher/wifi", - "revision": "ebeb58da4bc660b4882176fedcd10015f44af89c", - "revisionTime": "2018-06-01T12:43:32Z" + "revision": "9a2549315201616119128afe421d1601ef3506f9", + "revisionTime": "2018-06-15T12:49:15Z" }, { "checksumSHA1": "VzutdH69PUqRqhrDVv6F91ebQd4=",