@cryptotaxi247 / netdata / commits / a9420fd3a

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"