diff --git a/README.md b/README.md index 141eaf8..ea400bf 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ features: ``` ## Dynamic Interface Labels -Version 0.9.5 introduced dynamic labels retrieved from the interface descriptions. Flags are supported a well. The first part (label name) has to comply to the following rules: +Version 0.9.5 introduced dynamic labels retrieved from the interface descriptions. Version 0.12.4 added support for dynamic labels on BGP metrics. Flags are supported a well. The first part (label name) has to comply to the following rules: * must not begin with a figure * must only contain this charakters: A-Z,a-z,0-9,_ * is treated lower case diff --git a/collectors.go b/collectors.go index ee4105c..d1017fd 100644 --- a/collectors.go +++ b/collectors.go @@ -41,34 +41,31 @@ import ( "github.com/czerwonk/junos_exporter/pkg/features/system" "github.com/czerwonk/junos_exporter/pkg/features/vpws" "github.com/czerwonk/junos_exporter/pkg/features/vrrp" - "github.com/czerwonk/junos_exporter/pkg/interfacelabels" ) type collectors struct { logicalSystem string - dynamicLabels *interfacelabels.DynamicLabelManager collectors map[string]collector.RPCCollector devices map[string][]collector.RPCCollector cfg *config.Config } -func collectorsForDevices(devices []*connector.Device, cfg *config.Config, logicalSystem string, dynamicLabels *interfacelabels.DynamicLabelManager) *collectors { +func collectorsForDevices(devices []*connector.Device, cfg *config.Config, logicalSystem string) *collectors { c := &collectors{ logicalSystem: logicalSystem, - dynamicLabels: dynamicLabels, collectors: make(map[string]collector.RPCCollector), devices: make(map[string][]collector.RPCCollector), cfg: cfg, } for _, d := range devices { - c.initCollectorsForDevices(d, cfg.IfDescReg) + c.initCollectorsForDevices(d, deviceInterfaceRegex(cfg, d.Host)) } return c } -func (c *collectors) initCollectorsForDevices(device *connector.Device, bgpDescRe *regexp.Regexp) { +func (c *collectors) initCollectorsForDevices(device *connector.Device, descRe *regexp.Regexp) { f := c.cfg.FeaturesForDevice(device.Host) c.devices[device.Host] = make([]collector.RPCCollector, 0) @@ -80,19 +77,19 @@ func (c *collectors) initCollectorsForDevices(device *connector.Device, bgpDescR }) c.addCollectorIfEnabledForDevice(device, "bfd", f.BFD, bfd.NewCollector) c.addCollectorIfEnabledForDevice(device, "bgp", f.BGP, func() collector.RPCCollector { - return bgp.NewCollector(c.logicalSystem, bgpDescRe) + return bgp.NewCollector(c.logicalSystem, descRe) }) c.addCollectorIfEnabledForDevice(device, "env", f.Environment, environment.NewCollector) c.addCollectorIfEnabledForDevice(device, "firewall", f.Firewall, firewall.NewCollector) c.addCollectorIfEnabledForDevice(device, "fpc", f.FPC, fpc.NewCollector) c.addCollectorIfEnabledForDevice(device, "ifacediag", f.InterfaceDiagnostic, func() collector.RPCCollector { - return interfacediagnostics.NewCollector(c.dynamicLabels) + return interfacediagnostics.NewCollector(descRe) }) c.addCollectorIfEnabledForDevice(device, "ifacequeue", f.InterfaceQueue, func() collector.RPCCollector { - return interfacequeue.NewCollector(c.dynamicLabels) + return interfacequeue.NewCollector(descRe) }) c.addCollectorIfEnabledForDevice(device, "iface", f.Interfaces, func() collector.RPCCollector { - return interfaces.NewCollector(c.dynamicLabels) + return interfaces.NewCollector(descRe) }) c.addCollectorIfEnabledForDevice(device, "ipsec", f.IPSec, ipsec.NewCollector) c.addCollectorIfEnabledForDevice(device, "isis", f.ISIS, isis.NewCollector) diff --git a/collectors_test.go b/collectors_test.go index b5a5d9f..b180a67 100644 --- a/collectors_test.go +++ b/collectors_test.go @@ -9,7 +9,6 @@ import ( "github.com/czerwonk/junos_exporter/internal/config" "github.com/czerwonk/junos_exporter/pkg/connector" - "github.com/czerwonk/junos_exporter/pkg/interfacelabels" ) func TestCollectorsRegistered(t *testing.T) { @@ -40,7 +39,7 @@ func TestCollectorsRegistered(t *testing.T) { cols := collectorsForDevices([]*connector.Device{{ Host: "::1", - }}, c, "", interfacelabels.NewDynamicLabelManager()) + }}, c, "") assert.Equal(t, 20, len(cols.collectors), "collector count") } @@ -88,7 +87,7 @@ func TestCollectorsForDevices(t *testing.T) { d2 := &connector.Device{ Host: "2001:678:1e0::2", } - cols := collectorsForDevices([]*connector.Device{d1, d2}, c, "", interfacelabels.NewDynamicLabelManager()) + cols := collectorsForDevices([]*connector.Device{d1, d2}, c, "") assert.Equal(t, 20, len(cols.collectorsForDevice(d1)), "device 1 collector count") diff --git a/internal/config/config.go b/internal/config/config.go index 945d348..d895d5b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -21,8 +21,8 @@ type Config struct { IfDescReg *regexp.Regexp `yaml:"-"` } -func (c *Config) load() error { - if c.IfDescReStr != "" { +func (c *Config) load(dynamicIfaceLabels bool) error { + if c.IfDescReStr != "" && dynamicIfaceLabels { re, err := regexp.Compile(c.IfDescReStr) if err != nil { return fmt.Errorf("unable to compile interfce description regex %q: %w", c.IfDescReStr, err) @@ -31,6 +31,17 @@ func (c *Config) load() error { c.IfDescReg = re } + for _, d := range c.Devices { + if d.IfDescRegStr != "" && dynamicIfaceLabels { + re, err := regexp.Compile(c.IfDescReStr) + if err != nil { + return fmt.Errorf("unable to compile interfce description regex %q: %w", c.IfDescReStr, err) + } + + d.IfDescReg = re + } + } + return nil } @@ -98,7 +109,7 @@ func New() *Config { } // Load loads a config from reader -func Load(reader io.Reader) (*Config, error) { +func Load(reader io.Reader, dynamicIfaceLabels bool) (*Config, error) { b, err := io.ReadAll(reader) if err != nil { return nil, err @@ -110,7 +121,7 @@ func Load(reader io.Reader) (*Config, error) { return nil, err } - err = c.load() + err = c.load(dynamicIfaceLabels) if err != nil { return nil, err } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index bd03da3..63ca75c 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -17,7 +17,7 @@ func TestShouldParse(t *testing.T) { t.Fatal(err) } - c, err := Load(bytes.NewReader(b)) + c, err := Load(bytes.NewReader(b), true) if err != nil { t.Fatal(err) } @@ -49,7 +49,7 @@ func TestShouldUseDefaults(t *testing.T) { t.Fatal(err) } - c, err := Load(bytes.NewReader(b)) + c, err := Load(bytes.NewReader(b), true) if err != nil { t.Fatal(err) } @@ -78,7 +78,7 @@ func TestShouldParseDevices(t *testing.T) { t.Fatal(err) } - c, err := Load(bytes.NewReader(b)) + c, err := Load(bytes.NewReader(b), true) if err != nil { t.Fatal(err) } @@ -124,7 +124,7 @@ func TestShouldParseDevicesWithPattern(t *testing.T) { t.Fatal(err) } - c, err := Load(bytes.NewReader(b)) + c, err := Load(bytes.NewReader(b), true) if err != nil { t.Fatal(err) } @@ -165,7 +165,7 @@ func TestShouldParseDevicesWithPatternInvalid(t *testing.T) { t.Fatal(err) } - c, err := Load(bytes.NewReader(b)) + c, err := Load(bytes.NewReader(b), true) if c != nil { t.Fatal("Parsing should fail because of invalid pattern") } @@ -185,7 +185,7 @@ func TestFindDeviceConfig(t *testing.T) { if err != nil { t.Fatal(err) } - c, err := Load(bytes.NewReader(b)) + c, err := Load(bytes.NewReader(b), true) if err != nil { t.Fatal(err) } diff --git a/junos_collector.go b/junos_collector.go index 66d5a2c..755d663 100644 --- a/junos_collector.go +++ b/junos_collector.go @@ -8,14 +8,16 @@ import ( "sync" "time" + "github.com/czerwonk/junos_exporter/internal/config" "github.com/czerwonk/junos_exporter/pkg/connector" - "github.com/czerwonk/junos_exporter/pkg/interfacelabels" + "github.com/czerwonk/junos_exporter/pkg/dynamiclabels" "github.com/czerwonk/junos_exporter/pkg/rpc" "github.com/prometheus/client_golang/prometheus" - log "github.com/sirupsen/logrus" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/trace" + + log "github.com/sirupsen/logrus" ) const prefix = "junos_" @@ -40,8 +42,6 @@ type junosCollector struct { } func newJunosCollector(ctx context.Context, devices []*connector.Device, logicalSystem string) *junosCollector { - l := interfacelabels.NewDynamicLabelManager() - clients := make(map[*connector.Device]*rpc.Client) for _, d := range devices { @@ -52,42 +52,28 @@ func newJunosCollector(ctx context.Context, devices []*connector.Device, logical } clients[d] = cl - cta := &clientTracingAdapter{ - cl: cl, - ctx: ctx, - } - - if *dynamicIfaceLabels { - regex := deviceInterfaceRegex(d.Host) - err = l.CollectDescriptions(d, cta, regex) - if err != nil { - log.Errorf("Could not get interface descriptions %s: %s", d, err) - continue - } - } } return &junosCollector{ devices: devices, - collectors: collectorsForDevices(devices, cfg, logicalSystem, l), + collectors: collectorsForDevices(devices, cfg, logicalSystem), clients: clients, ctx: ctx, } } -func deviceInterfaceRegex(host string) *regexp.Regexp { +func deviceInterfaceRegex(cfg *config.Config, host string) *regexp.Regexp { dc := cfg.FindDeviceConfig(host) - if len(dc.IfDescRegStr) > 0 { - regex, err := regexp.Compile(dc.IfDescRegStr) - if err == nil { - return regex - } + if dc != nil { + return dc.IfDescReg + } - log.Errorf("device specific dynamic label regex %s invalid: %v", dc.IfDescRegStr, err) + if cfg.IfDescReg != nil { + return cfg.IfDescReg } - return interfacelabels.DefaultInterfaceDescRegex() + return dynamiclabels.DefaultInterfaceDescRegex() } func clientForDevice(device *connector.Device, connManager *connector.SSHConnectionManager) (*rpc.Client, error) { diff --git a/main.go b/main.go index 8d11210..77cb655 100644 --- a/main.go +++ b/main.go @@ -205,7 +205,7 @@ func loadConfig() (*config.Config, error) { return nil, err } - return config.Load(bytes.NewReader(b)) + return config.Load(bytes.NewReader(b), *dynamicIfaceLabels) } func loadConfigFromFlags() *config.Config { diff --git a/pkg/dynamiclabels/dynamic_labels.go b/pkg/dynamiclabels/dynamic_labels.go new file mode 100644 index 0000000..aab3f77 --- /dev/null +++ b/pkg/dynamiclabels/dynamic_labels.go @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT + +package dynamiclabels + +import ( + "regexp" + "strings" +) + +var ( + nameRe *regexp.Regexp +) + +func init() { + nameRe = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_]*$`) +} + +func DefaultInterfaceDescRegex() *regexp.Regexp { + return regexp.MustCompile(`\[([^=\]]+)(=[^\]]+)?\]`) +} + +type Label struct { + name string + value string +} + +func (il *Label) Name() string { + return il.name +} + +func (il *Label) Value() string { + return il.value +} + +func ParseDescription(description string, ifDescReg *regexp.Regexp) Labels { + labels := make(Labels, 0) + + if len(description) == 0 || ifDescReg == nil { + return labels + } + + matches := ifDescReg.FindAllStringSubmatch(description, -1) + for _, m := range matches { + n := strings.ToLower(m[1]) + + if !nameRe.Match([]byte(n)) { + continue + } + + label := &Label{ + name: n, + } + + val := m[2] + + if strings.HasPrefix(val, "=") { + label.value = val[1:] + } else { + label.value = "1" + } + + labels = append(labels, label) + } + + return labels +} + +type Labels []*Label + +func (ils Labels) Keys() []string { + ret := make([]string, 0, len(ils)) + for _, il := range ils { + ret = append(ret, il.name) + } + + return ret +} + +func (ils Labels) Values() []string { + ret := make([]string, 0, len(ils)) + for _, il := range ils { + ret = append(ret, il.value) + } + + return ret +} diff --git a/pkg/dynamiclabels/dynamic_labels_test.go b/pkg/dynamiclabels/dynamic_labels_test.go new file mode 100644 index 0000000..b639f38 --- /dev/null +++ b/pkg/dynamiclabels/dynamic_labels_test.go @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT + +package dynamiclabels + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParseDescriptions(t *testing.T) { + tests := []struct { + name string + description string + keys []string + values []string + }{ + { + name: "tags and kv pairs", + description: "Name1 [tag1] [foo=x]", + keys: []string{"tag1", "foo"}, + values: []string{"1", "x"}, + }, + { + name: "kv pairs", + description: "Name2 [foo=y] [bar=123]", + keys: []string{"foo", "bar"}, + values: []string{"y", "123"}, + }, + { + name: "empty", + description: "", + keys: []string{}, + values: []string{}, + }, + { + name: "more kv pairs", + description: "Internal: Test-Network [vrf=AS4711]", + keys: []string{"vrf"}, + values: []string{"AS4711"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ifLabels := ParseDescription(test.description, DefaultInterfaceDescRegex()) + assert.Equal(t, test.keys, ifLabels.Keys(), test.name) + assert.Equal(t, test.values, ifLabels.Values(), test.name) + }) + } +} diff --git a/pkg/features/bgp/collector.go b/pkg/features/bgp/collector.go index 3d5e47c..e408196 100644 --- a/pkg/features/bgp/collector.go +++ b/pkg/features/bgp/collector.go @@ -8,7 +8,7 @@ import ( "regexp" "github.com/czerwonk/junos_exporter/pkg/collector" - "github.com/czerwonk/junos_exporter/pkg/interfacelabels" + "github.com/czerwonk/junos_exporter/pkg/dynamiclabels" "github.com/prometheus/client_golang/prometheus" "strings" @@ -35,7 +35,7 @@ type description struct { holdTimeDesc *prometheus.Desc } -func newDescriptions(dynLabels interfacelabels.InterfaceLabels) *description { +func newDescriptions(dynLabels dynamiclabels.Labels) *description { d := &description{} l := []string{"target", "asn", "ip", "description", "group"} @@ -174,7 +174,7 @@ func (c *bgpCollector) collectForPeer(p peer, groups groupMap, ch chan<- prometh up = 1 } - dynLabels := interfacelabels.ParseDescription(p.Description, c.descriptionRe) + dynLabels := dynamiclabels.ParseDescription(p.Description, c.descriptionRe) lv = append(lv, dynLabels.Values()...) d := newDescriptions(dynLabels) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 77056b4..7a8666b 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -6,72 +6,123 @@ import ( "encoding/xml" "fmt" "log" + "regexp" "strings" - "github.com/czerwonk/junos_exporter/pkg/interfacelabels" - "github.com/czerwonk/junos_exporter/pkg/collector" + "github.com/czerwonk/junos_exporter/pkg/dynamiclabels" "github.com/prometheus/client_golang/prometheus" ) const prefix = "junos_interface_diagnostics_" -type interfaceDiagnosticsCollector struct { - labels *interfacelabels.DynamicLabelManager - laserBiasCurrentDesc *prometheus.Desc - laserBiasCurrentHighAlarmThresholdDesc *prometheus.Desc - laserBiasCurrentLowAlarmThresholdDesc *prometheus.Desc - laserBiasCurrentHighWarnThresholdDesc *prometheus.Desc - laserBiasCurrentLowWarnThresholdDesc *prometheus.Desc - - laserOutputPowerDesc *prometheus.Desc - laserOutputPowerHighAlarmThresholdDesc *prometheus.Desc - laserOutputPowerLowAlarmThresholdDesc *prometheus.Desc - laserOutputPowerHighWarnThresholdDesc *prometheus.Desc - laserOutputPowerLowWarnThresholdDesc *prometheus.Desc - - laserOutputPowerDbmDesc *prometheus.Desc - laserOutputPowerHighAlarmThresholdDbmDesc *prometheus.Desc - laserOutputPowerLowAlarmThresholdDbmDesc *prometheus.Desc - laserOutputPowerHighWarnThresholdDbmDesc *prometheus.Desc - laserOutputPowerLowWarnThresholdDbmDesc *prometheus.Desc - - moduleTemperatureDesc *prometheus.Desc - moduleTemperatureHighAlarmThresholdDesc *prometheus.Desc - moduleTemperatureLowAlarmThresholdDesc *prometheus.Desc - moduleTemperatureHighWarnThresholdDesc *prometheus.Desc - moduleTemperatureLowWarnThresholdDesc *prometheus.Desc - - laserRxOpticalPowerDesc *prometheus.Desc - laserRxOpticalPowerHighAlarmThresholdDesc *prometheus.Desc - laserRxOpticalPowerLowAlarmThresholdDesc *prometheus.Desc - laserRxOpticalPowerHighWarnThresholdDesc *prometheus.Desc - laserRxOpticalPowerLowWarnThresholdDesc *prometheus.Desc - +type description struct { + laserBiasCurrentDesc *prometheus.Desc + laserBiasCurrentHighAlarmThresholdDesc *prometheus.Desc + laserBiasCurrentLowAlarmThresholdDesc *prometheus.Desc + laserBiasCurrentHighWarnThresholdDesc *prometheus.Desc + laserBiasCurrentLowWarnThresholdDesc *prometheus.Desc + laserOutputPowerDesc *prometheus.Desc + laserOutputPowerHighAlarmThresholdDesc *prometheus.Desc + laserOutputPowerLowAlarmThresholdDesc *prometheus.Desc + laserOutputPowerHighWarnThresholdDesc *prometheus.Desc + laserOutputPowerLowWarnThresholdDesc *prometheus.Desc + laserOutputPowerDbmDesc *prometheus.Desc + laserOutputPowerHighAlarmThresholdDbmDesc *prometheus.Desc + laserOutputPowerLowAlarmThresholdDbmDesc *prometheus.Desc + laserOutputPowerHighWarnThresholdDbmDesc *prometheus.Desc + laserOutputPowerLowWarnThresholdDbmDesc *prometheus.Desc + moduleTemperatureDesc *prometheus.Desc + moduleTemperatureHighAlarmThresholdDesc *prometheus.Desc + moduleTemperatureLowAlarmThresholdDesc *prometheus.Desc + moduleTemperatureHighWarnThresholdDesc *prometheus.Desc + moduleTemperatureLowWarnThresholdDesc *prometheus.Desc + laserRxOpticalPowerDesc *prometheus.Desc + laserRxOpticalPowerHighAlarmThresholdDesc *prometheus.Desc + laserRxOpticalPowerLowAlarmThresholdDesc *prometheus.Desc + laserRxOpticalPowerHighWarnThresholdDesc *prometheus.Desc + laserRxOpticalPowerLowWarnThresholdDesc *prometheus.Desc laserRxOpticalPowerDbmDesc *prometheus.Desc laserRxOpticalPowerHighAlarmThresholdDbmDesc *prometheus.Desc laserRxOpticalPowerLowAlarmThresholdDbmDesc *prometheus.Desc laserRxOpticalPowerHighWarnThresholdDbmDesc *prometheus.Desc laserRxOpticalPowerLowWarnThresholdDbmDesc *prometheus.Desc + moduleVoltageDesc *prometheus.Desc + moduleVoltageHighAlarmThresholdDesc *prometheus.Desc + moduleVoltageLowAlarmThresholdDesc *prometheus.Desc + moduleVoltageHighWarnThresholdDesc *prometheus.Desc + moduleVoltageLowWarnThresholdDesc *prometheus.Desc + rxSignalAvgOpticalPowerDesc *prometheus.Desc + rxSignalAvgOpticalPowerDbmDesc *prometheus.Desc + transceiverDesc *prometheus.Desc +} + +func newDescriptions(dynLabels dynamiclabels.Labels) *description { + d := &description{} + + l := []string{"target", "name"} + l = append(l, dynLabels.Keys()...) + + d.moduleVoltageDesc = prometheus.NewDesc(prefix+"module_voltage", "Module voltage", l, nil) + d.moduleVoltageHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_high_alarm_threshold", "Module voltage high alarm threshold", l, nil) + d.moduleVoltageLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_low_alarm_threshold", "Module voltage low alarm threshold", l, nil) + d.moduleVoltageHighWarnThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_high_warn_threshold", "Module voltage high warn threshold", l, nil) + d.moduleVoltageLowWarnThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_low_warn_threshold", "Module voltage low warn threshold", l, nil) + + d.moduleTemperatureDesc = prometheus.NewDesc(prefix+"temp", "Module temperature in degrees Celsius", l, nil) + d.moduleTemperatureHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"temp_high_alarm_threshold", "Module temperature high alarm threshold in degrees Celsius", l, nil) + d.moduleTemperatureLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"temp_low_alarm_threshold", "Module temperature low alarm threshold in degrees Celsius", l, nil) + d.moduleTemperatureHighWarnThresholdDesc = prometheus.NewDesc(prefix+"temp_high_warn_threshold", "Module temperature high warn threshold in degrees Celsius", l, nil) + d.moduleTemperatureLowWarnThresholdDesc = prometheus.NewDesc(prefix+"temp_low_warn_threshold", "Module temperature low warn threshold in degrees Celsius", l, nil) + + d.rxSignalAvgOpticalPowerDesc = prometheus.NewDesc(prefix+"rx_signal_avg", "Receiver signal average optical power in mW", l, nil) + d.rxSignalAvgOpticalPowerDbmDesc = prometheus.NewDesc(prefix+"rx_signal_avg_dbm", "Receiver signal average optical power in mW", l, nil) - moduleVoltageDesc *prometheus.Desc - moduleVoltageHighAlarmThresholdDesc *prometheus.Desc - moduleVoltageLowAlarmThresholdDesc *prometheus.Desc - moduleVoltageHighWarnThresholdDesc *prometheus.Desc - moduleVoltageLowWarnThresholdDesc *prometheus.Desc + l = append(l, "lane") + d.laserBiasCurrentDesc = prometheus.NewDesc(prefix+"laser_bias", "Laser bias current in mA", l, nil) + d.laserBiasCurrentHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_high_alarm_threshold", "Laser bias current high alarm threshold", l, nil) + d.laserBiasCurrentLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_low_alarm_threshold", "Laser bias current low alarm threshold", l, nil) + d.laserBiasCurrentHighWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_high_warn_threshold", "Laser bias current high warn threshold", l, nil) + d.laserBiasCurrentLowWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_low_warn_threshold", "Laser bias current low warn threshold", l, nil) + d.laserOutputPowerDesc = prometheus.NewDesc(prefix+"laser_output", "Laser output power in mW", l, nil) + d.laserOutputPowerHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_output_high_alarm_threshold", "Laser output power high alarm threshold in mW", l, nil) + d.laserOutputPowerLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_output_low_alarm_threshold", "Laser output power low alarm threshold in mW", l, nil) + d.laserOutputPowerHighWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_output_high_warn_threshold", "Laser output power high warn threshold in mW", l, nil) + d.laserOutputPowerLowWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_output_low_warn_threshold", "Laser output power low warn threshold in mW", l, nil) + + d.laserOutputPowerDbmDesc = prometheus.NewDesc(prefix+"laser_output_dbm", "Laser output power in dBm", l, nil) + d.laserOutputPowerHighAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_high_alarm_threshold_dbm", "Laser output power high alarm threshold in dBm", l, nil) + d.laserOutputPowerLowAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_low_alarm_threshold_dbm", "Laser output power low alarm threshold in dBm", l, nil) + d.laserOutputPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_high_warn_threshold_dbm", "Laser output power high warn threshold in dBm", l, nil) + d.laserOutputPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_low_warn_threshold_dbm", "Laser output power low warn threshold in dBm", l, nil) + + d.laserRxOpticalPowerDesc = prometheus.NewDesc(prefix+"laser_rx", "Laser rx power in mW", l, nil) + d.laserRxOpticalPowerHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_high_alarm_threshold", "Laser rx power high alarm threshold in mW", l, nil) + d.laserRxOpticalPowerLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_low_alarm_threshold", "Laser rx power low alarm threshold in mW", l, nil) + d.laserRxOpticalPowerHighWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold", "Laser rx power high warn threshold in mW", l, nil) + d.laserRxOpticalPowerLowWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold", "Laser rx power low warn threshold in mW", l, nil) + + d.laserRxOpticalPowerDbmDesc = prometheus.NewDesc(prefix+"laser_rx_dbm", "Laser rx power in dBm", l, nil) + d.laserRxOpticalPowerHighAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_alarm_threshold_dbm", "Laser rx power high alarm threshold_dbm in dBm", l, nil) + d.laserRxOpticalPowerLowAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_alarm_threshold_dbm", "Laser rx power low alarm threshold_dbm in dBm", l, nil) + d.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) + d.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - rxSignalAvgOpticalPowerDesc *prometheus.Desc - rxSignalAvgOpticalPowerDbmDesc *prometheus.Desc + transceiver_labels := []string{"target", "name", "serial_number", "description", "speed", "fiber_type", "vendor_name", "vendor_part_number", "wavelength"} + d.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) - transceiverDesc *prometheus.Desc + return d +} + +type interfaceDiagnosticsCollector struct { + descriptionRe *regexp.Regexp } // NewCollector creates a new collector -func NewCollector(labels *interfacelabels.DynamicLabelManager) collector.RPCCollector { +func NewCollector(descriptionRe *regexp.Regexp) collector.RPCCollector { c := &interfaceDiagnosticsCollector{ - labels: labels, + descriptionRe: descriptionRe, } - c.init() return c } @@ -81,103 +132,52 @@ func (*interfaceDiagnosticsCollector) Name() string { return "Interface Diagnostics" } -func (c *interfaceDiagnosticsCollector) init() { - l := []string{"target", "name"} - l = append(l, c.labels.LabelNames()...) - - c.moduleVoltageDesc = prometheus.NewDesc(prefix+"module_voltage", "Module voltage", l, nil) - c.moduleVoltageHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_high_alarm_threshold", "Module voltage high alarm threshold", l, nil) - c.moduleVoltageLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_low_alarm_threshold", "Module voltage low alarm threshold", l, nil) - c.moduleVoltageHighWarnThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_high_warn_threshold", "Module voltage high warn threshold", l, nil) - c.moduleVoltageLowWarnThresholdDesc = prometheus.NewDesc(prefix+"module_voltage_low_warn_threshold", "Module voltage low warn threshold", l, nil) - - c.moduleTemperatureDesc = prometheus.NewDesc(prefix+"temp", "Module temperature in degrees Celsius", l, nil) - c.moduleTemperatureHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"temp_high_alarm_threshold", "Module temperature high alarm threshold in degrees Celsius", l, nil) - c.moduleTemperatureLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"temp_low_alarm_threshold", "Module temperature low alarm threshold in degrees Celsius", l, nil) - c.moduleTemperatureHighWarnThresholdDesc = prometheus.NewDesc(prefix+"temp_high_warn_threshold", "Module temperature high warn threshold in degrees Celsius", l, nil) - c.moduleTemperatureLowWarnThresholdDesc = prometheus.NewDesc(prefix+"temp_low_warn_threshold", "Module temperature low warn threshold in degrees Celsius", l, nil) - - c.rxSignalAvgOpticalPowerDesc = prometheus.NewDesc(prefix+"rx_signal_avg", "Receiver signal average optical power in mW", l, nil) - c.rxSignalAvgOpticalPowerDbmDesc = prometheus.NewDesc(prefix+"rx_signal_avg_dbm", "Receiver signal average optical power in mW", l, nil) - - l = append(l, "lane") - c.laserBiasCurrentDesc = prometheus.NewDesc(prefix+"laser_bias", "Laser bias current in mA", l, nil) - c.laserBiasCurrentHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_high_alarm_threshold", "Laser bias current high alarm threshold", l, nil) - c.laserBiasCurrentLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_low_alarm_threshold", "Laser bias current low alarm threshold", l, nil) - c.laserBiasCurrentHighWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_high_warn_threshold", "Laser bias current high warn threshold", l, nil) - c.laserBiasCurrentLowWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_bias_low_warn_threshold", "Laser bias current low warn threshold", l, nil) - c.laserOutputPowerDesc = prometheus.NewDesc(prefix+"laser_output", "Laser output power in mW", l, nil) - c.laserOutputPowerHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_output_high_alarm_threshold", "Laser output power high alarm threshold in mW", l, nil) - c.laserOutputPowerLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_output_low_alarm_threshold", "Laser output power low alarm threshold in mW", l, nil) - c.laserOutputPowerHighWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_output_high_warn_threshold", "Laser output power high warn threshold in mW", l, nil) - c.laserOutputPowerLowWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_output_low_warn_threshold", "Laser output power low warn threshold in mW", l, nil) - - c.laserOutputPowerDbmDesc = prometheus.NewDesc(prefix+"laser_output_dbm", "Laser output power in dBm", l, nil) - c.laserOutputPowerHighAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_high_alarm_threshold_dbm", "Laser output power high alarm threshold in dBm", l, nil) - c.laserOutputPowerLowAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_low_alarm_threshold_dbm", "Laser output power low alarm threshold in dBm", l, nil) - c.laserOutputPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_high_warn_threshold_dbm", "Laser output power high warn threshold in dBm", l, nil) - c.laserOutputPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_output_low_warn_threshold_dbm", "Laser output power low warn threshold in dBm", l, nil) - - c.laserRxOpticalPowerDesc = prometheus.NewDesc(prefix+"laser_rx", "Laser rx power in mW", l, nil) - c.laserRxOpticalPowerHighAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_high_alarm_threshold", "Laser rx power high alarm threshold in mW", l, nil) - c.laserRxOpticalPowerLowAlarmThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_low_alarm_threshold", "Laser rx power low alarm threshold in mW", l, nil) - c.laserRxOpticalPowerHighWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold", "Laser rx power high warn threshold in mW", l, nil) - c.laserRxOpticalPowerLowWarnThresholdDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold", "Laser rx power low warn threshold in mW", l, nil) - - c.laserRxOpticalPowerDbmDesc = prometheus.NewDesc(prefix+"laser_rx_dbm", "Laser rx power in dBm", l, nil) - c.laserRxOpticalPowerHighAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_alarm_threshold_dbm", "Laser rx power high alarm threshold_dbm in dBm", l, nil) - c.laserRxOpticalPowerLowAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_alarm_threshold_dbm", "Laser rx power low alarm threshold_dbm in dBm", l, nil) - c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) - c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - - transceiver_labels := []string{"target", "name", "serial_number", "description", "speed", "fiber_type", "vendor_name", "vendor_part_number", "wavelength"} - c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) -} - // Describe describes the metrics func (c *interfaceDiagnosticsCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- c.laserBiasCurrentDesc - ch <- c.laserBiasCurrentHighAlarmThresholdDesc - ch <- c.laserBiasCurrentLowAlarmThresholdDesc - ch <- c.laserBiasCurrentHighWarnThresholdDesc - ch <- c.laserBiasCurrentLowWarnThresholdDesc - ch <- c.laserOutputPowerDesc - ch <- c.laserOutputPowerHighAlarmThresholdDesc - ch <- c.laserOutputPowerLowAlarmThresholdDesc - ch <- c.laserOutputPowerHighWarnThresholdDesc - ch <- c.laserOutputPowerLowWarnThresholdDesc - ch <- c.laserOutputPowerDbmDesc - ch <- c.laserOutputPowerHighAlarmThresholdDbmDesc - ch <- c.laserOutputPowerLowAlarmThresholdDbmDesc - ch <- c.laserOutputPowerHighWarnThresholdDbmDesc - ch <- c.laserOutputPowerLowWarnThresholdDbmDesc - ch <- c.moduleTemperatureDesc - ch <- c.moduleTemperatureHighAlarmThresholdDesc - ch <- c.moduleTemperatureLowAlarmThresholdDesc - ch <- c.moduleTemperatureHighWarnThresholdDesc - ch <- c.moduleTemperatureLowWarnThresholdDesc - - ch <- c.laserRxOpticalPowerDesc - ch <- c.laserRxOpticalPowerHighAlarmThresholdDesc - ch <- c.laserRxOpticalPowerLowAlarmThresholdDesc - ch <- c.laserRxOpticalPowerHighWarnThresholdDesc - ch <- c.laserRxOpticalPowerLowWarnThresholdDesc - ch <- c.laserRxOpticalPowerDbmDesc - ch <- c.laserRxOpticalPowerHighAlarmThresholdDbmDesc - ch <- c.laserRxOpticalPowerLowAlarmThresholdDbmDesc - ch <- c.laserRxOpticalPowerHighWarnThresholdDbmDesc - ch <- c.laserRxOpticalPowerLowWarnThresholdDbmDesc - - ch <- c.moduleVoltageDesc - ch <- c.moduleVoltageHighAlarmThresholdDesc - ch <- c.moduleVoltageLowAlarmThresholdDesc - ch <- c.moduleVoltageHighWarnThresholdDesc - ch <- c.moduleVoltageLowWarnThresholdDesc - - ch <- c.rxSignalAvgOpticalPowerDesc - ch <- c.rxSignalAvgOpticalPowerDbmDesc - - ch <- c.transceiverDesc + d := newDescriptions(nil) + + ch <- d.laserBiasCurrentDesc + ch <- d.laserBiasCurrentHighAlarmThresholdDesc + ch <- d.laserBiasCurrentLowAlarmThresholdDesc + ch <- d.laserBiasCurrentHighWarnThresholdDesc + ch <- d.laserBiasCurrentLowWarnThresholdDesc + ch <- d.laserOutputPowerDesc + ch <- d.laserOutputPowerHighAlarmThresholdDesc + ch <- d.laserOutputPowerLowAlarmThresholdDesc + ch <- d.laserOutputPowerHighWarnThresholdDesc + ch <- d.laserOutputPowerLowWarnThresholdDesc + ch <- d.laserOutputPowerDbmDesc + ch <- d.laserOutputPowerHighAlarmThresholdDbmDesc + ch <- d.laserOutputPowerLowAlarmThresholdDbmDesc + ch <- d.laserOutputPowerHighWarnThresholdDbmDesc + ch <- d.laserOutputPowerLowWarnThresholdDbmDesc + ch <- d.moduleTemperatureDesc + ch <- d.moduleTemperatureHighAlarmThresholdDesc + ch <- d.moduleTemperatureLowAlarmThresholdDesc + ch <- d.moduleTemperatureHighWarnThresholdDesc + ch <- d.moduleTemperatureLowWarnThresholdDesc + + ch <- d.laserRxOpticalPowerDesc + ch <- d.laserRxOpticalPowerHighAlarmThresholdDesc + ch <- d.laserRxOpticalPowerLowAlarmThresholdDesc + ch <- d.laserRxOpticalPowerHighWarnThresholdDesc + ch <- d.laserRxOpticalPowerLowWarnThresholdDesc + ch <- d.laserRxOpticalPowerDbmDesc + ch <- d.laserRxOpticalPowerHighAlarmThresholdDbmDesc + ch <- d.laserRxOpticalPowerLowAlarmThresholdDbmDesc + ch <- d.laserRxOpticalPowerHighWarnThresholdDbmDesc + ch <- d.laserRxOpticalPowerLowWarnThresholdDbmDesc + + ch <- d.moduleVoltageDesc + ch <- d.moduleVoltageHighAlarmThresholdDesc + ch <- d.moduleVoltageLowAlarmThresholdDesc + ch <- d.moduleVoltageHighWarnThresholdDesc + ch <- d.moduleVoltageLowWarnThresholdDesc + + ch <- d.rxSignalAvgOpticalPowerDesc + ch <- d.rxSignalAvgOpticalPowerDbmDesc + + ch <- d.transceiverDesc } // Collect collects metrics from JunOS @@ -196,72 +196,86 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan diagnostics = append(diagnostics, diagnosticsSatellite...) } - diagnostics_dict := make(map[string]*interfaceDiagnostics) + diagnosticsDict := make(map[string]*interfaceDiagnostics) - for _, d := range diagnostics { - index := strings.Split(d.Name, "-")[1] - diagnostics_dict[index] = d + ifMediaDict, err := c.interfaceMediaInfo(client) + if err != nil { + return err + } - l := append(labelValues, d.Name) - l = append(l, c.labels.ValuesForInterface(client.Device(), d.Name)...) + for _, diag := range diagnostics { + index := strings.Split(diag.Name, "-")[1] + diagnosticsDict[index] = diag - ch <- prometheus.MustNewConstMetric(c.moduleTemperatureDesc, prometheus.GaugeValue, d.ModuleTemperature, l...) - ch <- prometheus.MustNewConstMetric(c.moduleTemperatureHighAlarmThresholdDesc, prometheus.GaugeValue, d.ModuleTemperatureHighAlarmThreshold, l...) - ch <- prometheus.MustNewConstMetric(c.moduleTemperatureLowAlarmThresholdDesc, prometheus.GaugeValue, d.ModuleTemperatureLowAlarmThreshold, l...) - ch <- prometheus.MustNewConstMetric(c.moduleTemperatureHighWarnThresholdDesc, prometheus.GaugeValue, d.ModuleTemperatureHighWarnThreshold, l...) - ch <- prometheus.MustNewConstMetric(c.moduleTemperatureLowWarnThresholdDesc, prometheus.GaugeValue, d.ModuleTemperatureLowWarnThreshold, l...) + desc := "" + media := ifMediaDict[slotIndex(diag.Name)] + if media != nil { + desc = media.Description + } - if d.ModuleVoltage > 0 { - ch <- prometheus.MustNewConstMetric(c.moduleVoltageDesc, prometheus.GaugeValue, d.ModuleVoltage, l...) - ch <- prometheus.MustNewConstMetric(c.moduleVoltageHighAlarmThresholdDesc, prometheus.GaugeValue, d.ModuleVoltageHighAlarmThreshold, l...) - ch <- prometheus.MustNewConstMetric(c.moduleVoltageLowAlarmThresholdDesc, prometheus.GaugeValue, d.ModuleVoltageLowAlarmThreshold, l...) - ch <- prometheus.MustNewConstMetric(c.moduleVoltageHighWarnThresholdDesc, prometheus.GaugeValue, d.ModuleVoltageHighWarnThreshold, l...) - ch <- prometheus.MustNewConstMetric(c.moduleVoltageLowWarnThresholdDesc, prometheus.GaugeValue, d.ModuleVoltageLowWarnThreshold, l...) + dynLabels := dynamiclabels.ParseDescription(desc, c.descriptionRe) + d := newDescriptions(dynLabels) + + l := append(labelValues, diag.Name) + l = append(l, dynLabels.Values()...) + + ch <- prometheus.MustNewConstMetric(d.moduleTemperatureDesc, prometheus.GaugeValue, diag.ModuleTemperature, l...) + ch <- prometheus.MustNewConstMetric(d.moduleTemperatureHighAlarmThresholdDesc, prometheus.GaugeValue, diag.ModuleTemperatureHighAlarmThreshold, l...) + ch <- prometheus.MustNewConstMetric(d.moduleTemperatureLowAlarmThresholdDesc, prometheus.GaugeValue, diag.ModuleTemperatureLowAlarmThreshold, l...) + ch <- prometheus.MustNewConstMetric(d.moduleTemperatureHighWarnThresholdDesc, prometheus.GaugeValue, diag.ModuleTemperatureHighWarnThreshold, l...) + ch <- prometheus.MustNewConstMetric(d.moduleTemperatureLowWarnThresholdDesc, prometheus.GaugeValue, diag.ModuleTemperatureLowWarnThreshold, l...) + + if diag.ModuleVoltage > 0 { + ch <- prometheus.MustNewConstMetric(d.moduleVoltageDesc, prometheus.GaugeValue, diag.ModuleVoltage, l...) + ch <- prometheus.MustNewConstMetric(d.moduleVoltageHighAlarmThresholdDesc, prometheus.GaugeValue, diag.ModuleVoltageHighAlarmThreshold, l...) + ch <- prometheus.MustNewConstMetric(d.moduleVoltageLowAlarmThresholdDesc, prometheus.GaugeValue, diag.ModuleVoltageLowAlarmThreshold, l...) + ch <- prometheus.MustNewConstMetric(d.moduleVoltageHighWarnThresholdDesc, prometheus.GaugeValue, diag.ModuleVoltageHighWarnThreshold, l...) + ch <- prometheus.MustNewConstMetric(d.moduleVoltageLowWarnThresholdDesc, prometheus.GaugeValue, diag.ModuleVoltageLowWarnThreshold, l...) } - if d.RxSignalAvgOpticalPower > 0 { - ch <- prometheus.MustNewConstMetric(c.rxSignalAvgOpticalPowerDesc, prometheus.GaugeValue, d.RxSignalAvgOpticalPower, l...) - ch <- prometheus.MustNewConstMetric(c.rxSignalAvgOpticalPowerDbmDesc, prometheus.GaugeValue, d.RxSignalAvgOpticalPowerDbm, l...) + if diag.RxSignalAvgOpticalPower > 0 { + ch <- prometheus.MustNewConstMetric(d.rxSignalAvgOpticalPowerDesc, prometheus.GaugeValue, diag.RxSignalAvgOpticalPower, l...) + ch <- prometheus.MustNewConstMetric(d.rxSignalAvgOpticalPowerDbmDesc, prometheus.GaugeValue, diag.RxSignalAvgOpticalPowerDbm, l...) } var data []*interfaceDiagnostics - if len(d.Lanes) > 0 { - data = d.Lanes + if len(diag.Lanes) > 0 { + data = diag.Lanes } else { - data = []*interfaceDiagnostics{d} + data = []*interfaceDiagnostics{diag} } for _, e := range data { l2 := append(l, e.Index) - ch <- prometheus.MustNewConstMetric(c.laserBiasCurrentDesc, prometheus.GaugeValue, e.LaserBiasCurrent, l2...) - ch <- prometheus.MustNewConstMetric(c.laserBiasCurrentHighAlarmThresholdDesc, prometheus.GaugeValue, d.LaserBiasCurrentHighAlarmThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserBiasCurrentLowAlarmThresholdDesc, prometheus.GaugeValue, d.LaserBiasCurrentLowAlarmThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserBiasCurrentHighWarnThresholdDesc, prometheus.GaugeValue, d.LaserBiasCurrentHighWarnThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserBiasCurrentLowWarnThresholdDesc, prometheus.GaugeValue, d.LaserBiasCurrentLowWarnThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerDesc, prometheus.GaugeValue, e.LaserOutputPower, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerHighAlarmThresholdDesc, prometheus.GaugeValue, d.LaserOutputPowerHighAlarmThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerLowAlarmThresholdDesc, prometheus.GaugeValue, d.LaserOutputPowerLowAlarmThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerHighWarnThresholdDesc, prometheus.GaugeValue, d.LaserOutputPowerHighWarnThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerLowWarnThresholdDesc, prometheus.GaugeValue, d.LaserOutputPowerLowWarnThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerDbmDesc, prometheus.GaugeValue, e.LaserOutputPowerDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerHighAlarmThresholdDbmDesc, prometheus.GaugeValue, d.LaserOutputPowerHighAlarmThresholdDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerLowAlarmThresholdDbmDesc, prometheus.GaugeValue, d.LaserOutputPowerLowAlarmThresholdDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerHighWarnThresholdDbmDesc, prometheus.GaugeValue, d.LaserOutputPowerHighWarnThresholdDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserOutputPowerLowWarnThresholdDbmDesc, prometheus.GaugeValue, d.LaserOutputPowerLowWarnThresholdDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerDesc, prometheus.GaugeValue, e.LaserRxOpticalPower, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerHighAlarmThresholdDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerHighAlarmThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerLowAlarmThresholdDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerLowAlarmThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerHighWarnThresholdDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerHighWarnThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerLowWarnThresholdDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerLowWarnThreshold, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerDbmDesc, prometheus.GaugeValue, e.LaserRxOpticalPowerDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerHighAlarmThresholdDbmDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerHighAlarmThresholdDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerLowAlarmThresholdDbmDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerLowAlarmThresholdDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerHighWarnThresholdDbmDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerHighWarnThresholdDbm, l2...) - ch <- prometheus.MustNewConstMetric(c.laserRxOpticalPowerLowWarnThresholdDbmDesc, prometheus.GaugeValue, d.LaserRxOpticalPowerLowWarnThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserBiasCurrentDesc, prometheus.GaugeValue, e.LaserBiasCurrent, l2...) + ch <- prometheus.MustNewConstMetric(d.laserBiasCurrentHighAlarmThresholdDesc, prometheus.GaugeValue, diag.LaserBiasCurrentHighAlarmThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserBiasCurrentLowAlarmThresholdDesc, prometheus.GaugeValue, diag.LaserBiasCurrentLowAlarmThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserBiasCurrentHighWarnThresholdDesc, prometheus.GaugeValue, diag.LaserBiasCurrentHighWarnThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserBiasCurrentLowWarnThresholdDesc, prometheus.GaugeValue, diag.LaserBiasCurrentLowWarnThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerDesc, prometheus.GaugeValue, e.LaserOutputPower, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerHighAlarmThresholdDesc, prometheus.GaugeValue, diag.LaserOutputPowerHighAlarmThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerLowAlarmThresholdDesc, prometheus.GaugeValue, diag.LaserOutputPowerLowAlarmThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerHighWarnThresholdDesc, prometheus.GaugeValue, diag.LaserOutputPowerHighWarnThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerLowWarnThresholdDesc, prometheus.GaugeValue, diag.LaserOutputPowerLowWarnThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerDbmDesc, prometheus.GaugeValue, e.LaserOutputPowerDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerHighAlarmThresholdDbmDesc, prometheus.GaugeValue, diag.LaserOutputPowerHighAlarmThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerLowAlarmThresholdDbmDesc, prometheus.GaugeValue, diag.LaserOutputPowerLowAlarmThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerHighWarnThresholdDbmDesc, prometheus.GaugeValue, diag.LaserOutputPowerHighWarnThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserOutputPowerLowWarnThresholdDbmDesc, prometheus.GaugeValue, diag.LaserOutputPowerLowWarnThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerDesc, prometheus.GaugeValue, e.LaserRxOpticalPower, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerHighAlarmThresholdDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerHighAlarmThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerLowAlarmThresholdDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerLowAlarmThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerHighWarnThresholdDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerHighWarnThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerLowWarnThresholdDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerLowWarnThreshold, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerDbmDesc, prometheus.GaugeValue, e.LaserRxOpticalPowerDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerHighAlarmThresholdDbmDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerHighAlarmThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerLowAlarmThresholdDbmDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerLowAlarmThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerHighWarnThresholdDbmDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerHighWarnThresholdDbm, l2...) + ch <- prometheus.MustNewConstMetric(d.laserRxOpticalPowerLowWarnThresholdDbmDesc, prometheus.GaugeValue, diag.LaserRxOpticalPowerLowWarnThresholdDbm, l2...) } } - err = c.createTransceiverMetrics(client, ch, labelValues) + err = c.createTransceiverMetrics(client, ch, labelValues, ifMediaDict) if err != nil { return err } @@ -327,7 +341,7 @@ func (c *interfaceDiagnosticsCollector) transceiverInfoFromRPCResult(client coll } func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client collector.Client, fpc string, pic string) ([]picPort, error) { - var x = fPCInformationStruct{} + var x = fpcInformationStruct{} command := fmt.Sprintf("show chassis pic fpc-slot %s pic-slot %s", fpc, pic) err := client.RunCommandAndParse(command, &x) if err != nil { @@ -337,12 +351,7 @@ func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client collecto return x.FPCInformation.FPC.PicDetail.PicPortInfoList, nil } -func (c *interfaceDiagnosticsCollector) createTransceiverMetrics(client collector.Client, ch chan<- prometheus.Metric, labelValues []string) error { - ifMediaDict, err := c.interfaceMediaInfo(client) - if err != nil { - return err - } - +func (c *interfaceDiagnosticsCollector) createTransceiverMetrics(client collector.Client, ch chan<- prometheus.Metric, labelValues []string, ifMediaDict map[string]*physicalInterface) error { transceiverInfo, err := c.chassisHardwareInfos(client) if err != nil { return err @@ -365,7 +374,9 @@ func (c *interfaceDiagnosticsCollector) createTransceiverMetrics(client collecto transceiver_labels := append(labelValues, t.Name, chassisInfo.SerialNumber, chassisInfo.Description, port_speed, t.PicPort.FiberMode, strings.TrimSpace(t.PicPort.SFPVendorName), strings.TrimSpace(t.PicPort.SFPVendorPno), t.PicPort.Wavelength) - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, oper_status, transceiver_labels...) + d := newDescriptions(nil) + + ch <- prometheus.MustNewConstMetric(d.transceiverDesc, prometheus.GaugeValue, oper_status, transceiver_labels...) } return nil diff --git a/pkg/features/interfacediagnostics/helper.go b/pkg/features/interfacediagnostics/helper.go index 01ced0b..b71259b 100644 --- a/pkg/features/interfacediagnostics/helper.go +++ b/pkg/features/interfacediagnostics/helper.go @@ -111,10 +111,13 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma for _, i := range *interfaceMediaList { if strings.HasPrefix(i.Name, "xe") || strings.HasPrefix(i.Name, "ge") || strings.HasPrefix(i.Name, "et") { iface := i - slotIndex := iface.Name[3:] - interfaceMediaDict[slotIndex] = &iface + interfaceMediaDict[slotIndex(iface.Name)] = &iface } } return interfaceMediaDict } + +func slotIndex(ifName string) string { + return ifName[3:] +} diff --git a/pkg/features/interfacediagnostics/rpc.go b/pkg/features/interfacediagnostics/rpc.go index 8fec751..cd7676a 100644 --- a/pkg/features/interfacediagnostics/rpc.go +++ b/pkg/features/interfacediagnostics/rpc.go @@ -2,14 +2,14 @@ package interfacediagnostics -type fPCInformationStruct struct { - FPCInformation fPCInformation `xml:"fpc-information"` +type fpcInformationStruct struct { + FPCInformation fpcInformation `xml:"fpc-information"` } -type fPCInformation struct { - FPC fPC `xml:"fpc"` +type fpcInformation struct { + FPC fpc `xml:"fpc"` } -type fPC struct { +type fpc struct { PicDetail picDetail `xml:"pic-detail"` } @@ -46,6 +46,7 @@ type physicalInterface struct { OperStatus string `xml:"oper-status"` LocalIndex string `xml:"local-index"` SnmpIndex string `xml:"snmp-index"` + Description string `xml:"description"` IfType string `xml:"if-type"` LinkLevelType string `xml:"link-level-type"` Mtu string `xml:"mtu"` diff --git a/pkg/features/interfacequeue/collector.go b/pkg/features/interfacequeue/collector.go index 4e2a0c0..bc02c5e 100644 --- a/pkg/features/interfacequeue/collector.go +++ b/pkg/features/interfacequeue/collector.go @@ -3,26 +3,16 @@ package interfacequeue import ( + "regexp" + "github.com/czerwonk/junos_exporter/pkg/collector" - "github.com/czerwonk/junos_exporter/pkg/connector" - "github.com/czerwonk/junos_exporter/pkg/interfacelabels" + "github.com/czerwonk/junos_exporter/pkg/dynamiclabels" "github.com/prometheus/client_golang/prometheus" ) const prefix = "junos_interface_queues_" -// NewCollector creates an queue collector instance -func NewCollector(labels *interfacelabels.DynamicLabelManager) collector.RPCCollector { - c := &interfaceQueueCollector{ - labels: labels, - } - c.init() - - return c -} - -type interfaceQueueCollector struct { - labels *interfacelabels.DynamicLabelManager +type description struct { queuedPackets *prometheus.Desc queuedBytes *prometheus.Desc transferedPackets *prometheus.Desc @@ -44,59 +34,77 @@ type interfaceQueueCollector struct { totalDropBytes *prometheus.Desc } -// Name returns the name of the collector -func (*interfaceQueueCollector) Name() string { - return "Interface Queues" -} +func newDescriptions(dynLabels dynamiclabels.Labels) *description { + d := &description{} -func (c *interfaceQueueCollector) init() { l := []string{"target", "name", "description"} - l = append(l, c.labels.LabelNames()...) l = append(l, "queue_number") l = append(l, "forwarding_class") + l = append(l, dynLabels.Keys()...) + + d.queuedPackets = prometheus.NewDesc(prefix+"queued_packets_count", "Number of queued packets", l, nil) + d.queuedBytes = prometheus.NewDesc(prefix+"queued_bytes_count", "Number of bytes of queued packets", l, nil) + d.transferedPackets = prometheus.NewDesc(prefix+"transfered_packets_count", "Number of transfered packets", l, nil) + d.transferedBytes = prometheus.NewDesc(prefix+"transfered_bytes_count", "Number of bytes of transfered packets", l, nil) + d.rateLimitDropPackets = prometheus.NewDesc(prefix+"rate_limit_drop_packets_count", "Number of packets droped by rate limit", l, nil) + d.rateLimitDropBytes = prometheus.NewDesc(prefix+"rate_limit_drop_bytes_count", "Number of bytes droped by rate limit", l, nil) + d.redPackets = prometheus.NewDesc(prefix+"red_packets_count", "Number of queued packets", l, nil) + d.redBytes = prometheus.NewDesc(prefix+"red_bytes_count", "Number of bytes of queued packets", l, nil) + d.redPacketsLow = prometheus.NewDesc(prefix+"red_packets_low_count", "Number of queued packets", l, nil) + d.redBytesLow = prometheus.NewDesc(prefix+"red_bytes_low_count", "Number of bytes of queued packets", l, nil) + d.redPacketsMediumLow = prometheus.NewDesc(prefix+"red_packets_medium_low_count", "Number of queued packets", l, nil) + d.redBytesMediumLow = prometheus.NewDesc(prefix+"red_bytes_medium_low_count", "Number of bytes of queued packets", l, nil) + d.redPacketsMediumHigh = prometheus.NewDesc(prefix+"red_packets_medium_high_count", "Number of queued packets", l, nil) + d.redBytesMediumHigh = prometheus.NewDesc(prefix+"red_bytes_medium_high_count", "Number of bytes of queued packets", l, nil) + d.redPacketsHigh = prometheus.NewDesc(prefix+"red_packets_high_count", "Number of queued packets", l, nil) + d.redBytesHigh = prometheus.NewDesc(prefix+"red_bytes_high_count", "Number of bytes of queued packets", l, nil) + d.tailDropPackets = prometheus.NewDesc(prefix+"tail_drop_packets_count", "Number of tail droped packets", l, nil) + d.totalDropPackets = prometheus.NewDesc(prefix+"drop_packets_count", "Number of packets droped", l, nil) + d.totalDropBytes = prometheus.NewDesc(prefix+"drop_bytes_count", "Number of bytes droped", l, nil) + + return d +} - c.queuedPackets = prometheus.NewDesc(prefix+"queued_packets_count", "Number of queued packets", l, nil) - c.queuedBytes = prometheus.NewDesc(prefix+"queued_bytes_count", "Number of bytes of queued packets", l, nil) - c.transferedPackets = prometheus.NewDesc(prefix+"transfered_packets_count", "Number of transfered packets", l, nil) - c.transferedBytes = prometheus.NewDesc(prefix+"transfered_bytes_count", "Number of bytes of transfered packets", l, nil) - c.rateLimitDropPackets = prometheus.NewDesc(prefix+"rate_limit_drop_packets_count", "Number of packets droped by rate limit", l, nil) - c.rateLimitDropBytes = prometheus.NewDesc(prefix+"rate_limit_drop_bytes_count", "Number of bytes droped by rate limit", l, nil) - c.redPackets = prometheus.NewDesc(prefix+"red_packets_count", "Number of queued packets", l, nil) - c.redBytes = prometheus.NewDesc(prefix+"red_bytes_count", "Number of bytes of queued packets", l, nil) - c.redPacketsLow = prometheus.NewDesc(prefix+"red_packets_low_count", "Number of queued packets", l, nil) - c.redBytesLow = prometheus.NewDesc(prefix+"red_bytes_low_count", "Number of bytes of queued packets", l, nil) - c.redPacketsMediumLow = prometheus.NewDesc(prefix+"red_packets_medium_low_count", "Number of queued packets", l, nil) - c.redBytesMediumLow = prometheus.NewDesc(prefix+"red_bytes_medium_low_count", "Number of bytes of queued packets", l, nil) - c.redPacketsMediumHigh = prometheus.NewDesc(prefix+"red_packets_medium_high_count", "Number of queued packets", l, nil) - c.redBytesMediumHigh = prometheus.NewDesc(prefix+"red_bytes_medium_high_count", "Number of bytes of queued packets", l, nil) - c.redPacketsHigh = prometheus.NewDesc(prefix+"red_packets_high_count", "Number of queued packets", l, nil) - c.redBytesHigh = prometheus.NewDesc(prefix+"red_bytes_high_count", "Number of bytes of queued packets", l, nil) - c.tailDropPackets = prometheus.NewDesc(prefix+"tail_drop_packets_count", "Number of tail droped packets", l, nil) - c.totalDropPackets = prometheus.NewDesc(prefix+"drop_packets_count", "Number of packets droped", l, nil) - c.totalDropBytes = prometheus.NewDesc(prefix+"drop_bytes_count", "Number of bytes droped", l, nil) +// NewCollector creates an queue collector instance +func NewCollector(descRe *regexp.Regexp) collector.RPCCollector { + c := &interfaceQueueCollector{ + descriptionRe: descRe, + } + + return c +} + +type interfaceQueueCollector struct { + descriptionRe *regexp.Regexp +} + +// Name returns the name of the collector +func (*interfaceQueueCollector) Name() string { + return "Interface Queues" } // Describe describes the metrics func (c *interfaceQueueCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- c.queuedBytes - ch <- c.queuedPackets - ch <- c.transferedBytes - ch <- c.transferedPackets - ch <- c.rateLimitDropBytes - ch <- c.rateLimitDropPackets - ch <- c.redPackets - ch <- c.redBytes - ch <- c.redPacketsLow - ch <- c.redBytesLow - ch <- c.redPacketsMediumLow - ch <- c.redBytesMediumLow - ch <- c.redPacketsMediumHigh - ch <- c.redBytesMediumHigh - ch <- c.redPacketsHigh - ch <- c.redBytesHigh - ch <- c.tailDropPackets - ch <- c.totalDropBytes - ch <- c.totalDropPackets + d := newDescriptions(nil) + ch <- d.queuedBytes + ch <- d.queuedPackets + ch <- d.transferedBytes + ch <- d.transferedPackets + ch <- d.rateLimitDropBytes + ch <- d.rateLimitDropPackets + ch <- d.redPackets + ch <- d.redBytes + ch <- d.redPacketsLow + ch <- d.redBytesLow + ch <- d.redPacketsMediumLow + ch <- d.redBytesMediumLow + ch <- d.redPacketsMediumHigh + ch <- d.redBytesMediumHigh + ch <- d.redPacketsHigh + ch <- d.redBytesHigh + ch <- d.tailDropPackets + ch <- d.totalDropBytes + ch <- d.totalDropPackets } // Collect collects metrics from JunOS @@ -109,42 +117,44 @@ func (c *interfaceQueueCollector) Collect(client collector.Client, ch chan<- pro } for _, iface := range q.InterfaceInformation.Interfaces { - c.collectForInterface(iface, client.Device(), ch, labelValues) + c.collectForInterface(iface, ch, labelValues) } return nil } -func (c *interfaceQueueCollector) collectForInterface(iface physicalInterface, device *connector.Device, ch chan<- prometheus.Metric, labelValues []string) { - l := append(labelValues, iface.Name, iface.Description) - l = append(l, c.labels.ValuesForInterface(device, iface.Name)...) +func (c *interfaceQueueCollector) collectForInterface(iface physicalInterface, ch chan<- prometheus.Metric, labelValues []string) { + lv := append(labelValues, []string{iface.Name, iface.Description}...) + dynLabels := dynamiclabels.ParseDescription(iface.Description, c.descriptionRe) for _, q := range iface.QueueCounters.Queues { - c.collectForQueue(q, ch, l) + c.collectForQueue(q, ch, lv, dynLabels) } } -func (c *interfaceQueueCollector) collectForQueue(queue queue, ch chan<- prometheus.Metric, labelValues []string) { +func (c *interfaceQueueCollector) collectForQueue(queue queue, ch chan<- prometheus.Metric, labelValues []string, dynLabels dynamiclabels.Labels) { l := append(labelValues, queue.Number) l = append(l, queue.ForwaringClassName) - - ch <- prometheus.MustNewConstMetric(c.queuedPackets, prometheus.CounterValue, float64(queue.QueuedPackets), l...) - ch <- prometheus.MustNewConstMetric(c.queuedBytes, prometheus.CounterValue, float64(queue.QueuedBytes), l...) - ch <- prometheus.MustNewConstMetric(c.transferedPackets, prometheus.CounterValue, float64(queue.TransferedPackets), l...) - ch <- prometheus.MustNewConstMetric(c.transferedBytes, prometheus.CounterValue, float64(queue.TransferedBytes), l...) - ch <- prometheus.MustNewConstMetric(c.rateLimitDropPackets, prometheus.CounterValue, float64(queue.RateLimitDropPackets), l...) - ch <- prometheus.MustNewConstMetric(c.rateLimitDropBytes, prometheus.CounterValue, float64(queue.RateLimitDropBytes), l...) - ch <- prometheus.MustNewConstMetric(c.redPackets, prometheus.CounterValue, float64(queue.RedPackets), l...) - ch <- prometheus.MustNewConstMetric(c.redBytes, prometheus.CounterValue, float64(queue.RedBytes), l...) - ch <- prometheus.MustNewConstMetric(c.redPacketsLow, prometheus.CounterValue, float64(queue.RedPacketsLow), l...) - ch <- prometheus.MustNewConstMetric(c.redBytesLow, prometheus.CounterValue, float64(queue.RedBytesLow), l...) - ch <- prometheus.MustNewConstMetric(c.redPacketsMediumLow, prometheus.CounterValue, float64(queue.RedPacketsMediumLow), l...) - ch <- prometheus.MustNewConstMetric(c.redBytesMediumLow, prometheus.CounterValue, float64(queue.RedBytesMediumLow), l...) - ch <- prometheus.MustNewConstMetric(c.redPacketsMediumHigh, prometheus.CounterValue, float64(queue.RedPacketsMediumHigh), l...) - ch <- prometheus.MustNewConstMetric(c.redBytesMediumHigh, prometheus.CounterValue, float64(queue.RedBytesMediumHigh), l...) - ch <- prometheus.MustNewConstMetric(c.redPacketsHigh, prometheus.CounterValue, float64(queue.RedPacketsHigh), l...) - ch <- prometheus.MustNewConstMetric(c.redBytesHigh, prometheus.CounterValue, float64(queue.RedBytesHigh), l...) - ch <- prometheus.MustNewConstMetric(c.tailDropPackets, prometheus.CounterValue, float64(queue.TailDropPackets), l...) - ch <- prometheus.MustNewConstMetric(c.totalDropPackets, prometheus.CounterValue, float64(queue.TotalDropPackets), l...) - ch <- prometheus.MustNewConstMetric(c.totalDropBytes, prometheus.CounterValue, float64(queue.TotalDropBytes), l...) + l = append(l, dynLabels.Values()...) + + d := newDescriptions(dynLabels) + ch <- prometheus.MustNewConstMetric(d.queuedPackets, prometheus.CounterValue, float64(queue.QueuedPackets), l...) + ch <- prometheus.MustNewConstMetric(d.queuedBytes, prometheus.CounterValue, float64(queue.QueuedBytes), l...) + ch <- prometheus.MustNewConstMetric(d.transferedPackets, prometheus.CounterValue, float64(queue.TransferedPackets), l...) + ch <- prometheus.MustNewConstMetric(d.transferedBytes, prometheus.CounterValue, float64(queue.TransferedBytes), l...) + ch <- prometheus.MustNewConstMetric(d.rateLimitDropPackets, prometheus.CounterValue, float64(queue.RateLimitDropPackets), l...) + ch <- prometheus.MustNewConstMetric(d.rateLimitDropBytes, prometheus.CounterValue, float64(queue.RateLimitDropBytes), l...) + ch <- prometheus.MustNewConstMetric(d.redPackets, prometheus.CounterValue, float64(queue.RedPackets), l...) + ch <- prometheus.MustNewConstMetric(d.redBytes, prometheus.CounterValue, float64(queue.RedBytes), l...) + ch <- prometheus.MustNewConstMetric(d.redPacketsLow, prometheus.CounterValue, float64(queue.RedPacketsLow), l...) + ch <- prometheus.MustNewConstMetric(d.redBytesLow, prometheus.CounterValue, float64(queue.RedBytesLow), l...) + ch <- prometheus.MustNewConstMetric(d.redPacketsMediumLow, prometheus.CounterValue, float64(queue.RedPacketsMediumLow), l...) + ch <- prometheus.MustNewConstMetric(d.redBytesMediumLow, prometheus.CounterValue, float64(queue.RedBytesMediumLow), l...) + ch <- prometheus.MustNewConstMetric(d.redPacketsMediumHigh, prometheus.CounterValue, float64(queue.RedPacketsMediumHigh), l...) + ch <- prometheus.MustNewConstMetric(d.redBytesMediumHigh, prometheus.CounterValue, float64(queue.RedBytesMediumHigh), l...) + ch <- prometheus.MustNewConstMetric(d.redPacketsHigh, prometheus.CounterValue, float64(queue.RedPacketsHigh), l...) + ch <- prometheus.MustNewConstMetric(d.redBytesHigh, prometheus.CounterValue, float64(queue.RedBytesHigh), l...) + ch <- prometheus.MustNewConstMetric(d.tailDropPackets, prometheus.CounterValue, float64(queue.TailDropPackets), l...) + ch <- prometheus.MustNewConstMetric(d.totalDropPackets, prometheus.CounterValue, float64(queue.TotalDropPackets), l...) + ch <- prometheus.MustNewConstMetric(d.totalDropBytes, prometheus.CounterValue, float64(queue.TotalDropBytes), l...) } diff --git a/pkg/features/interfaces/collector.go b/pkg/features/interfaces/collector.go index f17ebc3..fd382d6 100644 --- a/pkg/features/interfaces/collector.go +++ b/pkg/features/interfaces/collector.go @@ -3,20 +3,18 @@ package interfaces import ( + "regexp" "strconv" "strings" "github.com/czerwonk/junos_exporter/pkg/collector" - "github.com/czerwonk/junos_exporter/pkg/connector" - "github.com/czerwonk/junos_exporter/pkg/interfacelabels" + "github.com/czerwonk/junos_exporter/pkg/dynamiclabels" "github.com/prometheus/client_golang/prometheus" ) const prefix = "junos_interface_" -// Collector collects interface metrics -type interfaceCollector struct { - labels *interfacelabels.DynamicLabelManager +type description struct { receiveBytesDesc *prometheus.Desc receivePacketsDesc *prometheus.Desc receiveErrorsDesc *prometheus.Desc @@ -56,12 +54,62 @@ type interfaceCollector struct { transmitTotalErrorsDesc *prometheus.Desc } +func newDescriptions(dynLabels dynamiclabels.Labels) *description { + d := &description{} + l := []string{"target", "name", "description", "mac"} + l = append(l, dynLabels.Keys()...) + + d.receiveBytesDesc = prometheus.NewDesc(prefix+"receive_bytes", "Received data in bytes", l, nil) + d.receivePacketsDesc = prometheus.NewDesc(prefix+"receive_packets_total", "Received packets", l, nil) + d.receiveErrorsDesc = prometheus.NewDesc(prefix+"receive_errors", "Number of errors caused by incoming packets", l, nil) + d.receiveDropsDesc = prometheus.NewDesc(prefix+"receive_drops", "Number of dropped incoming packets", l, nil) + d.interfaceSpeedDesc = prometheus.NewDesc(prefix+"speed", "speed in in bps", l, nil) + d.interfaceBPDUErrorDesc = prometheus.NewDesc(prefix+"error_bpdublock", "Flag which tells that there's a BPDU_Block on the interface (bool)", l, nil) + d.transmitBytesDesc = prometheus.NewDesc(prefix+"transmit_bytes", "Transmitted data in bytes", l, nil) + d.transmitPacketsDesc = prometheus.NewDesc(prefix+"transmit_packets_total", "Transmitted packets", l, nil) + d.transmitErrorsDesc = prometheus.NewDesc(prefix+"transmit_errors", "Number of errors caused by outgoing packets", l, nil) + d.transmitDropsDesc = prometheus.NewDesc(prefix+"transmit_drops", "Number of dropped outgoing packets", l, nil) + d.ipv6receiveBytesDesc = prometheus.NewDesc(prefix+"IPv6_receive_bytes_total", "Received IPv6 data in bytes", l, nil) + d.ipv6receivePacketsDesc = prometheus.NewDesc(prefix+"IPv6_receive_packets_total", "Received IPv6 packets", l, nil) + d.ipv6transmitBytesDesc = prometheus.NewDesc(prefix+"IPv6_transmit_bytes_total", "Transmitted IPv6 data in bytes", l, nil) + d.ipv6transmitPacketsDesc = prometheus.NewDesc(prefix+"IPv6_transmit_packets_total", "Transmitted IPv6 packets", l, nil) + d.adminStatusDesc = prometheus.NewDesc(prefix+"admin_up", "Admin operational status", l, nil) + d.operStatusDesc = prometheus.NewDesc(prefix+"up", "Interface operational status", l, nil) + d.errorStatusDesc = prometheus.NewDesc(prefix+"error_status", "Admin and operational status differ", l, nil) + d.lastFlappedDesc = prometheus.NewDesc(prefix+"last_flapped_seconds", "Seconds since last flapped (-1 if never)", l, nil) + d.receiveUnicastsDesc = prometheus.NewDesc(prefix+"receive_unicasts_packets", "Received unicast packets", l, nil) + d.receiveBroadcastsDesc = prometheus.NewDesc(prefix+"receive_broadcasts_packets", "Received broadcast packets", l, nil) + d.receiveMulticastsDesc = prometheus.NewDesc(prefix+"receive_multicasts_packets", "Received multicast packets", l, nil) + d.receiveCRCErrorsDesc = prometheus.NewDesc(prefix+"receive_errors_crc_packets", "Number of CRC error incoming packets", l, nil) + d.transmitUnicastsDesc = prometheus.NewDesc(prefix+"transmit_unicasts_packets", "Transmitted unicast packets", l, nil) + d.transmitBroadcastsDesc = prometheus.NewDesc(prefix+"transmit_broadcasts_packets", "Transmitted broadcast packets", l, nil) + d.transmitMulticastsDesc = prometheus.NewDesc(prefix+"transmit_multicasts_packets", "Transmitted multicast packets", l, nil) + d.transmitCRCErrorsDesc = prometheus.NewDesc(prefix+"transmit_errors_crc_packets", "Number of CRC error outgoing packets", l, nil) + d.fecCcwCountDesc = prometheus.NewDesc(prefix+"fec_ccw_count", "Number FEC Corrected Errors", l, nil) + d.fecNccwCountDesc = prometheus.NewDesc(prefix+"fec_nccw_count", "Number FEC Uncorrected Errors", l, nil) + d.fecCcwErrorRateDesc = prometheus.NewDesc(prefix+"fec_ccw_error_rate", "Number FEC Corrected Errors Rate", l, nil) + d.fecNccwErrorRateDesc = prometheus.NewDesc(prefix+"fec_nccw_error_rate", "Number FEC Uncorrected Errors Rate", l, nil) + d.receiveOversizedFramesDesc = prometheus.NewDesc(prefix+"receive_oversized_frames", "Number of received Oversize Frames", l, nil) + d.receiveJabberFramesDesc = prometheus.NewDesc(prefix+"receive_jabber_frames", "Number of received Jabber Frames", l, nil) + d.receiveFragmentFramesDesc = prometheus.NewDesc(prefix+"receive_fragment_frames", "Number of received Fragment Frames", l, nil) + d.receiveVlanTaggedFramesDesc = prometheus.NewDesc(prefix+"receive_vlan_tagged_frames", "Number of received Vlan Tagged Frames", l, nil) + d.receiveCodeViolationsDesc = prometheus.NewDesc(prefix+"receive_code_violations", "Number of received Code Violations", l, nil) + d.receiveTotalErrorsDesc = prometheus.NewDesc(prefix+"receive_total_errors", "Number of received Total Errors", l, nil) + d.transmitTotalErrorsDesc = prometheus.NewDesc(prefix+"transmit_total_errors", "Number of transmitted Total Errors", l, nil) + + return d +} + +// Collector collects interface metrics +type interfaceCollector struct { + descriptionRe *regexp.Regexp +} + // NewCollector creates a new collector -func NewCollector(labels *interfacelabels.DynamicLabelManager) collector.RPCCollector { +func NewCollector(descRe *regexp.Regexp) collector.RPCCollector { c := &interfaceCollector{ - labels: labels, + descriptionRe: descRe, } - c.init() return c } @@ -71,89 +119,46 @@ func (*interfaceCollector) Name() string { return "Interfaces" } -func (c *interfaceCollector) init() { - l := []string{"target", "name", "description", "mac"} - l = append(l, c.labels.LabelNames()...) - - c.receiveBytesDesc = prometheus.NewDesc(prefix+"receive_bytes", "Received data in bytes", l, nil) - c.receivePacketsDesc = prometheus.NewDesc(prefix+"receive_packets_total", "Received packets", l, nil) - c.receiveErrorsDesc = prometheus.NewDesc(prefix+"receive_errors", "Number of errors caused by incoming packets", l, nil) - c.receiveDropsDesc = prometheus.NewDesc(prefix+"receive_drops", "Number of dropped incoming packets", l, nil) - c.interfaceSpeedDesc = prometheus.NewDesc(prefix+"speed", "speed in in bps", l, nil) - c.interfaceBPDUErrorDesc = prometheus.NewDesc(prefix+"error_bpdublock", "Flag which tells that there's a BPDU_Block on the interface (bool)", l, nil) - c.transmitBytesDesc = prometheus.NewDesc(prefix+"transmit_bytes", "Transmitted data in bytes", l, nil) - c.transmitPacketsDesc = prometheus.NewDesc(prefix+"transmit_packets_total", "Transmitted packets", l, nil) - c.transmitErrorsDesc = prometheus.NewDesc(prefix+"transmit_errors", "Number of errors caused by outgoing packets", l, nil) - c.transmitDropsDesc = prometheus.NewDesc(prefix+"transmit_drops", "Number of dropped outgoing packets", l, nil) - c.ipv6receiveBytesDesc = prometheus.NewDesc(prefix+"IPv6_receive_bytes_total", "Received IPv6 data in bytes", l, nil) - c.ipv6receivePacketsDesc = prometheus.NewDesc(prefix+"IPv6_receive_packets_total", "Received IPv6 packets", l, nil) - c.ipv6transmitBytesDesc = prometheus.NewDesc(prefix+"IPv6_transmit_bytes_total", "Transmitted IPv6 data in bytes", l, nil) - c.ipv6transmitPacketsDesc = prometheus.NewDesc(prefix+"IPv6_transmit_packets_total", "Transmitted IPv6 packets", l, nil) - c.adminStatusDesc = prometheus.NewDesc(prefix+"admin_up", "Admin operational status", l, nil) - c.operStatusDesc = prometheus.NewDesc(prefix+"up", "Interface operational status", l, nil) - c.errorStatusDesc = prometheus.NewDesc(prefix+"error_status", "Admin and operational status differ", l, nil) - c.lastFlappedDesc = prometheus.NewDesc(prefix+"last_flapped_seconds", "Seconds since last flapped (-1 if never)", l, nil) - c.receiveUnicastsDesc = prometheus.NewDesc(prefix+"receive_unicasts_packets", "Received unicast packets", l, nil) - c.receiveBroadcastsDesc = prometheus.NewDesc(prefix+"receive_broadcasts_packets", "Received broadcast packets", l, nil) - c.receiveMulticastsDesc = prometheus.NewDesc(prefix+"receive_multicasts_packets", "Received multicast packets", l, nil) - c.receiveCRCErrorsDesc = prometheus.NewDesc(prefix+"receive_errors_crc_packets", "Number of CRC error incoming packets", l, nil) - c.transmitUnicastsDesc = prometheus.NewDesc(prefix+"transmit_unicasts_packets", "Transmitted unicast packets", l, nil) - c.transmitBroadcastsDesc = prometheus.NewDesc(prefix+"transmit_broadcasts_packets", "Transmitted broadcast packets", l, nil) - c.transmitMulticastsDesc = prometheus.NewDesc(prefix+"transmit_multicasts_packets", "Transmitted multicast packets", l, nil) - c.transmitCRCErrorsDesc = prometheus.NewDesc(prefix+"transmit_errors_crc_packets", "Number of CRC error outgoing packets", l, nil) - c.fecCcwCountDesc = prometheus.NewDesc(prefix+"fec_ccw_count", "Number FEC Corrected Errors", l, nil) - c.fecNccwCountDesc = prometheus.NewDesc(prefix+"fec_nccw_count", "Number FEC Uncorrected Errors", l, nil) - c.fecCcwErrorRateDesc = prometheus.NewDesc(prefix+"fec_ccw_error_rate", "Number FEC Corrected Errors Rate", l, nil) - c.fecNccwErrorRateDesc = prometheus.NewDesc(prefix+"fec_nccw_error_rate", "Number FEC Uncorrected Errors Rate", l, nil) - c.receiveOversizedFramesDesc = prometheus.NewDesc(prefix+"receive_oversized_frames", "Number of received Oversize Frames", l, nil) - c.receiveJabberFramesDesc = prometheus.NewDesc(prefix+"receive_jabber_frames", "Number of received Jabber Frames", l, nil) - c.receiveFragmentFramesDesc = prometheus.NewDesc(prefix+"receive_fragment_frames", "Number of received Fragment Frames", l, nil) - c.receiveVlanTaggedFramesDesc = prometheus.NewDesc(prefix+"receive_vlan_tagged_frames", "Number of received Vlan Tagged Frames", l, nil) - c.receiveCodeViolationsDesc = prometheus.NewDesc(prefix+"receive_code_violations", "Number of received Code Violations", l, nil) - c.receiveTotalErrorsDesc = prometheus.NewDesc(prefix+"receive_total_errors", "Number of received Total Errors", l, nil) - c.transmitTotalErrorsDesc = prometheus.NewDesc(prefix+"transmit_total_errors", "Number of transmitted Total Errors", l, nil) - -} - // Describe describes the metrics -func (c *interfaceCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- c.receiveBytesDesc - ch <- c.receivePacketsDesc - ch <- c.receiveErrorsDesc - ch <- c.receiveDropsDesc - ch <- c.interfaceSpeedDesc - ch <- c.interfaceBPDUErrorDesc - ch <- c.transmitBytesDesc - ch <- c.transmitPacketsDesc - ch <- c.transmitDropsDesc - ch <- c.transmitErrorsDesc - ch <- c.ipv6receiveBytesDesc - ch <- c.ipv6receivePacketsDesc - ch <- c.ipv6transmitBytesDesc - ch <- c.ipv6transmitPacketsDesc - ch <- c.adminStatusDesc - ch <- c.operStatusDesc - ch <- c.errorStatusDesc - ch <- c.lastFlappedDesc - ch <- c.receiveUnicastsDesc - ch <- c.receiveBroadcastsDesc - ch <- c.receiveMulticastsDesc - ch <- c.receiveCRCErrorsDesc - ch <- c.transmitUnicastsDesc - ch <- c.transmitBroadcastsDesc - ch <- c.transmitMulticastsDesc - ch <- c.transmitCRCErrorsDesc - ch <- c.fecCcwCountDesc - ch <- c.fecNccwCountDesc - ch <- c.fecCcwErrorRateDesc - ch <- c.fecNccwErrorRateDesc - ch <- c.receiveOversizedFramesDesc - ch <- c.receiveJabberFramesDesc - ch <- c.receiveFragmentFramesDesc - ch <- c.receiveVlanTaggedFramesDesc - ch <- c.receiveCodeViolationsDesc - ch <- c.receiveTotalErrorsDesc - ch <- c.transmitTotalErrorsDesc +func (*interfaceCollector) Describe(ch chan<- *prometheus.Desc) { + d := newDescriptions(nil) + ch <- d.receiveBytesDesc + ch <- d.receivePacketsDesc + ch <- d.receiveErrorsDesc + ch <- d.receiveDropsDesc + ch <- d.interfaceSpeedDesc + ch <- d.interfaceBPDUErrorDesc + ch <- d.transmitBytesDesc + ch <- d.transmitPacketsDesc + ch <- d.transmitDropsDesc + ch <- d.transmitErrorsDesc + ch <- d.ipv6receiveBytesDesc + ch <- d.ipv6receivePacketsDesc + ch <- d.ipv6transmitBytesDesc + ch <- d.ipv6transmitPacketsDesc + ch <- d.adminStatusDesc + ch <- d.operStatusDesc + ch <- d.errorStatusDesc + ch <- d.lastFlappedDesc + ch <- d.receiveUnicastsDesc + ch <- d.receiveBroadcastsDesc + ch <- d.receiveMulticastsDesc + ch <- d.receiveCRCErrorsDesc + ch <- d.transmitUnicastsDesc + ch <- d.transmitBroadcastsDesc + ch <- d.transmitMulticastsDesc + ch <- d.transmitCRCErrorsDesc + ch <- d.fecCcwCountDesc + ch <- d.fecNccwCountDesc + ch <- d.fecCcwErrorRateDesc + ch <- d.fecNccwErrorRateDesc + ch <- d.receiveOversizedFramesDesc + ch <- d.receiveJabberFramesDesc + ch <- d.receiveFragmentFramesDesc + ch <- d.receiveVlanTaggedFramesDesc + ch <- d.receiveCodeViolationsDesc + ch <- d.receiveTotalErrorsDesc + ch <- d.transmitTotalErrorsDesc } // Collect collects metrics from JunOS @@ -164,7 +169,7 @@ func (c *interfaceCollector) Collect(client collector.Client, ch chan<- promethe } for _, s := range stats { - c.collectForInterface(s, client.Device(), ch, labelValues) + c.collectForInterface(s, ch, labelValues) } return nil @@ -258,18 +263,20 @@ func (c *interfaceCollector) interfaceStats(client collector.Client) ([]*interfa return stats, nil } -func (c *interfaceCollector) collectForInterface(s *interfaceStats, device *connector.Device, ch chan<- prometheus.Metric, labelValues []string) { - l := append(labelValues, []string{s.Name, s.Description, s.Mac}...) - l = append(l, c.labels.ValuesForInterface(device, s.Name)...) - - ch <- prometheus.MustNewConstMetric(c.receiveBytesDesc, prometheus.CounterValue, s.ReceiveBytes, l...) - ch <- prometheus.MustNewConstMetric(c.receivePacketsDesc, prometheus.CounterValue, s.ReceivePackets, l...) - ch <- prometheus.MustNewConstMetric(c.transmitBytesDesc, prometheus.CounterValue, s.TransmitBytes, l...) - ch <- prometheus.MustNewConstMetric(c.transmitPacketsDesc, prometheus.CounterValue, s.TransmitPackets, l...) - ch <- prometheus.MustNewConstMetric(c.ipv6receiveBytesDesc, prometheus.CounterValue, s.IPv6ReceiveBytes, l...) - ch <- prometheus.MustNewConstMetric(c.ipv6receivePacketsDesc, prometheus.CounterValue, s.IPv6ReceivePackets, l...) - ch <- prometheus.MustNewConstMetric(c.ipv6transmitBytesDesc, prometheus.CounterValue, s.IPv6TransmitBytes, l...) - ch <- prometheus.MustNewConstMetric(c.ipv6transmitPacketsDesc, prometheus.CounterValue, s.IPv6TransmitPackets, l...) +func (c *interfaceCollector) collectForInterface(s *interfaceStats, ch chan<- prometheus.Metric, labelValues []string) { + lv := append(labelValues, []string{s.Name, s.Description, s.Mac}...) + dynLabels := dynamiclabels.ParseDescription(s.Description, c.descriptionRe) + lv = append(lv, dynLabels.Values()...) + d := newDescriptions(dynLabels) + + ch <- prometheus.MustNewConstMetric(d.receiveBytesDesc, prometheus.CounterValue, s.ReceiveBytes, lv...) + ch <- prometheus.MustNewConstMetric(d.receivePacketsDesc, prometheus.CounterValue, s.ReceivePackets, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitBytesDesc, prometheus.CounterValue, s.TransmitBytes, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitPacketsDesc, prometheus.CounterValue, s.TransmitPackets, lv...) + ch <- prometheus.MustNewConstMetric(d.ipv6receiveBytesDesc, prometheus.CounterValue, s.IPv6ReceiveBytes, lv...) + ch <- prometheus.MustNewConstMetric(d.ipv6receivePacketsDesc, prometheus.CounterValue, s.IPv6ReceivePackets, lv...) + ch <- prometheus.MustNewConstMetric(d.ipv6transmitBytesDesc, prometheus.CounterValue, s.IPv6TransmitBytes, lv...) + ch <- prometheus.MustNewConstMetric(d.ipv6transmitPacketsDesc, prometheus.CounterValue, s.IPv6TransmitPackets, lv...) if s.IsPhysical { adminUp := 0 @@ -313,41 +320,41 @@ func (c *interfaceCollector) collectForInterface(s *interfaceStats, device *conn sp64, _ := strconv.ParseFloat(speed, 64) if s.BPDUError { - ch <- prometheus.MustNewConstMetric(c.interfaceBPDUErrorDesc, prometheus.GaugeValue, float64(1), l...) + ch <- prometheus.MustNewConstMetric(d.interfaceBPDUErrorDesc, prometheus.GaugeValue, float64(1), lv...) } - ch <- prometheus.MustNewConstMetric(c.adminStatusDesc, prometheus.GaugeValue, float64(adminUp), l...) - ch <- prometheus.MustNewConstMetric(c.operStatusDesc, prometheus.GaugeValue, float64(operUp), l...) - ch <- prometheus.MustNewConstMetric(c.errorStatusDesc, prometheus.GaugeValue, float64(err), l...) - ch <- prometheus.MustNewConstMetric(c.transmitErrorsDesc, prometheus.CounterValue, s.TransmitErrors, l...) - ch <- prometheus.MustNewConstMetric(c.transmitDropsDesc, prometheus.CounterValue, s.TransmitDrops, l...) - ch <- prometheus.MustNewConstMetric(c.receiveErrorsDesc, prometheus.CounterValue, s.ReceiveErrors, l...) - ch <- prometheus.MustNewConstMetric(c.receiveDropsDesc, prometheus.CounterValue, s.ReceiveDrops, l...) - ch <- prometheus.MustNewConstMetric(c.interfaceSpeedDesc, prometheus.GaugeValue, float64(sp64), l...) + ch <- prometheus.MustNewConstMetric(d.adminStatusDesc, prometheus.GaugeValue, float64(adminUp), lv...) + ch <- prometheus.MustNewConstMetric(d.operStatusDesc, prometheus.GaugeValue, float64(operUp), lv...) + ch <- prometheus.MustNewConstMetric(d.errorStatusDesc, prometheus.GaugeValue, float64(err), lv...) + ch <- prometheus.MustNewConstMetric(d.transmitErrorsDesc, prometheus.CounterValue, s.TransmitErrors, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitDropsDesc, prometheus.CounterValue, s.TransmitDrops, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveErrorsDesc, prometheus.CounterValue, s.ReceiveErrors, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveDropsDesc, prometheus.CounterValue, s.ReceiveDrops, lv...) + ch <- prometheus.MustNewConstMetric(d.interfaceSpeedDesc, prometheus.GaugeValue, float64(sp64), lv...) if s.LastFlapped != 0 { - ch <- prometheus.MustNewConstMetric(c.lastFlappedDesc, prometheus.GaugeValue, s.LastFlapped, l...) + ch <- prometheus.MustNewConstMetric(d.lastFlappedDesc, prometheus.GaugeValue, s.LastFlapped, lv...) } - ch <- prometheus.MustNewConstMetric(c.receiveUnicastsDesc, prometheus.CounterValue, s.ReceiveUnicasts, l...) - ch <- prometheus.MustNewConstMetric(c.receiveBroadcastsDesc, prometheus.CounterValue, s.ReceiveBroadcasts, l...) - ch <- prometheus.MustNewConstMetric(c.receiveMulticastsDesc, prometheus.CounterValue, s.ReceiveMulticasts, l...) - ch <- prometheus.MustNewConstMetric(c.receiveCRCErrorsDesc, prometheus.CounterValue, s.ReceiveCRCErrors, l...) - ch <- prometheus.MustNewConstMetric(c.transmitUnicastsDesc, prometheus.CounterValue, s.TransmitUnicasts, l...) - ch <- prometheus.MustNewConstMetric(c.transmitBroadcastsDesc, prometheus.CounterValue, s.TransmitBroadcasts, l...) - ch <- prometheus.MustNewConstMetric(c.transmitMulticastsDesc, prometheus.CounterValue, s.TransmitMulticasts, l...) - ch <- prometheus.MustNewConstMetric(c.transmitCRCErrorsDesc, prometheus.CounterValue, s.TransmitCRCErrors, l...) - ch <- prometheus.MustNewConstMetric(c.fecCcwCountDesc, prometheus.CounterValue, s.FecCcwCount, l...) - ch <- prometheus.MustNewConstMetric(c.fecNccwCountDesc, prometheus.CounterValue, s.FecNccwCount, l...) - ch <- prometheus.MustNewConstMetric(c.fecCcwErrorRateDesc, prometheus.CounterValue, s.FecCcwErrorRate, l...) - ch <- prometheus.MustNewConstMetric(c.fecNccwErrorRateDesc, prometheus.CounterValue, s.FecNccwErrorRate, l...) - ch <- prometheus.MustNewConstMetric(c.receiveOversizedFramesDesc, prometheus.CounterValue, s.ReceiveOversizedFrames, l...) - ch <- prometheus.MustNewConstMetric(c.receiveJabberFramesDesc, prometheus.CounterValue, s.ReceiveJabberFrames, l...) - ch <- prometheus.MustNewConstMetric(c.receiveFragmentFramesDesc, prometheus.CounterValue, s.ReceiveFragmentFrames, l...) - ch <- prometheus.MustNewConstMetric(c.receiveVlanTaggedFramesDesc, prometheus.CounterValue, s.ReceiveVlanTaggedFrames, l...) - ch <- prometheus.MustNewConstMetric(c.receiveCodeViolationsDesc, prometheus.CounterValue, s.ReceiveCodeViolations, l...) - ch <- prometheus.MustNewConstMetric(c.receiveTotalErrorsDesc, prometheus.CounterValue, s.ReceiveTotalErrors, l...) - ch <- prometheus.MustNewConstMetric(c.transmitTotalErrorsDesc, prometheus.CounterValue, s.TransmitTotalErrors, l...) + ch <- prometheus.MustNewConstMetric(d.receiveUnicastsDesc, prometheus.CounterValue, s.ReceiveUnicasts, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveBroadcastsDesc, prometheus.CounterValue, s.ReceiveBroadcasts, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveMulticastsDesc, prometheus.CounterValue, s.ReceiveMulticasts, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveCRCErrorsDesc, prometheus.CounterValue, s.ReceiveCRCErrors, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitUnicastsDesc, prometheus.CounterValue, s.TransmitUnicasts, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitBroadcastsDesc, prometheus.CounterValue, s.TransmitBroadcasts, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitMulticastsDesc, prometheus.CounterValue, s.TransmitMulticasts, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitCRCErrorsDesc, prometheus.CounterValue, s.TransmitCRCErrors, lv...) + ch <- prometheus.MustNewConstMetric(d.fecCcwCountDesc, prometheus.CounterValue, s.FecCcwCount, lv...) + ch <- prometheus.MustNewConstMetric(d.fecNccwCountDesc, prometheus.CounterValue, s.FecNccwCount, lv...) + ch <- prometheus.MustNewConstMetric(d.fecCcwErrorRateDesc, prometheus.CounterValue, s.FecCcwErrorRate, lv...) + ch <- prometheus.MustNewConstMetric(d.fecNccwErrorRateDesc, prometheus.CounterValue, s.FecNccwErrorRate, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveOversizedFramesDesc, prometheus.CounterValue, s.ReceiveOversizedFrames, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveJabberFramesDesc, prometheus.CounterValue, s.ReceiveJabberFrames, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveFragmentFramesDesc, prometheus.CounterValue, s.ReceiveFragmentFrames, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveVlanTaggedFramesDesc, prometheus.CounterValue, s.ReceiveVlanTaggedFrames, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveCodeViolationsDesc, prometheus.CounterValue, s.ReceiveCodeViolations, lv...) + ch <- prometheus.MustNewConstMetric(d.receiveTotalErrorsDesc, prometheus.CounterValue, s.ReceiveTotalErrors, lv...) + ch <- prometheus.MustNewConstMetric(d.transmitTotalErrorsDesc, prometheus.CounterValue, s.TransmitTotalErrors, lv...) } } diff --git a/pkg/interfacelabels/dynamic_labels.go b/pkg/interfacelabels/dynamic_labels.go deleted file mode 100644 index 3382284..0000000 --- a/pkg/interfacelabels/dynamic_labels.go +++ /dev/null @@ -1,173 +0,0 @@ -// SPDX-License-Identifier: MIT - -package interfacelabels - -import ( - "regexp" - "strings" - "sync" - - "github.com/czerwonk/junos_exporter/pkg/collector" - "github.com/czerwonk/junos_exporter/pkg/connector" - "github.com/pkg/errors" -) - -var ( - nameRe *regexp.Regexp -) - -func init() { - nameRe = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_]*$`) -} - -func DefaultInterfaceDescRegex() *regexp.Regexp { - return regexp.MustCompile(`\[([^=\]]+)(=[^\]]+)?\]`) -} - -// NewDynamicLabelManager create a new instance of DynamicLabels -func NewDynamicLabelManager() *DynamicLabelManager { - return &DynamicLabelManager{ - labelNames: make(map[string]int), - labels: make(map[interfaceKey][]*InterfaceLabel), - } -} - -// DynamicLabelManager parses and manages dynamic labels and label values -type DynamicLabelManager struct { - labelNames map[string]int - labels map[interfaceKey][]*InterfaceLabel - labelCount int - mu sync.Mutex -} - -type interfaceKey struct { - host string - ifaceName string -} - -type InterfaceLabel struct { - name string - value string -} - -func (il *InterfaceLabel) Name() string { - return il.name -} - -func (il *InterfaceLabel) Value() string { - return il.value -} - -// CollectDescriptions collects labels from descriptions -func (l *DynamicLabelManager) CollectDescriptions(device *connector.Device, client collector.Client, ifDescReg *regexp.Regexp) error { - r := &result{} - err := client.RunCommandAndParse("show interfaces descriptions", r) - if err != nil { - return errors.Wrap(err, "could not retrieve interface descriptions for "+device.Host) - } - - l.parseDescriptions(device, r.Information.LogicalInterfaces, ifDescReg) - l.parseDescriptions(device, r.Information.PhysicalInterfaces, ifDescReg) - - return nil -} - -// LabelNames returns the names for all dynamic labels -func (l *DynamicLabelManager) LabelNames() []string { - names := make([]string, len(l.labelNames)) - - for k, v := range l.labelNames { - names[v] = k - } - - return names -} - -// ValuesForInterface returns the values for all dynamic labels -func (l *DynamicLabelManager) ValuesForInterface(device *connector.Device, ifaceName string) []string { - labels := make([]string, len(l.labelNames)) - - k := interfaceKey{host: device.Host, ifaceName: ifaceName} - ifaceLabels, found := l.labels[k] - if !found { - return labels - } - - for _, la := range ifaceLabels { - labels[l.labelNames[la.name]] = la.value - } - - return labels -} - -func (l *DynamicLabelManager) parseDescriptions(device *connector.Device, ifaces []interfaceDescription, ifDescReg *regexp.Regexp) { - l.mu.Lock() - defer l.mu.Unlock() - - for _, in := range ifaces { - labels := ParseDescription(in.Description, ifDescReg) - - for _, la := range labels { - if _, found := l.labelNames[la.name]; !found { - l.labelNames[la.name] = l.labelCount - l.labelCount++ - } - - k := interfaceKey{host: device.Host, ifaceName: in.Name} - l.labels[k] = append(l.labels[k], la) - } - } -} - -func ParseDescription(description string, ifDescReg *regexp.Regexp) InterfaceLabels { - labels := make(InterfaceLabels, 0) - - if len(description) == 0 || ifDescReg == nil { - return labels - } - - matches := ifDescReg.FindAllStringSubmatch(description, -1) - for _, m := range matches { - n := strings.ToLower(m[1]) - - if !nameRe.Match([]byte(n)) { - continue - } - - label := &InterfaceLabel{ - name: n, - } - - val := m[2] - - if strings.HasPrefix(val, "=") { - label.value = val[1:] - } else { - label.value = "1" - } - - labels = append(labels, label) - } - - return labels -} - -type InterfaceLabels []*InterfaceLabel - -func (ils InterfaceLabels) Keys() []string { - ret := make([]string, 0, len(ils)) - for _, il := range ils { - ret = append(ret, il.name) - } - - return ret -} - -func (ils InterfaceLabels) Values() []string { - ret := make([]string, 0, len(ils)) - for _, il := range ils { - ret = append(ret, il.value) - } - - return ret -} diff --git a/pkg/interfacelabels/dynamic_labels_test.go b/pkg/interfacelabels/dynamic_labels_test.go deleted file mode 100644 index c0ea6bb..0000000 --- a/pkg/interfacelabels/dynamic_labels_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: MIT - -package interfacelabels - -import ( - "regexp" - "testing" - - "github.com/czerwonk/junos_exporter/pkg/connector" - "github.com/stretchr/testify/assert" -) - -func TestParseDescriptions(t *testing.T) { - t.Run("Test default", func(t *testing.T) { - l := NewDynamicLabelManager() - regex := DefaultInterfaceDescRegex() - - if1 := interfaceDescription{ - Name: "xe-0/0/0", - Description: "Name1 [tag1] [foo=x]", - } - if2 := interfaceDescription{ - Name: "xe-0/0/1", - Description: "Name2 [foo=y] [bar=123]", - } - if3 := interfaceDescription{ - Name: "xe-0/0/3", - } - if4 := interfaceDescription{ - Name: "irb.216", - Description: "Internal: Test-Network [vrf=AS4711]", - } - - d1 := &connector.Device{Host: "device1"} - d2 := &connector.Device{Host: "device2"} - - l.parseDescriptions(d1, []interfaceDescription{if1}, regex) - l.parseDescriptions(d2, []interfaceDescription{if2, if3, if4}, regex) - - assert.Equal(t, []string{"tag1", "foo", "bar", "vrf"}, l.LabelNames(), "Label names") - assert.Equal(t, []string{"1", "x", "", ""}, l.ValuesForInterface(d1, if1.Name), "Values if1") - assert.Equal(t, []string{"", "y", "123", ""}, l.ValuesForInterface(d2, if2.Name), "Values if2") - assert.Equal(t, []string{"", "", "", ""}, l.ValuesForInterface(d2, if3.Name), "Values if3") - assert.Equal(t, []string{"", "", "", "AS4711"}, l.ValuesForInterface(d2, if4.Name), "Values if4") - }) - - t.Run("Test custom regex", func(t *testing.T) { - l := NewDynamicLabelManager() - regex := regexp.MustCompile(`[[\s]([^=\[\]]+)(=[^,\]]+)?[,\]]`) - - if1 := interfaceDescription{ - Name: "xe-0/0/0", - Description: "Name1 [foo=x, bar=y, thisisatag]", - } - if2 := interfaceDescription{ - Name: "xe-0/0/1", - Description: "Name2 [onlyatag]", - } - if3 := interfaceDescription{ - Name: "xe-0/0/3", - Description: "Name2 [foo=x, bar=y, this=is]", - } - - d1 := &connector.Device{Host: "device1"} - d2 := &connector.Device{Host: "device2"} - d3 := &connector.Device{Host: "device3"} - - l.parseDescriptions(d1, []interfaceDescription{if1}, regex) - l.parseDescriptions(d2, []interfaceDescription{if2}, regex) - l.parseDescriptions(d3, []interfaceDescription{if3}, regex) - - assert.Equal(t, []string{"foo", "bar", "thisisatag", "onlyatag", "this"}, l.LabelNames(), "Label names") - assert.Equal(t, []string{"x", "y", "1", "", ""}, l.ValuesForInterface(d1, if1.Name), "Values if1") - assert.Equal(t, []string{"", "", "", "1", ""}, l.ValuesForInterface(d2, if2.Name), "Values if2") - assert.Equal(t, []string{"x", "y", "", "", "is"}, l.ValuesForInterface(d3, if3.Name), "Values if3") - }) -} diff --git a/pkg/interfacelabels/rpc.go b/pkg/interfacelabels/rpc.go deleted file mode 100644 index 6e96a09..0000000 --- a/pkg/interfacelabels/rpc.go +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT - -package interfacelabels - -type result struct { - Information struct { - PhysicalInterfaces []interfaceDescription `xml:"physical-interface"` - LogicalInterfaces []interfaceDescription `xml:"logical-interface"` - } `xml:"interface-information"` -} - -type interfaceDescription struct { - Name string `xml:"name"` - Description string `xml:"description"` -}