diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:20 +0000 |
commit | 87d772a7d708fec12f48cd8adc0dedff6e1025da (patch) | |
tree | 1fee344c64cc3f43074a01981e21126c8482a522 /src/go/plugin/go.d/modules/snmp/charts.go | |
parent | Adding upstream version 1.46.3. (diff) | |
download | netdata-87d772a7d708fec12f48cd8adc0dedff6e1025da.tar.xz netdata-87d772a7d708fec12f48cd8adc0dedff6e1025da.zip |
Adding upstream version 1.47.0.upstream/1.47.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/go/plugin/go.d/modules/snmp/charts.go')
-rw-r--r-- | src/go/plugin/go.d/modules/snmp/charts.go | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/snmp/charts.go b/src/go/plugin/go.d/modules/snmp/charts.go new file mode 100644 index 000000000..dd31f1cc7 --- /dev/null +++ b/src/go/plugin/go.d/modules/snmp/charts.go @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package snmp + +import ( + "fmt" + "strings" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" +) + +const ( + prioNetIfaceTraffic = module.Priority + iota + prioNetIfaceUnicast + prioNetIfaceMulticast + prioNetIfaceBroadcast + prioNetIfaceErrors + prioNetIfaceDiscards + prioNetIfaceAdminStatus + prioNetIfaceOperStatus + prioSysUptime +) + +var netIfaceChartsTmpl = module.Charts{ + netIfaceTrafficChartTmpl.Copy(), + netIfacePacketsChartTmpl.Copy(), + netIfaceMulticastChartTmpl.Copy(), + netIfaceBroadcastChartTmpl.Copy(), + netIfaceErrorsChartTmpl.Copy(), + netIfaceDiscardsChartTmpl.Copy(), + netIfaceAdminStatusChartTmpl.Copy(), + netIfaceOperStatusChartTmpl.Copy(), +} + +var ( + netIfaceTrafficChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_traffic", + Title: "SNMP device network interface traffic", + Units: "kilobits/s", + Fam: "traffic", + Ctx: "snmp.device_net_interface_traffic", + Priority: prioNetIfaceTraffic, + Type: module.Area, + Dims: module.Dims{ + {ID: "net_iface_%s_traffic_in", Name: "received", Algo: module.Incremental}, + {ID: "net_iface_%s_traffic_out", Name: "sent", Mul: -1, Algo: module.Incremental}, + }, + } + + netIfacePacketsChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_unicast", + Title: "SNMP device network interface unicast packets", + Units: "packets/s", + Fam: "packets", + Ctx: "snmp.device_net_interface_unicast", + Priority: prioNetIfaceUnicast, + Dims: module.Dims{ + {ID: "net_iface_%s_ucast_in", Name: "received", Algo: module.Incremental}, + {ID: "net_iface_%s_ucast_out", Name: "sent", Mul: -1, Algo: module.Incremental}, + }, + } + netIfaceMulticastChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_multicast", + Title: "SNMP device network interface multicast packets", + Units: "packets/s", + Fam: "packets", + Ctx: "snmp.device_net_interface_multicast", + Priority: prioNetIfaceMulticast, + Dims: module.Dims{ + {ID: "net_iface_%s_mcast_in", Name: "received", Algo: module.Incremental}, + {ID: "net_iface_%s_mcast_out", Name: "sent", Mul: -1, Algo: module.Incremental}, + }, + } + netIfaceBroadcastChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_broadcast", + Title: "SNMP device network interface broadcast packets", + Units: "packets/s", + Fam: "packets", + Ctx: "snmp.device_net_interface_broadcast", + Priority: prioNetIfaceBroadcast, + Dims: module.Dims{ + {ID: "net_iface_%s_bcast_in", Name: "received", Algo: module.Incremental}, + {ID: "net_iface_%s_bcast_out", Name: "sent", Mul: -1, Algo: module.Incremental}, + }, + } + + netIfaceErrorsChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_errors", + Title: "SNMP device network interface errors", + Units: "errors/s", + Fam: "errors", + Ctx: "snmp.device_net_interface_errors", + Priority: prioNetIfaceErrors, + Dims: module.Dims{ + {ID: "net_iface_%s_errors_in", Name: "inbound", Algo: module.Incremental}, + {ID: "net_iface_%s_errors_out", Name: "outbound", Mul: -1, Algo: module.Incremental}, + }, + } + + netIfaceDiscardsChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_discards", + Title: "SNMP device network interface discards", + Units: "discards/s", + Fam: "discards", + Ctx: "snmp.device_net_interface_discards", + Priority: prioNetIfaceDiscards, + Dims: module.Dims{ + {ID: "net_iface_%s_discards_in", Name: "inbound", Algo: module.Incremental}, + {ID: "net_iface_%s_discards_out", Name: "outbound", Mul: -1, Algo: module.Incremental}, + }, + } + + netIfaceAdminStatusChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_admin_status", + Title: "SNMP device network interface administrative status", + Units: "status", + Fam: "status", + Ctx: "snmp.device_net_interface_admin_status", + Priority: prioNetIfaceAdminStatus, + Dims: module.Dims{ + {ID: "net_iface_%s_admin_status_up", Name: "up"}, + {ID: "net_iface_%s_admin_status_down", Name: "down"}, + {ID: "net_iface_%s_admin_status_testing", Name: "testing"}, + }, + } + netIfaceOperStatusChartTmpl = module.Chart{ + ID: "snmp_device_net_iface_%s_oper_status", + Title: "SNMP device network interface operational status", + Units: "status", + Fam: "status", + Ctx: "snmp.device_net_interface_oper_status", + Priority: prioNetIfaceOperStatus, + Dims: module.Dims{ + {ID: "net_iface_%s_oper_status_up", Name: "up"}, + {ID: "net_iface_%s_oper_status_down", Name: "down"}, + {ID: "net_iface_%s_oper_status_testing", Name: "testing"}, + {ID: "net_iface_%s_oper_status_unknown", Name: "unknown"}, + {ID: "net_iface_%s_oper_status_dormant", Name: "dormant"}, + {ID: "net_iface_%s_oper_status_notPresent", Name: "not_present"}, + {ID: "net_iface_%s_oper_status_lowerLayerDown", Name: "lower_layer_down"}, + }, + } +) + +var ( + uptimeChart = module.Chart{ + ID: "snmp_device_uptime", + Title: "SNMP device uptime", + Units: "seconds", + Fam: "uptime", + Ctx: "snmp.device_uptime", + Priority: prioSysUptime, + Dims: module.Dims{ + {ID: "uptime", Name: "uptime"}, + }, + } +) + +func (s *SNMP) addNetIfaceCharts(iface *netInterface) { + charts := netIfaceChartsTmpl.Copy() + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, cleanIfaceName(iface.ifName)) + chart.Labels = []module.Label{ + {Key: "sysName", Value: s.sysName}, + {Key: "ifDescr", Value: iface.ifDescr}, + {Key: "ifName", Value: iface.ifName}, + {Key: "ifType", Value: ifTypeMapping[iface.ifType]}, + } + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, iface.ifName) + } + } + + if err := s.Charts().Add(*charts...); err != nil { + s.Warning(err) + } +} + +func (s *SNMP) removeNetIfaceCharts(iface *netInterface) { + px := fmt.Sprintf("snmp_device_net_iface_%s_", cleanIfaceName(iface.ifName)) + for _, chart := range *s.Charts() { + if strings.HasPrefix(chart.ID, px) { + chart.MarkRemove() + chart.MarkNotCreated() + } + } +} + +func (s *SNMP) addSysUptimeChart() { + chart := uptimeChart.Copy() + chart.Labels = []module.Label{ + {Key: "sysName", Value: s.sysName}, + } + if err := s.Charts().Add(chart); err != nil { + s.Warning(err) + } +} + +func cleanIfaceName(name string) string { + r := strings.NewReplacer(".", "_", " ", "_") + return r.Replace(name) +} + +func newUserInputCharts(configs []ChartConfig) (*module.Charts, error) { + charts := &module.Charts{} + for _, cfg := range configs { + if len(cfg.IndexRange) == 2 { + cs, err := newUserInputChartsFromIndexRange(cfg) + if err != nil { + return nil, err + } + if err := charts.Add(*cs...); err != nil { + return nil, err + } + } else { + chart, err := newUserInputChart(cfg) + if err != nil { + return nil, err + } + if err = charts.Add(chart); err != nil { + return nil, err + } + } + } + return charts, nil +} + +func newUserInputChartsFromIndexRange(cfg ChartConfig) (*module.Charts, error) { + var addPrio int + charts := &module.Charts{} + for i := cfg.IndexRange[0]; i <= cfg.IndexRange[1]; i++ { + chart, err := newUserInputChartWithOIDIndex(i, cfg) + if err != nil { + return nil, err + } + chart.Priority += addPrio + addPrio += 1 + if err = charts.Add(chart); err != nil { + return nil, err + } + } + return charts, nil +} + +func newUserInputChartWithOIDIndex(oidIndex int, cfg ChartConfig) (*module.Chart, error) { + chart, err := newUserInputChart(cfg) + if err != nil { + return nil, err + } + + chart.ID = fmt.Sprintf("%s_%d", chart.ID, oidIndex) + chart.Title = fmt.Sprintf("%s %d", chart.Title, oidIndex) + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf("%s.%d", dim.ID, oidIndex) + } + + return chart, nil +} + +func newUserInputChart(cfg ChartConfig) (*module.Chart, error) { + chart := &module.Chart{ + ID: cfg.ID, + Title: cfg.Title, + Units: cfg.Units, + Fam: cfg.Family, + Ctx: fmt.Sprintf("snmp.%s", cfg.ID), + Type: module.ChartType(cfg.Type), + Priority: cfg.Priority, + } + + if chart.Title == "" { + chart.Title = "Untitled chart" + } + if chart.Units == "" { + chart.Units = "num" + } + if chart.Priority < module.Priority { + chart.Priority += module.Priority + } + + seen := make(map[string]struct{}) + var a string + for _, cfg := range cfg.Dimensions { + if cfg.Algorithm != "" { + seen[cfg.Algorithm] = struct{}{} + a = cfg.Algorithm + } + dim := &module.Dim{ + ID: strings.TrimPrefix(cfg.OID, "."), + Name: cfg.Name, + Algo: module.DimAlgo(cfg.Algorithm), + Mul: cfg.Multiplier, + Div: cfg.Divisor, + } + if err := chart.AddDim(dim); err != nil { + return nil, err + } + } + if len(seen) == 1 && a != "" && len(chart.Dims) > 1 { + for _, d := range chart.Dims { + if d.Algo == "" { + d.Algo = module.DimAlgo(a) + } + } + } + + return chart, nil +} |