Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions collector/fixtures/e2e-64k-page-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3376,6 +3376,46 @@ node_wifi_station_transmit_failed_total{device="wlan0",mac_address="aa:bb:cc:dd:
# TYPE node_wifi_station_transmit_retries_total counter
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_wifi_survey_channel_time_active_seconds The time the radio spent on the channel while it was active in seconds.
# TYPE node_wifi_survey_channel_time_active_seconds counter
node_wifi_survey_channel_time_active_seconds{device="wlan0",frequency="2412"} 80
node_wifi_survey_channel_time_active_seconds{device="wlan0",frequency="2437"} 40
# HELP node_wifi_survey_channel_time_bss_rx_seconds The time the radio spent on the channel receiving data from a BSS in seconds.
# TYPE node_wifi_survey_channel_time_bss_rx_seconds counter
node_wifi_survey_channel_time_bss_rx_seconds{device="wlan0",frequency="2412"} 15
node_wifi_survey_channel_time_bss_rx_seconds{device="wlan0",frequency="2437"} 8
# HELP node_wifi_survey_channel_time_busy_seconds The time the radio spent on the channel while it was busy in seconds.
# TYPE node_wifi_survey_channel_time_busy_seconds counter
node_wifi_survey_channel_time_busy_seconds{device="wlan0",frequency="2412"} 30
node_wifi_survey_channel_time_busy_seconds{device="wlan0",frequency="2437"} 15
# HELP node_wifi_survey_channel_time_ext_busy_seconds The time the radio spent on the channel while it was busy with external traffic in seconds.
# TYPE node_wifi_survey_channel_time_ext_busy_seconds counter
node_wifi_survey_channel_time_ext_busy_seconds{device="wlan0",frequency="2412"} 5
node_wifi_survey_channel_time_ext_busy_seconds{device="wlan0",frequency="2437"} 2
# HELP node_wifi_survey_channel_time_rx_seconds The time the radio spent on the channel receiving data in seconds.
# TYPE node_wifi_survey_channel_time_rx_seconds counter
node_wifi_survey_channel_time_rx_seconds{device="wlan0",frequency="2412"} 20
node_wifi_survey_channel_time_rx_seconds{device="wlan0",frequency="2437"} 10
# HELP node_wifi_survey_channel_time_scan_seconds The time the radio spent on the channel while it was scanning in seconds.
# TYPE node_wifi_survey_channel_time_scan_seconds counter
node_wifi_survey_channel_time_scan_seconds{device="wlan0",frequency="2412"} 2
node_wifi_survey_channel_time_scan_seconds{device="wlan0",frequency="2437"} 1
# HELP node_wifi_survey_channel_time_seconds The time the radio spent on the channel in seconds.
# TYPE node_wifi_survey_channel_time_seconds counter
node_wifi_survey_channel_time_seconds{device="wlan0",frequency="2412"} 120
node_wifi_survey_channel_time_seconds{device="wlan0",frequency="2437"} 60
# HELP node_wifi_survey_channel_time_tx_seconds The time the radio spent on the channel transmitting data in seconds.
# TYPE node_wifi_survey_channel_time_tx_seconds counter
node_wifi_survey_channel_time_tx_seconds{device="wlan0",frequency="2412"} 10
node_wifi_survey_channel_time_tx_seconds{device="wlan0",frequency="2437"} 5
# HELP node_wifi_survey_in_use Indicates if the channel is currently in use (1 for in use, 0 for not in use).
# TYPE node_wifi_survey_in_use gauge
node_wifi_survey_in_use{device="wlan0",frequency="2412"} 1
node_wifi_survey_in_use{device="wlan0",frequency="2437"} 0
# HELP node_wifi_survey_noise_dbm The noise level in decibel-milliwatts (dBm).
# TYPE node_wifi_survey_noise_dbm gauge
node_wifi_survey_noise_dbm{device="wlan0",frequency="2412"} -95
node_wifi_survey_noise_dbm{device="wlan0",frequency="2437"} -92
# HELP node_xfrm_acquire_error_packets_total State hasn’t been fully acquired before use
# TYPE node_xfrm_acquire_error_packets_total counter
node_xfrm_acquire_error_packets_total 24532
Expand Down
40 changes: 40 additions & 0 deletions collector/fixtures/e2e-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3398,6 +3398,46 @@ node_wifi_station_transmit_failed_total{device="wlan0",mac_address="aa:bb:cc:dd:
# TYPE node_wifi_station_transmit_retries_total counter
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_wifi_survey_channel_time_active_seconds The time the radio spent on the channel while it was active in seconds.
# TYPE node_wifi_survey_channel_time_active_seconds counter
node_wifi_survey_channel_time_active_seconds{device="wlan0",frequency="2412"} 80
node_wifi_survey_channel_time_active_seconds{device="wlan0",frequency="2437"} 40
# HELP node_wifi_survey_channel_time_bss_rx_seconds The time the radio spent on the channel receiving data from a BSS in seconds.
# TYPE node_wifi_survey_channel_time_bss_rx_seconds counter
node_wifi_survey_channel_time_bss_rx_seconds{device="wlan0",frequency="2412"} 15
node_wifi_survey_channel_time_bss_rx_seconds{device="wlan0",frequency="2437"} 8
# HELP node_wifi_survey_channel_time_busy_seconds The time the radio spent on the channel while it was busy in seconds.
# TYPE node_wifi_survey_channel_time_busy_seconds counter
node_wifi_survey_channel_time_busy_seconds{device="wlan0",frequency="2412"} 30
node_wifi_survey_channel_time_busy_seconds{device="wlan0",frequency="2437"} 15
# HELP node_wifi_survey_channel_time_ext_busy_seconds The time the radio spent on the channel while it was busy with external traffic in seconds.
# TYPE node_wifi_survey_channel_time_ext_busy_seconds counter
node_wifi_survey_channel_time_ext_busy_seconds{device="wlan0",frequency="2412"} 5
node_wifi_survey_channel_time_ext_busy_seconds{device="wlan0",frequency="2437"} 2
# HELP node_wifi_survey_channel_time_rx_seconds The time the radio spent on the channel receiving data in seconds.
# TYPE node_wifi_survey_channel_time_rx_seconds counter
node_wifi_survey_channel_time_rx_seconds{device="wlan0",frequency="2412"} 20
node_wifi_survey_channel_time_rx_seconds{device="wlan0",frequency="2437"} 10
# HELP node_wifi_survey_channel_time_scan_seconds The time the radio spent on the channel while it was scanning in seconds.
# TYPE node_wifi_survey_channel_time_scan_seconds counter
node_wifi_survey_channel_time_scan_seconds{device="wlan0",frequency="2412"} 2
node_wifi_survey_channel_time_scan_seconds{device="wlan0",frequency="2437"} 1
# HELP node_wifi_survey_channel_time_seconds The time the radio spent on the channel in seconds.
# TYPE node_wifi_survey_channel_time_seconds counter
node_wifi_survey_channel_time_seconds{device="wlan0",frequency="2412"} 120
node_wifi_survey_channel_time_seconds{device="wlan0",frequency="2437"} 60
# HELP node_wifi_survey_channel_time_tx_seconds The time the radio spent on the channel transmitting data in seconds.
# TYPE node_wifi_survey_channel_time_tx_seconds counter
node_wifi_survey_channel_time_tx_seconds{device="wlan0",frequency="2412"} 10
node_wifi_survey_channel_time_tx_seconds{device="wlan0",frequency="2437"} 5
# HELP node_wifi_survey_in_use Indicates if the channel is currently in use (1 for in use, 0 for not in use).
# TYPE node_wifi_survey_in_use gauge
node_wifi_survey_in_use{device="wlan0",frequency="2412"} 1
node_wifi_survey_in_use{device="wlan0",frequency="2437"} 0
# HELP node_wifi_survey_noise_dbm The noise level in decibel-milliwatts (dBm).
# TYPE node_wifi_survey_noise_dbm gauge
node_wifi_survey_noise_dbm{device="wlan0",frequency="2412"} -95
node_wifi_survey_noise_dbm{device="wlan0",frequency="2437"} -92
# HELP node_xfrm_acquire_error_packets_total State hasn’t been fully acquired before use
# TYPE node_xfrm_acquire_error_packets_total counter
node_xfrm_acquire_error_packets_total 24532
Expand Down
30 changes: 30 additions & 0 deletions collector/fixtures/wifi/wlan0/surveyinfo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
{
"interfaceindex": 3,
"frequency": 2412,
"noise": -95,
"channeltime": 120000000000,
"channeltimeactive": 80000000000,
"channeltimebusy": 30000000000,
"channeltimeextbusy": 5000000000,
"channeltimebssrx": 15000000000,
"channeltimerx": 20000000000,
"channeltimetx": 10000000000,
"channeltimescan": 2000000000,
"inuse": true
},
{
"interfaceindex": 3,
"frequency": 2437,
"noise": -92,
"channeltime": 60000000000,
"channeltimeactive": 40000000000,
"channeltimebusy": 15000000000,
"channeltimeextbusy": 2000000000,
"channeltimebssrx": 8000000000,
"channeltimerx": 10000000000,
"channeltimetx": 5000000000,
"channeltimescan": 1000000000,
"inuse": false
}
]
195 changes: 195 additions & 0 deletions collector/wifi_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ type wifiCollector struct {
stationTransmitFailedTotal *prometheus.Desc
stationBeaconLossTotal *prometheus.Desc

surveyNoiseDBM *prometheus.Desc
surveyChannelTimeSeconds *prometheus.Desc
surveyChannelTimeActiveSeconds *prometheus.Desc
surveyChannelTimeBusySeconds *prometheus.Desc
surveyChannelTimeExtBusySeconds *prometheus.Desc
surveyChannelTimeBssRxSeconds *prometheus.Desc
surveyChannelTimeRxSeconds *prometheus.Desc
surveyChannelTimeTxSeconds *prometheus.Desc
surveyChannelTimeScanSeconds *prometheus.Desc
surveyInUse *prometheus.Desc

logger *slog.Logger
}

Expand All @@ -63,6 +74,7 @@ type wifiStater interface {
Close() error
Interfaces() ([]*wifi.Interface, error)
StationInfo(ifi *wifi.Interface) ([]*wifi.StationInfo, error)
SurveyInfo(ifi *wifi.Interface) ([]*wifi.SurveyInfo, error)
}

// NewWifiCollector returns a new Collector exposing Wifi statistics.
Expand Down Expand Up @@ -159,6 +171,77 @@ func NewWifiCollector(logger *slog.Logger) (Collector, error) {
labels,
nil,
),

surveyNoiseDBM: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_noise_dbm"),
"The noise level in decibel-milliwatts (dBm).",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeSeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_seconds"),
"The time the radio spent on the channel in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeActiveSeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_active_seconds"),
"The time the radio spent on the channel while it was active in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeBusySeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_busy_seconds"),
"The time the radio spent on the channel while it was busy in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeExtBusySeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_ext_busy_seconds"),
"The time the radio spent on the channel while it was busy with external traffic in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeBssRxSeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_bss_rx_seconds"),
"The time the radio spent on the channel receiving data from a BSS in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeRxSeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_rx_seconds"),
"The time the radio spent on the channel receiving data in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeTxSeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_tx_seconds"),
"The time the radio spent on the channel transmitting data in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyChannelTimeScanSeconds: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_channel_time_scan_seconds"),
"The time the radio spent on the channel while it was scanning in seconds.",
[]string{"device", "frequency_mhz"},
nil,
),

surveyInUse: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "survey_in_use"),
"Indicates if the channel is currently in use (1 for in use, 0 for not in use).",
[]string{"device", "frequency_mhz"},
nil,
),

logger: logger,
}, nil
}
Expand Down Expand Up @@ -227,6 +310,19 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error {
return fmt.Errorf("failed to retrieve station info for device %q: %v",
ifi.Name, err)
}

surveys, err := stat.SurveyInfo(ifi)
switch {
case err == nil:
for _, survey := range surveys {
c.updateSurveyStats(ch, ifi.Name, survey)
}
case errors.Is(err, os.ErrNotExist):
c.logger.Debug("survey information not found for wifi device", "name", ifi.Name)
default:
return fmt.Errorf("failed to retrieve survey info for device %q: %v",
ifi.Name, err)
}
}

return nil
Expand Down Expand Up @@ -327,6 +423,94 @@ func (c *wifiCollector) updateStationStats(ch chan<- prometheus.Metric, device s
)
}

func (c *wifiCollector) updateSurveyStats(ch chan<- prometheus.Metric, device string, info *wifi.SurveyInfo) {
frequencyMHz := fmt.Sprintf("%d", info.Frequency)

ch <- prometheus.MustNewConstMetric(
c.surveyNoiseDBM,
prometheus.GaugeValue,
float64(info.Noise),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeSeconds,
prometheus.CounterValue,
info.ChannelTime.Seconds(),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeActiveSeconds,
prometheus.CounterValue,
info.ChannelTimeActive.Seconds(),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeBusySeconds,
prometheus.CounterValue,
info.ChannelTimeBusy.Seconds(),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeExtBusySeconds,
prometheus.CounterValue,
info.ChannelTimeExtBusy.Seconds(),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeBssRxSeconds,
prometheus.CounterValue,
info.ChannelTimeBssRx.Seconds(),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeRxSeconds,
prometheus.CounterValue,
info.ChannelTimeRx.Seconds(),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeTxSeconds,
prometheus.CounterValue,
info.ChannelTimeTx.Seconds(),
device,
frequencyMHz,
)

ch <- prometheus.MustNewConstMetric(
c.surveyChannelTimeScanSeconds,
prometheus.CounterValue,
info.ChannelTimeScan.Seconds(),
device,
frequencyMHz,
)

var inUseValue float64
if info.InUse {
inUseValue = 1
}
ch <- prometheus.MustNewConstMetric(
c.surveyInUse,
prometheus.GaugeValue,
inUseValue,
device,
frequencyMHz,
)
}

func mHzToHz(mHz int) float64 {
return float64(mHz) * 1000 * 1000
}
Expand Down Expand Up @@ -404,3 +588,14 @@ func (s *mockWifiStater) StationInfo(ifi *wifi.Interface) ([]*wifi.StationInfo,

return stations, nil
}

func (s *mockWifiStater) SurveyInfo(ifi *wifi.Interface) ([]*wifi.SurveyInfo, error) {
p := filepath.Join(ifi.Name, "surveyinfo.json")

var surveyInfo []*wifi.SurveyInfo
if err := s.unmarshalJSONFile(p, &surveyInfo); err != nil {
return nil, err
}

return surveyInfo, nil
}