diff --git a/docs/collector.net.md b/docs/collector.net.md index 52dd118d..1e176798 100644 --- a/docs/collector.net.md +++ b/docs/collector.net.md @@ -42,6 +42,7 @@ Comma-separated list of collectors to use. Defaults to all, if not specified. | `windows_net_current_bandwidth_bytes` | Estimate of the interface's current bandwidth in bytes per second | gauge | `nic` | | `windows_net_nic_address_info` | A metric with a constant '1' value labeled with the network interface's address information. | gauge | `nic`, `address`, `family` | | `windows_net_nic_info` | A metric with a constant '1' value labeled with the network interface's general information. | gauge | `nic`, `friendly_name`, `mac` | +| `windows_net_nic_operation_status` | The operational status for the interface as defined in RFC 2863 as IfOperStatus. | gauge | `nic`, `status` | | `windows_net_route_info` | A metric with a constant '1' value labeled with the network interface's route information. | gauge | `nic`, `src`, `dest`, `metric` | ### Example metric diff --git a/internal/collector/net/net.go b/internal/collector/net/net.go index ba1e7046..d8b1c3c1 100644 --- a/internal/collector/net/net.go +++ b/internal/collector/net/net.go @@ -36,8 +36,8 @@ import ( const ( Name = "net" - subCollectorMetrics = "metrics" - subCollectorNicAddresses = "nic_addresses" + subCollectorMetrics = "metrics" + subCollectorNicInfo = "nic_info" ) type Config struct { @@ -52,7 +52,7 @@ var ConfigDefaults = Config{ NicInclude: types.RegExpAny, CollectorsEnabled: []string{ subCollectorMetrics, - subCollectorNicAddresses, + subCollectorNicInfo, }, } @@ -78,6 +78,7 @@ type Collector struct { currentBandwidth *prometheus.Desc nicIPAddressInfo *prometheus.Desc + nicOperStatus *prometheus.Desc nicInfo *prometheus.Desc routeInfo *prometheus.Desc } @@ -247,6 +248,12 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { []string{"nic", "address", "family"}, nil, ) + c.nicOperStatus = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "nic_operation_status"), + "The operational status for the interface as defined in RFC 2863 as IfOperStatus.", + []string{"nic", "status"}, + nil, + ) c.nicInfo = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "nic_info"), "A metric with a constant '1' value labeled with the network interface's general information.", @@ -267,7 +274,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { return fmt.Errorf("failed to create Network Interface collector: %w", err) } - if slices.Contains(c.config.CollectorsEnabled, subCollectorNicAddresses) { + if slices.Contains(c.config.CollectorsEnabled, subCollectorNicInfo) { logger.Info("nic/addresses collector is in an experimental state! The configuration and metrics may change in future. Please report any issues.", slog.String("collector", Name), ) @@ -287,8 +294,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error { } } - if slices.Contains(c.config.CollectorsEnabled, subCollectorNicAddresses) { - if err := c.collectNICAddresses(ch); err != nil { + if slices.Contains(c.config.CollectorsEnabled, subCollectorNicInfo) { + if err := c.collectNICInfo(ch); err != nil { errs = append(errs, fmt.Errorf("failed collecting net addresses: %w", err)) } } @@ -391,13 +398,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error { return nil } -//nolint:gochecknoglobals -var addressFamily = map[uint16]string{ - windows.AF_INET: "ipv4", - windows.AF_INET6: "ipv6", -} - -func (c *Collector) collectNICAddresses(ch chan<- prometheus.Metric) error { +func (c *Collector) collectNICInfo(ch chan<- prometheus.Metric) error { nicAdapterAddresses, err := adapterAddresses() if err != nil { return err @@ -432,6 +433,21 @@ func (c *Collector) collectNICAddresses(ch chan<- prometheus.Metric) error { macAddress, ) + for operState, labelValue := range operStatus { + var metricStatus float64 + if operState == nicAdapter.OperStatus { + metricStatus = 1 + } + + ch <- prometheus.MustNewConstMetric( + c.nicOperStatus, + prometheus.GaugeValue, + metricStatus, + nicName, + labelValue, + ) + } + if nicAdapter.OperStatus != windows.IfOperStatusUp { continue } diff --git a/internal/collector/net/types.go b/internal/collector/net/types.go index c06c2413..3016ef99 100644 --- a/internal/collector/net/types.go +++ b/internal/collector/net/types.go @@ -15,6 +15,25 @@ package net +import "golang.org/x/sys/windows" + +//nolint:gochecknoglobals +var ( + addressFamily = map[uint16]string{ + windows.AF_INET: "ipv4", + windows.AF_INET6: "ipv6", + } + operStatus = map[uint32]string{ + windows.IfOperStatusUp: "up", + windows.IfOperStatusDown: "down", + windows.IfOperStatusTesting: "testing", + windows.IfOperStatusUnknown: "unknown", + windows.IfOperStatusDormant: "dormant", + windows.IfOperStatusNotPresent: "not present", + windows.IfOperStatusLowerLayerDown: "lower layer down", + } +) + type perfDataCounterValues struct { Name string diff --git a/tools/e2e-output.txt b/tools/e2e-output.txt index 8705d5ac..fc316d31 100644 --- a/tools/e2e-output.txt +++ b/tools/e2e-output.txt @@ -277,6 +277,8 @@ windows_exporter_collector_timeout{collector="udp"} 0 # TYPE windows_net_nic_address_info gauge # HELP windows_net_nic_info A metric with a constant '1' value labeled with the network interface's general information. # TYPE windows_net_nic_info gauge +# HELP windows_net_nic_operation_status The operational status for the interface as defined in RFC 2863 as IfOperStatus. +# TYPE windows_net_nic_operation_status gauge # HELP windows_net_output_queue_length_packets (Network.OutputQueueLength) # TYPE windows_net_output_queue_length_packets gauge # HELP windows_net_packets_outbound_discarded_total (Network.PacketsOutboundDiscarded) diff --git a/tools/end-to-end-test.ps1 b/tools/end-to-end-test.ps1 index 0ecc27a8..4eb1888c 100644 --- a/tools/end-to-end-test.ps1 +++ b/tools/end-to-end-test.ps1 @@ -66,7 +66,8 @@ try { throw $_ } -$output_diff = Compare-Object ((Get-Content 'e2e-output.txt' | Out-String).Trim()) ((Get-Content "$($temp_dir)/e2e-output.txt" | Out-String).Trim()) +# Compare the expected and actual output +$output_diff = Compare-Object (Get-Content 'e2e-output.txt' | Where-Object { $_ -ne "" }) (Get-Content "$($temp_dir)/e2e-output.txt" | Where-Object { $_ -ne "" }) # Fail if differences in output are detected if (-not ($null -eq $output_diff)) { @@ -74,6 +75,7 @@ if (-not ($null -eq $output_diff)) { Write-Host "STDOUT" Get-Content "$($temp_dir)/windows_exporter.log" + Write-Host "----------------------------------------" Write-Host "STDERR" Get-Content "$($temp_dir)/windows_exporter_error.log"