improve(go.d/ddsnmp): refactor IF-MIB profile with unified virtual metrics and 64-bit preference (#21017)
Ilya Mashchenko committed
Sep 21, 2025 at 04:43 UTC
a9420fd3a398e4838dc68e18af7d09be526e5bf1
3 files changed
+304
-89
src/go/plugin/go.d/collector/snmp/charts.go
+1
-1
@@ -416,7 +416,7 @@ func (c *Collector) addProfileTableMetricChart(m ddsnmp.Metric) {
416
if !seen[k] {
417
seen[k] = true
418
id := fmt.Sprintf("snmp_device_prof_%s_%s", key, k)
419
- chart.Dims = append(chart.Dims, &module.Dim{ID: id, Name: k, Algo: module.Absolute})
419
+ chart.Dims = append(chart.Dims, &module.Dim{ID: id, Name: k, Algo: dimAlgoFromDdSnmpType(m)})
420
}
421
}
422
} else {
src/go/plugin/go.d/collector/snmp/ddsnmp/ddsnmpcollector/collector_vmetrics_test.go
+120
@@ -1436,6 +1436,126 @@ func TestVirtualMetricsCollector_Collect(t *testing.T) {
1436
{Name: "ifTotalTrafficIn", Value: 123, Description: "Total inbound"},
1437
},
1438
},
1439
+
1440
+ // alternatives + per_row: choose 64-bit ifXTable when available
1441
+ "alternatives per_row: select 64-bit child": {
1442
+ profileDef: &ddprofiledefinition.ProfileDefinition{
1443
+ VirtualMetrics: []ddprofiledefinition.VirtualMetricConfig{
1444
+ {
1445
+ Name: "ifTraffic",
1446
+ PerRow: true,
1447
+ GroupBy: []string{"interface"},
1448
+ Alternatives: []ddprofiledefinition.VirtualMetricAlternativeSourcesConfig{
1449
+ {Sources: []ddprofiledefinition.VirtualMetricSourceConfig{
1450
+ {Metric: "ifHCInOctets", Table: "ifXTable", As: "in"},
1451
+ {Metric: "ifHCOutOctets", Table: "ifXTable", As: "out"},
1452
+ }},
1453
+ {Sources: []ddprofiledefinition.VirtualMetricSourceConfig{
1454
+ {Metric: "ifInOctets", Table: "ifTable", As: "in"},
1455
+ {Metric: "ifOutOctets", Table: "ifTable", As: "out"},
1456
+ }},
1457
+ },
1458
+ ChartMeta: ddprofiledefinition.ChartMeta{
1459
+ Description: "Per-interface traffic",
1460
+ Family: "Network/Interface/Traffic/Total",
1461
+ Unit: "bit/s",
1462
+ },
1463
+ },
1464
+ },
1465
+ },
1466
+ collectedMetrics: []ddsnmp.Metric{
1467
+ {Name: "ifHCInOctets", Value: 100, IsTable: true, Table: "ifXTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth0"}},
1468
+ {Name: "ifHCOutOctets", Value: 200, IsTable: true, Table: "ifXTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth0"}},
1469
+ {Name: "ifHCInOctets", Value: 300, IsTable: true, Table: "ifXTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth1"}},
1470
+ {Name: "ifHCOutOctets", Value: 400, IsTable: true, Table: "ifXTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth1"}},
1471
+
1472
+ // 32-bit also present but must be ignored
1473
+ {Name: "ifInOctets", Value: 1, IsTable: true, Table: "ifTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth0"}},
1474
+ {Name: "ifOutOctets", Value: 2, IsTable: true, Table: "ifTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth0"}},
1475
+ },
1476
+ expected: []ddsnmp.Metric{
1477
+ {
1478
+ Name: "ifTraffic",
1479
+ IsTable: true,
1480
+ Table: "ifXTable",
1481
+ Tags: map[string]string{"interface": "eth0"},
1482
+ MultiValue: map[string]int64{"in": 100, "out": 200},
1483
+ Description: "Per-interface traffic",
1484
+ Family: "Network/Interface/Traffic/Total",
1485
+ Unit: "bit/s",
1486
+ MetricType: ddprofiledefinition.ProfileMetricTypeCounter,
1487
+ },
1488
+ {
1489
+ Name: "ifTraffic",
1490
+ IsTable: true,
1491
+ Table: "ifXTable",
1492
+ Tags: map[string]string{"interface": "eth1"},
1493
+ MultiValue: map[string]int64{"in": 300, "out": 400},
1494
+ Description: "Per-interface traffic",
1495
+ Family: "Network/Interface/Traffic/Total",
1496
+ Unit: "bit/s",
1497
+ MetricType: ddprofiledefinition.ProfileMetricTypeCounter,
1498
+ },
1499
+ },
1500
+ },
1501
+
1502
+ // alternatives + per_row: fall back to 32-bit if only ifTable has data
1503
+ "alternatives per_row: fallback to 32-bit child": {
1504
+ profileDef: &ddprofiledefinition.ProfileDefinition{
1505
+ VirtualMetrics: []ddprofiledefinition.VirtualMetricConfig{
1506
+ {
1507
+ Name: "ifTraffic",
1508
+ PerRow: true,
1509
+ GroupBy: []string{"interface"},
1510
+ Alternatives: []ddprofiledefinition.VirtualMetricAlternativeSourcesConfig{
1511
+ {Sources: []ddprofiledefinition.VirtualMetricSourceConfig{
1512
+ {Metric: "ifHCInOctets", Table: "ifXTable", As: "in"},
1513
+ {Metric: "ifHCOutOctets", Table: "ifXTable", As: "out"},
1514
+ }},
1515
+ {Sources: []ddprofiledefinition.VirtualMetricSourceConfig{
1516
+ {Metric: "ifInOctets", Table: "ifTable", As: "in"},
1517
+ {Metric: "ifOutOctets", Table: "ifTable", As: "out"},
1518
+ }},
1519
+ },
1520
+ ChartMeta: ddprofiledefinition.ChartMeta{
1521
+ Description: "Per-interface traffic",
1522
+ Family: "Network/Interface/Traffic/Total",
1523
+ Unit: "bit/s",
1524
+ },
1525
+ },
1526
+ },
1527
+ },
1528
+ collectedMetrics: []ddsnmp.Metric{
1529
+ {Name: "ifInOctets", Value: 10, IsTable: true, Table: "ifTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth0"}},
1530
+ {Name: "ifOutOctets", Value: 20, IsTable: true, Table: "ifTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth0"}},
1531
+ {Name: "ifInOctets", Value: 30, IsTable: true, Table: "ifTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth1"}},
1532
+ {Name: "ifOutOctets", Value: 40, IsTable: true, Table: "ifTable", MetricType: ddprofiledefinition.ProfileMetricTypeCounter, Tags: map[string]string{"interface": "eth1"}},
1533
+ },
1534
+ expected: []ddsnmp.Metric{
1535
+ {
1536
+ Name: "ifTraffic",
1537
+ IsTable: true,
1538
+ Table: "ifTable", // fallback
1539
+ Tags: map[string]string{"interface": "eth0"},
1540
+ MultiValue: map[string]int64{"in": 10, "out": 20},
1541
+ Description: "Per-interface traffic",
1542
+ Family: "Network/Interface/Traffic/Total",
1543
+ Unit: "bit/s",
1544
+ MetricType: ddprofiledefinition.ProfileMetricTypeCounter,
1545
+ },
1546
+ {
1547
+ Name: "ifTraffic",
1548
+ IsTable: true,
1549
+ Table: "ifTable", // fallback
1550
+ Tags: map[string]string{"interface": "eth1"},
1551
+ MultiValue: map[string]int64{"in": 30, "out": 40},
1552
+ Description: "Per-interface traffic",
1553
+ Family: "Network/Interface/Traffic/Total",
1554
+ Unit: "bit/s",
1555
+ MetricType: ddprofiledefinition.ProfileMetricTypeCounter,
1556
+ },
1557
+ },
1558
+ },
1559
}
1560
1561
for name, tc := range tests {
src/go/plugin/go.d/config/go.d/snmp.profiles/default/_std-if-mib.yaml
+183
-88
@@ -10,35 +10,27 @@ metrics:
10
description: Number of network interfaces regardless of their current state present on this system
11
family: 'Network/Interface/Count/Total'
12
unit: "{interface}"
13
+
14
+ # =========================
15
+ # IF-MIB::ifTable (32-bit)
16
+ # =========================
17
- MIB: IF-MIB
18
table:
19
OID: 1.3.6.1.2.1.2.2
20
name: ifTable
21
symbols:
18
- - OID: 1.3.6.1.2.1.2.2.1.14
19
- name: ifInErrors
20
- chart_meta:
21
- description: Number of inbound packets that contained errors preventing them from being deliverable to a higher-layer protocol
22
- family: 'Network/Interface/Error/Total/In'
23
- unit: "{error}/s"
24
- - OID: 1.3.6.1.2.1.2.2.1.20
25
- name: ifOutErrors
26
- chart_meta:
27
- description: Number of outbound packets that could not be transmitted because of errors
28
- family: 'Network/Interface/Error/Total/Out'
29
- unit: "{error}/s"
30
- - OID: 1.3.6.1.2.1.2.2.1.13
31
- name: ifInDiscards
32
- chart_meta:
33
- description: Number of inbound packets chosen to be discarded even though no errors had been detected to prevent their being deliverable to a higher-layer protocol
34
- family: 'Network/Interface/Discard/In'
35
- unit: "{discard}/s"
36
- - OID: 1.3.6.1.2.1.2.2.1.19
37
- name: ifOutDiscards
38
- chart_meta:
39
- description: Number of outbound packets chosen to be discarded even though no errors had been detected to prevent their being transmitted
40
- family: 'Network/Interface/Discard/Out'
41
- unit: "{discard}/s"
22
+ # 32-bit octets (fallback for traffic)
23
+ - { OID: 1.3.6.1.2.1.2.2.1.10, name: _ifInOctets, scale_factor: 8 }
24
+ - { OID: 1.3.6.1.2.1.2.2.1.16, name: _ifOutOctets, scale_factor: 8 }
25
+ # 32-bit unicast packets (fallback for unicast packet rate)
26
+ - { OID: 1.3.6.1.2.1.2.2.1.11, name: _ifInUcastPkts }
27
+ - { OID: 1.3.6.1.2.1.2.2.1.17, name: _ifOutUcastPkts }
28
+ # 32-bit only
29
+ - { OID: 1.3.6.1.2.1.2.2.1.14, name: _ifInErrors }
30
+ - { OID: 1.3.6.1.2.1.2.2.1.20, name: _ifOutErrors }
31
+ - { OID: 1.3.6.1.2.1.2.2.1.13, name: _ifInDiscards }
32
+ - { OID: 1.3.6.1.2.1.2.2.1.19, name: _ifOutDiscards }
33
+
34
- OID: 1.3.6.1.2.1.2.2.1.7
35
name: ifAdminStatus
36
chart_meta:
@@ -78,61 +70,24 @@ metrics:
70
OID: 1.3.6.1.2.1.2.2.1.3
71
name: ifType
72
mapping_ref: ifType
73
+
74
+ # =========================
75
+ # IF-MIB::ifXTable (64-bit + extras)
76
+ # =========================
77
- MIB: IF-MIB
78
table:
79
OID: 1.3.6.1.2.1.31.1.1
80
name: ifXTable
81
symbols:
86
- - OID: 1.3.6.1.2.1.31.1.1.1.6
87
- name: ifHCInOctets
88
- chart_meta:
89
- description: Total number of octets received on the interface including framing characters
90
- family: 'Network/Interface/Traffic/Total/In'
91
- unit: "bit/s"
92
- scale_factor: 8 # octets => bits
93
- - OID: 1.3.6.1.2.1.31.1.1.1.10
94
- name: ifHCOutOctets
95
- chart_meta:
96
- description: Total number of octets transmitted out of the interface including framing characters
97
- family: 'Network/Interface/Traffic/Total/Out'
98
- unit: "bit/s"
99
- scale_factor: 8 # octets => bits
100
- - OID: 1.3.6.1.2.1.31.1.1.1.7
101
- name: ifHCInUcastPkts
102
- chart_meta:
103
- description: Number of packets delivered by this sub-layer to a higher layer which were not addressed to a multicast or broadcast address
104
- family: 'Network/Interface/Packet/Unicast/In'
105
- unit: "{packet}/s"
106
- - OID: 1.3.6.1.2.1.31.1.1.1.8
107
- name: ifHCInMulticastPkts
108
- chart_meta:
109
- description: Number of packets delivered by this sub-layer to a higher layer which were addressed to a multicast address
110
- family: 'Network/Interface/Packet/Multicast/In'
111
- unit: "{packet}/s"
112
- - OID: 1.3.6.1.2.1.31.1.1.1.9
113
- name: ifHCInBroadcastPkts
114
- chart_meta:
115
- description: Number of packets delivered by this sub-layer to a higher layer which were addressed to a broadcast address
116
- family: 'Network/Interface/Packet/Broadcast/In'
117
- unit: "{packet}/s"
118
- - OID: 1.3.6.1.2.1.31.1.1.1.11
119
- name: ifHCOutUcastPkts
120
- chart_meta:
121
- description: Total number of packets that higher-level protocols requested be transmitted and which were not addressed to a multicast or broadcast address
122
- family: 'Network/Interface/Packet/Unicast/Out'
123
- unit: "{packet}/s"
124
- - OID: 1.3.6.1.2.1.31.1.1.1.12
125
- name: ifHCOutMulticastPkts
126
- chart_meta:
127
- description: Total number of packets that higher-level protocols requested be transmitted and which were addressed to a multicast address
128
- family: 'Network/Interface/Packet/Multicast/Out'
129
- unit: "{packet}/s"
130
- - OID: 1.3.6.1.2.1.31.1.1.1.13
131
- name: ifHCOutBroadcastPkts
132
- chart_meta:
133
- description: Total number of packets that higher-level protocols requested be transmitted and which were addressed to a broadcast address
134
- family: 'Network/Interface/Packet/Broadcast/Out'
135
- unit: "{packet}/s"
82
+ - { OID: 1.3.6.1.2.1.31.1.1.1.6, name: _ifHCInOctets, scale_factor: 8 }
83
+ - { OID: 1.3.6.1.2.1.31.1.1.1.10, name: _ifHCOutOctets, scale_factor: 8 }
84
+ - { OID: 1.3.6.1.2.1.31.1.1.1.7, name: _ifHCInUcastPkts }
85
+ - { OID: 1.3.6.1.2.1.31.1.1.1.11, name: _ifHCOutUcastPkts }
86
+ - { OID: 1.3.6.1.2.1.31.1.1.1.8, name: _ifHCInMulticastPkts }
87
+ - { OID: 1.3.6.1.2.1.31.1.1.1.12, name: _ifHCOutMulticastPkts }
88
+ - { OID: 1.3.6.1.2.1.31.1.1.1.9, name: _ifHCInBroadcastPkts }
89
+ - { OID: 1.3.6.1.2.1.31.1.1.1.13, name: _ifHCOutBroadcastPkts }
90
+
91
- OID: 1.3.6.1.2.1.31.1.1.1.15
92
name: ifHighSpeed
93
chart_meta:
@@ -158,27 +113,167 @@ metrics:
113
mapping_ref: ifType
114
115
virtual_metrics:
161
- - name: ifTotalTrafficIn
162
- sources:
163
- - metric: ifHCInOctets
164
- table: ifXTable
116
+ # ======================
117
+ # TOTALS (all interfaces)
118
+ # ======================
119
+
120
+ # Traffic total (prefer 64-bit HC; fallback to 32-bit)
121
+ - name: ifTotalTraffic
122
+ alternatives:
123
+ - sources:
124
+ - { metric: _ifHCInOctets, table: ifXTable, as: in }
125
+ - { metric: _ifHCOutOctets, table: ifXTable, as: out }
126
+ - sources:
127
+ - { metric: _ifInOctets, table: ifTable, as: in }
128
+ - { metric: _ifOutOctets, table: ifTable, as: out }
129
chart_meta:
166
- description: Total inbound traffic across all interfaces
167
- family: 'Network/Total/Traffic/In'
130
+ description: Total traffic across all interfaces
131
+ family: 'Network/Total/Traffic'
132
unit: "bit/s"
169
- - name: ifTotalTrafficOut
133
+
134
+ # Unicast packets total (prefer 64-bit HC; fallback to 32-bit)
135
+ - name: ifTotalPacketsUcast
136
+ alternatives:
137
+ - sources:
138
+ - { metric: _ifHCInUcastPkts, table: ifXTable, as: in }
139
+ - { metric: _ifHCOutUcastPkts, table: ifXTable, as: out }
140
+ - sources:
141
+ - { metric: _ifInUcastPkts, table: ifTable, as: in }
142
+ - { metric: _ifOutUcastPkts, table: ifTable, as: out }
143
+ chart_meta:
144
+ description: Total unicast packets across all interfaces
145
+ family: 'Network/Total/Packet/Unicast'
146
+ unit: "{packet}/s"
147
+
148
+ # Multicast packets total (HC only from ifXTable)
149
+ - name: ifTotalPacketsMulticast
150
sources:
171
- - metric: ifHCOutOctets
172
- table: ifXTable
151
+ - { metric: _ifHCInMulticastPkts, table: ifXTable, as: in }
152
+ - { metric: _ifHCOutMulticastPkts, table: ifXTable, as: out }
153
chart_meta:
174
- description: Total outbound traffic across all interfaces
175
- family: 'Network/Total/Traffic/Out'
176
- unit: "bit/s"
154
+ description: Total multicast packets across all interfaces
155
+ family: 'Network/Total/Packet/Multicast'
156
+ unit: "{packet}/s"
157
+
158
+ # Broadcast packets total (HC only from ifXTable)
159
+ - name: ifTotalPacketsBroadcast
160
+ sources:
161
+ - { metric: _ifHCInBroadcastPkts, table: ifXTable, as: in }
162
+ - { metric: _ifHCOutBroadcastPkts, table: ifXTable, as: out }
163
+ chart_meta:
164
+ description: Total broadcast packets across all interfaces
165
+ family: 'Network/Total/Packet/Broadcast'
166
+ unit: "{packet}/s"
167
+
168
+ # Errors total (ifTable only)
169
+ - name: ifTotalErrors
170
+ sources:
171
+ - { metric: _ifInErrors, table: ifTable, as: in }
172
+ - { metric: _ifOutErrors, table: ifTable, as: out }
173
+ chart_meta:
174
+ description: Total packets with errors across all interfaces
175
+ family: 'Network/Total/Error'
176
+ unit: "{error}/s"
177
+
178
+ # Discards total (ifTable only)
179
+ - name: ifTotalDiscards
180
+ sources:
181
+ - { metric: _ifInDiscards, table: ifTable, as: in }
182
+ - { metric: _ifOutDiscards, table: ifTable, as: out }
183
+ chart_meta:
184
+ description: Total packets discarded across all interfaces
185
+ family: 'Network/Total/Discard'
186
+ unit: "{discard}/s"
187
+
188
+ # Operational status total
189
- name: ifTotalOperStatus
190
sources:
179
- - metric: ifOperStatus
180
- table: ifTable
191
+ - { metric: ifOperStatus, table: ifTable }
192
chart_meta:
193
description: Total count of interfaces by operational status
194
family: 'Network/Total/Interface/Status'
195
unit: "{status}"
196
+
197
+ # =========================
198
+ # PER INTERFACE (per_row)
199
+ # =========================
200
+
201
+ # Traffic per interface
202
+ - name: ifTraffic
203
+ per_row: true
204
+ group_by: ["interface"]
205
+ alternatives:
206
+ - sources:
207
+ - { metric: _ifHCInOctets, table: ifXTable, as: in }
208
+ - { metric: _ifHCOutOctets, table: ifXTable, as: out }
209
+ - sources:
210
+ - { metric: _ifInOctets, table: ifTable, as: in }
211
+ - { metric: _ifOutOctets, table: ifTable, as: out }
212
+ chart_meta:
213
+ description: Traffic
214
+ family: 'Network/Interface/Traffic/Total'
215
+ unit: "bit/s"
216
+
217
+ # Unicast packets per interface
218
+ - name: ifPacketsUcast
219
+ per_row: true
220
+ group_by: ["interface"]
221
+ alternatives:
222
+ - sources:
223
+ - { metric: _ifHCInUcastPkts, table: ifXTable, as: in }
224
+ - { metric: _ifHCOutUcastPkts, table: ifXTable, as: out }
225
+ - sources:
226
+ - { metric: _ifInUcastPkts, table: ifTable, as: in }
227
+ - { metric: _ifOutUcastPkts, table: ifTable, as: out }
228
+ chart_meta:
229
+ description: Unicast packets
230
+ family: 'Network/Interface/Packet/Unicast'
231
+ unit: "{packet}/s"
232
+
233
+ # Multicast packets per interface
234
+ - name: ifPacketsMulticast
235
+ per_row: true
236
+ group_by: ["interface"]
237
+ sources:
238
+ - { metric: _ifHCInMulticastPkts, table: ifXTable, as: in }
239
+ - { metric: _ifHCOutMulticastPkts, table: ifXTable, as: out }
240
+ chart_meta:
241
+ description: Multicast packets
242
+ family: 'Network/Interface/Packet/Multicast'
243
+ unit: "{packet}/s"
244
+
245
+ # Broadcast packets per interface
246
+ - name: ifPacketsBroadcast
247
+ per_row: true
248
+ group_by: ["interface"]
249
+ sources:
250
+ - { metric: _ifHCInBroadcastPkts, table: ifXTable, as: in }
251
+ - { metric: _ifHCOutBroadcastPkts, table: ifXTable, as: out }
252
+ chart_meta:
253
+ description: Broadcast packets
254
+ family: 'Network/Interface/Packet/Broadcast'
255
+ unit: "{packet}/s"
256
+
257
+ # Errors per interface (ifTable only)
258
+ - name: ifErrors
259
+ per_row: true
260
+ group_by: ["interface"]
261
+ sources:
262
+ - { metric: _ifInErrors, table: ifTable, as: in }
263
+ - { metric: _ifOutErrors, table: ifTable, as: out }
264
+ chart_meta:
265
+ description: Packets with errors
266
+ family: 'Network/Interface/Error/Total'
267
+ unit: "{error}/s"
268
+
269
+ # Discards per interface (ifTable only)
270
+ - name: ifDiscards
271
+ per_row: true
272
+ group_by: ["interface"]
273
+ sources:
274
+ - { metric: _ifInDiscards, table: ifTable, as: in }
275
+ - { metric: _ifOutDiscards, table: ifTable, as: out }
276
+ chart_meta:
277
+ description: Packets discarded
278
+ family: 'Network/Interface/Discard'
279
+ unit: "{discard}/s"