Skip to content

Commit d91ea65

Browse files
authored
fix(go.d/ap): handle unknown values in station statistics gracefully (netdata#21461)
1 parent 176121b commit d91ea65

File tree

3 files changed

+124
-72
lines changed

3 files changed

+124
-72
lines changed

src/go/plugin/go.d/collector/ap/collect.go

Lines changed: 79 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ type iwInterface struct {
2222
}
2323

2424
type stationStats struct {
25-
clients int64
26-
rxBytes int64
27-
rxPackets int64
28-
txBytes int64
29-
txPackets int64
30-
txRetries int64
31-
txFailed int64
32-
signalAvg int64
33-
txBitrate float64
34-
rxBitrate float64
25+
clients *int64
26+
rxBytes *int64
27+
rxPackets *int64
28+
txBytes *int64
29+
txPackets *int64
30+
txRetries *int64
31+
txFailed *int64
32+
signalAvg *int64
33+
txBitrate *float64
34+
rxBitrate *float64
3535
}
3636

3737
func (c *Collector) collect() (map[string]int64, error) {
@@ -59,10 +59,7 @@ func (c *Collector) collect() (map[string]int64, error) {
5959
return nil, fmt.Errorf("getting station statistics for %s: %v", iface, err)
6060
}
6161

62-
stats, err := parseIwStationStatistics(bs)
63-
if err != nil {
64-
return nil, fmt.Errorf("parsing station statistics for %s: %v", iface, err)
65-
}
62+
stats := parseIwStationStatistics(bs)
6663

6764
key := fmt.Sprintf("%s-%s", iface.name, iface.ssid)
6865

@@ -75,18 +72,39 @@ func (c *Collector) collect() (map[string]int64, error) {
7572

7673
px := fmt.Sprintf("ap_%s_%s_", iface.name, iface.ssid)
7774

78-
mx[px+"clients"] = stats.clients
79-
mx[px+"bw_received"] = stats.rxBytes
80-
mx[px+"bw_sent"] = stats.txBytes
81-
mx[px+"packets_received"] = stats.rxPackets
82-
mx[px+"packets_sent"] = stats.txPackets
83-
mx[px+"issues_retries"] = stats.txRetries
84-
mx[px+"issues_failures"] = stats.txFailed
85-
mx[px+"average_signal"], mx[px+"bitrate_receive"], mx[px+"bitrate_transmit"] = 0, 0, 0
86-
if clients := float64(stats.clients); clients > 0 {
87-
mx[px+"average_signal"] = int64(float64(stats.signalAvg) / clients * precision)
88-
mx[px+"bitrate_receive"] = int64(stats.rxBitrate / clients * precision)
89-
mx[px+"bitrate_transmit"] = int64(stats.txBitrate / clients * precision)
75+
if stats.clients != nil {
76+
mx[px+"clients"] = *stats.clients
77+
}
78+
if stats.rxBytes != nil {
79+
mx[px+"bw_received"] = *stats.rxBytes
80+
}
81+
if stats.txBytes != nil {
82+
mx[px+"bw_sent"] = *stats.txBytes
83+
}
84+
if stats.rxPackets != nil {
85+
mx[px+"packets_received"] = *stats.rxPackets
86+
}
87+
if stats.txPackets != nil {
88+
mx[px+"packets_sent"] = *stats.txPackets
89+
}
90+
if stats.txRetries != nil {
91+
mx[px+"issues_retries"] = *stats.txRetries
92+
}
93+
if stats.txFailed != nil {
94+
mx[px+"issues_failures"] = *stats.txFailed
95+
}
96+
97+
if stats.clients != nil && *stats.clients > 0 {
98+
clients := float64(*stats.clients)
99+
if stats.signalAvg != nil {
100+
mx[px+"average_signal"] = int64(float64(*stats.signalAvg) / clients * precision)
101+
}
102+
if stats.rxBitrate != nil {
103+
mx[px+"bitrate_receive"] = int64(*stats.rxBitrate / clients * precision)
104+
}
105+
if stats.txBitrate != nil {
106+
mx[px+"bitrate_transmit"] = int64(*stats.txBitrate / clients * precision)
107+
}
90108
}
91109
}
92110

@@ -146,66 +164,57 @@ func parseIwDevices(resp []byte) ([]*iwInterface, error) {
146164
return apIfaces, nil
147165
}
148166

149-
func parseIwStationStatistics(resp []byte) (*stationStats, error) {
167+
func parseIwStationStatistics(resp []byte) *stationStats {
150168
var stats stationStats
151169

152170
sc := bufio.NewScanner(bytes.NewReader(resp))
153171

154172
for sc.Scan() {
155173
line := strings.TrimSpace(sc.Text())
156174

157-
var v float64
158-
var err error
159-
160175
switch {
161176
case strings.HasPrefix(line, "Station"):
162-
stats.clients++
177+
stats.addInt64(&stats.clients, 1)
163178
case strings.HasPrefix(line, "rx bytes:"):
164-
if v, err = get3rdValue(line); err == nil {
165-
stats.rxBytes += int64(v)
179+
if v, err := get3rdValue(line); err == nil {
180+
stats.addInt64(&stats.rxBytes, int64(v))
166181
}
167182
case strings.HasPrefix(line, "rx packets:"):
168-
if v, err = get3rdValue(line); err == nil {
169-
stats.rxPackets += int64(v)
183+
if v, err := get3rdValue(line); err == nil {
184+
stats.addInt64(&stats.rxPackets, int64(v))
170185
}
171186
case strings.HasPrefix(line, "tx bytes:"):
172-
if v, err = get3rdValue(line); err == nil {
173-
stats.txBytes += int64(v)
187+
if v, err := get3rdValue(line); err == nil {
188+
stats.addInt64(&stats.txBytes, int64(v))
174189
}
175190
case strings.HasPrefix(line, "tx packets:"):
176-
if v, err = get3rdValue(line); err == nil {
177-
stats.txPackets += int64(v)
191+
if v, err := get3rdValue(line); err == nil {
192+
stats.addInt64(&stats.txPackets, int64(v))
178193
}
179194
case strings.HasPrefix(line, "tx retries:"):
180-
if v, err = get3rdValue(line); err == nil {
181-
stats.txRetries += int64(v)
195+
if v, err := get3rdValue(line); err == nil {
196+
stats.addInt64(&stats.txRetries, int64(v))
182197
}
183198
case strings.HasPrefix(line, "tx failed:"):
184-
if v, err = get3rdValue(line); err == nil {
185-
stats.txFailed += int64(v)
199+
if v, err := get3rdValue(line); err == nil {
200+
stats.addInt64(&stats.txFailed, int64(v))
186201
}
187202
case strings.HasPrefix(line, "signal avg:"):
188-
if v, err = get3rdValue(line); err == nil {
189-
stats.signalAvg += int64(v)
203+
if v, err := get3rdValue(line); err == nil {
204+
stats.addInt64(&stats.signalAvg, int64(v))
190205
}
191206
case strings.HasPrefix(line, "tx bitrate:"):
192-
if v, err = get3rdValue(line); err == nil {
193-
stats.txBitrate += v
207+
if v, err := get3rdValue(line); err == nil {
208+
stats.addFloat64(&stats.txBitrate, v)
194209
}
195210
case strings.HasPrefix(line, "rx bitrate:"):
196-
if v, err = get3rdValue(line); err == nil {
197-
stats.rxBitrate += v
211+
if v, err := get3rdValue(line); err == nil {
212+
stats.addFloat64(&stats.rxBitrate, v)
198213
}
199-
default:
200-
continue
201-
}
202-
203-
if err != nil {
204-
return nil, fmt.Errorf("parsing line '%s': %v", line, err)
205214
}
206215
}
207216

208-
return &stats, nil
217+
return &stats
209218
}
210219

211220
func get3rdValue(line string) (float64, error) {
@@ -221,3 +230,17 @@ func get3rdValue(line string) (float64, error) {
221230
}
222231
return strconv.ParseFloat(v, 64)
223232
}
233+
234+
func (s *stationStats) addInt64(dst **int64, v int64) {
235+
if *dst == nil {
236+
*dst = new(int64)
237+
}
238+
**dst += v
239+
}
240+
241+
func (s *stationStats) addFloat64(dst **float64, v float64) {
242+
if *dst == nil {
243+
*dst = new(float64)
244+
}
245+
**dst += v
246+
}

src/go/plugin/go.d/collector/ap/collector_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -166,26 +166,26 @@ func TestCollector_Collect(t *testing.T) {
166166
prepareMock: prepareMockOk,
167167
wantCharts: len(apChartsTmpl) * 2,
168168
wantMetrics: map[string]int64{
169-
"ap_wlp1s0_testing_average_signal": -34000,
170-
"ap_wlp1s0_testing_bitrate_receive": 65500,
171-
"ap_wlp1s0_testing_bitrate_transmit": 65000,
172-
"ap_wlp1s0_testing_bw_received": 95117,
173-
"ap_wlp1s0_testing_bw_sent": 8270,
174-
"ap_wlp1s0_testing_clients": 2,
169+
"ap_wlp1s0_testing_average_signal": -50666,
170+
"ap_wlp1s0_testing_bitrate_receive": 49400,
171+
"ap_wlp1s0_testing_bitrate_transmit": 43333,
172+
"ap_wlp1s0_testing_bw_received": 101822,
173+
"ap_wlp1s0_testing_bw_sent": 9284,
174+
"ap_wlp1s0_testing_clients": 3,
175175
"ap_wlp1s0_testing_issues_failures": 1,
176176
"ap_wlp1s0_testing_issues_retries": 1,
177-
"ap_wlp1s0_testing_packets_received": 2531,
178-
"ap_wlp1s0_testing_packets_sent": 38,
179-
"ap_wlp1s1_testing_average_signal": -34000,
180-
"ap_wlp1s1_testing_bitrate_receive": 65500,
181-
"ap_wlp1s1_testing_bitrate_transmit": 65000,
182-
"ap_wlp1s1_testing_bw_received": 95117,
183-
"ap_wlp1s1_testing_bw_sent": 8270,
184-
"ap_wlp1s1_testing_clients": 2,
177+
"ap_wlp1s0_testing_packets_received": 2670,
178+
"ap_wlp1s0_testing_packets_sent": 51,
179+
"ap_wlp1s1_testing_average_signal": -50666,
180+
"ap_wlp1s1_testing_bitrate_receive": 49400,
181+
"ap_wlp1s1_testing_bitrate_transmit": 43333,
182+
"ap_wlp1s1_testing_bw_received": 101822,
183+
"ap_wlp1s1_testing_bw_sent": 9284,
184+
"ap_wlp1s1_testing_clients": 3,
185185
"ap_wlp1s1_testing_issues_failures": 1,
186186
"ap_wlp1s1_testing_issues_retries": 1,
187-
"ap_wlp1s1_testing_packets_received": 2531,
188-
"ap_wlp1s1_testing_packets_sent": 38,
187+
"ap_wlp1s1_testing_packets_received": 2670,
188+
"ap_wlp1s1_testing_packets_sent": 51,
189189
},
190190
},
191191
"no ap devices": {

src/go/plugin/go.d/collector/ap/testdata/station_dump.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,32 @@ Station fa:50:db:c1:1c:18 (on wlp1s0)
5656
associated at [boottime]: 13440.167s
5757
associated at: 1720706069520 ms
5858
current time: 1720706075344 ms
59+
Station a7:2f:9e:d3:f0:34 (on wlp1s0)
60+
inactive time: 42324 ms
61+
rx bytes: 6705
62+
rx packets: 139
63+
tx bytes: 1014
64+
tx packets: 13
65+
tx retries: 0
66+
tx failed: 0
67+
rx drop misc: 0
68+
signal: -87 [-87] dBm
69+
signal avg: -84 [-84] dBm
70+
tx bitrate: (unknown)
71+
tx duration: 0 us
72+
rx bitrate: 17.2 MBit/s HE-MCS 1 HE-NSS 1 HE-GI 0 HE-DCM 0
73+
rx duration: 0 us
74+
authorized: yes
75+
authenticated: yes
76+
associated: yes
77+
preamble: long
78+
WMM/WME: yes
79+
MFP: no
80+
TDLS peer: no
81+
DTIM period: 2
82+
beacon interval:100
83+
short slot time:yes
84+
connected time: 2215 seconds
85+
associated at [boottime]: 3810.003s
86+
associated at: <timestamp> ms
87+
current time: <timestamp> ms

0 commit comments

Comments
 (0)