mirror of
				https://github.com/prometheus/node_exporter.git
				synced 2025-08-20 18:33:52 -07:00 
			
		
		
		
	Merge branch 'master' into master
This commit is contained in:
		
						commit
						026383cf5a
					
				| 
						 | 
					@ -69,7 +69,7 @@ func (c *btrfsCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, s := range stats {
 | 
						for _, s := range stats {
 | 
				
			||||||
		// match up procfs and ioctl info by filesystem UUID (without dashes)
 | 
							// match up procfs and ioctl info by filesystem UUID (without dashes)
 | 
				
			||||||
		var fsUUID = strings.Replace(s.UUID, "-", "", -1)
 | 
							var fsUUID = strings.ReplaceAll(s.UUID, "-", "")
 | 
				
			||||||
		ioctlStats := ioctlStatsMap[fsUUID]
 | 
							ioctlStats := ioctlStatsMap[fsUUID]
 | 
				
			||||||
		c.updateBtrfsStats(ch, s, ioctlStats)
 | 
							c.updateBtrfsStats(ch, s, ioctlStats)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,22 +30,50 @@ import (
 | 
				
			||||||
	"github.com/prometheus/client_golang/prometheus"
 | 
						"github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						nodeCPUPhysicalSecondsDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "physical_seconds_total"),
 | 
				
			||||||
 | 
							"Seconds the physical CPUs spent in each mode.",
 | 
				
			||||||
 | 
							[]string{"cpu", "mode"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						nodeCPUSRunQueueDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "runqueue"),
 | 
				
			||||||
 | 
							"Length of the run queue.", []string{"cpu"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						nodeCPUFlagsDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "flags"),
 | 
				
			||||||
 | 
							"CPU flags.",
 | 
				
			||||||
 | 
							[]string{"cpu", "flag"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						nodeCPUContextSwitchDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "context_switches_total"),
 | 
				
			||||||
 | 
							"Number of context switches.",
 | 
				
			||||||
 | 
							[]string{"cpu"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type cpuCollector struct {
 | 
					type cpuCollector struct {
 | 
				
			||||||
	cpu              typedDesc
 | 
						cpu              typedDesc
 | 
				
			||||||
 | 
						cpuPhysical      typedDesc
 | 
				
			||||||
 | 
						cpuRunQueue      typedDesc
 | 
				
			||||||
 | 
						cpuFlags         typedDesc
 | 
				
			||||||
 | 
						cpuContextSwitch typedDesc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logger             *slog.Logger
 | 
						logger             *slog.Logger
 | 
				
			||||||
	tickPerSecond int64
 | 
						tickPerSecond      float64
 | 
				
			||||||
 | 
						purrTicksPerSecond float64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	registerCollector("cpu", defaultEnabled, NewCpuCollector)
 | 
						registerCollector("cpu", defaultEnabled, NewCpuCollector)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func tickPerSecond() (int64, error) {
 | 
					func tickPerSecond() (float64, error) {
 | 
				
			||||||
	ticks, err := C.sysconf(C._SC_CLK_TCK)
 | 
						ticks, err := C.sysconf(C._SC_CLK_TCK)
 | 
				
			||||||
	if ticks == -1 || err != nil {
 | 
						if ticks == -1 || err != nil {
 | 
				
			||||||
		return 0, fmt.Errorf("failed to get clock ticks per second: %v", err)
 | 
							return 0, fmt.Errorf("failed to get clock ticks per second: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return int64(ticks), nil
 | 
						return float64(ticks), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCpuCollector(logger *slog.Logger) (Collector, error) {
 | 
					func NewCpuCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
| 
						 | 
					@ -53,10 +81,22 @@ func NewCpuCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pconfig, err := perfstat.PartitionStat()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &cpuCollector{
 | 
						return &cpuCollector{
 | 
				
			||||||
		cpu:                typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
 | 
							cpu:                typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
 | 
				
			||||||
 | 
							cpuPhysical:        typedDesc{nodeCPUPhysicalSecondsDesc, prometheus.CounterValue},
 | 
				
			||||||
 | 
							cpuRunQueue:        typedDesc{nodeCPUSRunQueueDesc, prometheus.GaugeValue},
 | 
				
			||||||
 | 
							cpuFlags:           typedDesc{nodeCPUFlagsDesc, prometheus.GaugeValue},
 | 
				
			||||||
 | 
							cpuContextSwitch:   typedDesc{nodeCPUContextSwitchDesc, prometheus.CounterValue},
 | 
				
			||||||
		logger:             logger,
 | 
							logger:             logger,
 | 
				
			||||||
		tickPerSecond:      ticks,
 | 
							tickPerSecond:      ticks,
 | 
				
			||||||
 | 
							purrTicksPerSecond: float64(pconfig.ProcessorMhz * 1e6),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,10 +107,26 @@ func (c *cpuCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for n, stat := range stats {
 | 
						for n, stat := range stats {
 | 
				
			||||||
		ch <- c.cpu.mustNewConstMetric(float64(stat.User/c.tickPerSecond), strconv.Itoa(n), "user")
 | 
							// LPAR metrics
 | 
				
			||||||
		ch <- c.cpu.mustNewConstMetric(float64(stat.Sys/c.tickPerSecond), strconv.Itoa(n), "system")
 | 
							ch <- c.cpu.mustNewConstMetric(float64(stat.User)/c.tickPerSecond, strconv.Itoa(n), "user")
 | 
				
			||||||
		ch <- c.cpu.mustNewConstMetric(float64(stat.Idle/c.tickPerSecond), strconv.Itoa(n), "idle")
 | 
							ch <- c.cpu.mustNewConstMetric(float64(stat.Sys)/c.tickPerSecond, strconv.Itoa(n), "system")
 | 
				
			||||||
		ch <- c.cpu.mustNewConstMetric(float64(stat.Wait/c.tickPerSecond), strconv.Itoa(n), "wait")
 | 
							ch <- c.cpu.mustNewConstMetric(float64(stat.Idle)/c.tickPerSecond, strconv.Itoa(n), "idle")
 | 
				
			||||||
 | 
							ch <- c.cpu.mustNewConstMetric(float64(stat.Wait)/c.tickPerSecond, strconv.Itoa(n), "wait")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Physical CPU metrics
 | 
				
			||||||
 | 
							ch <- c.cpuPhysical.mustNewConstMetric(float64(stat.PIdle)/c.purrTicksPerSecond, strconv.Itoa(n), "pidle")
 | 
				
			||||||
 | 
							ch <- c.cpuPhysical.mustNewConstMetric(float64(stat.PUser)/c.purrTicksPerSecond, strconv.Itoa(n), "puser")
 | 
				
			||||||
 | 
							ch <- c.cpuPhysical.mustNewConstMetric(float64(stat.PSys)/c.purrTicksPerSecond, strconv.Itoa(n), "psys")
 | 
				
			||||||
 | 
							ch <- c.cpuPhysical.mustNewConstMetric(float64(stat.PWait)/c.purrTicksPerSecond, strconv.Itoa(n), "pwait")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Run queue length
 | 
				
			||||||
 | 
							ch <- c.cpuRunQueue.mustNewConstMetric(float64(stat.RunQueue), strconv.Itoa(n))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Flags
 | 
				
			||||||
 | 
							ch <- c.cpuFlags.mustNewConstMetric(float64(stat.SpurrFlag), strconv.Itoa(n), "spurr")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Context switches
 | 
				
			||||||
 | 
							ch <- c.cpuContextSwitch.mustNewConstMetric(float64(stat.CSwitches), strconv.Itoa(n))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ func NewCPUCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
	isolcpus, err := sfs.IsolatedCPUs()
 | 
						isolcpus, err := sfs.IsolatedCPUs()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if !os.IsNotExist(err) {
 | 
							if !os.IsNotExist(err) {
 | 
				
			||||||
			return nil, fmt.Errorf("Unable to get isolated cpus: %w", err)
 | 
								return nil, fmt.Errorf("unable to get isolated cpus: %w", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		logger.Debug("Could not open isolated file", "error", err)
 | 
							logger.Debug("Could not open isolated file", "error", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@ func getCPUTemperatures() (map[int]float64, error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keys := sortFilterSysmonProperties(props, "coretemp")
 | 
						keys := sortFilterSysmonProperties(props, "coretemp")
 | 
				
			||||||
	for idx, _ := range keys {
 | 
						for idx := range keys {
 | 
				
			||||||
		convertTemperatures(props[keys[idx]], res)
 | 
							convertTemperatures(props[keys[idx]], res)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,12 +22,12 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	cpuVulerabilitiesCollector = "cpu_vulnerabilities"
 | 
						cpuVulnerabilitiesCollectorSubsystem = "cpu_vulnerabilities"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	vulnerabilityDesc = prometheus.NewDesc(
 | 
						vulnerabilityDesc = prometheus.NewDesc(
 | 
				
			||||||
		prometheus.BuildFQName(namespace, cpuVulerabilitiesCollector, "info"),
 | 
							prometheus.BuildFQName(namespace, cpuVulnerabilitiesCollectorSubsystem, "info"),
 | 
				
			||||||
		"Details of each CPU vulnerability reported by sysfs. The value of the series is an int encoded state of the vulnerability. The same state is stored as a string in the label",
 | 
							"Details of each CPU vulnerability reported by sysfs. The value of the series is an int encoded state of the vulnerability. The same state is stored as a string in the label",
 | 
				
			||||||
		[]string{"codename", "state", "mitigation"},
 | 
							[]string{"codename", "state", "mitigation"},
 | 
				
			||||||
		nil,
 | 
							nil,
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ var (
 | 
				
			||||||
type cpuVulnerabilitiesCollector struct{}
 | 
					type cpuVulnerabilitiesCollector struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	registerCollector(cpuVulerabilitiesCollector, defaultDisabled, NewVulnerabilitySysfsCollector)
 | 
						registerCollector(cpuVulnerabilitiesCollectorSubsystem, defaultDisabled, NewVulnerabilitySysfsCollector)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewVulnerabilitySysfsCollector(logger *slog.Logger) (Collector, error) {
 | 
					func NewVulnerabilitySysfsCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,11 +30,19 @@ type diskstatsCollector struct {
 | 
				
			||||||
	rbytes typedDesc
 | 
						rbytes typedDesc
 | 
				
			||||||
	wbytes typedDesc
 | 
						wbytes typedDesc
 | 
				
			||||||
	time   typedDesc
 | 
						time   typedDesc
 | 
				
			||||||
 | 
						bsize  typedDesc
 | 
				
			||||||
 | 
						qdepth typedDesc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rserv typedDesc
 | 
				
			||||||
 | 
						wserv typedDesc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfers typedDesc
 | 
				
			||||||
 | 
						xrate typedDesc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	deviceFilter deviceFilter
 | 
						deviceFilter deviceFilter
 | 
				
			||||||
	logger       *slog.Logger
 | 
						logger       *slog.Logger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tickPerSecond int64
 | 
						tickPerSecond float64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
| 
						 | 
					@ -57,6 +65,54 @@ func NewDiskstatsCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
		wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue},
 | 
							wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue},
 | 
				
			||||||
		time:   typedDesc{ioTimeSecondsDesc, prometheus.CounterValue},
 | 
							time:   typedDesc{ioTimeSecondsDesc, prometheus.CounterValue},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bsize: typedDesc{
 | 
				
			||||||
 | 
								prometheus.NewDesc(
 | 
				
			||||||
 | 
									prometheus.BuildFQName(namespace, diskSubsystem, "block_size_bytes"),
 | 
				
			||||||
 | 
									"Size of the block device in bytes.",
 | 
				
			||||||
 | 
									diskLabelNames, nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								prometheus.GaugeValue,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							qdepth: typedDesc{
 | 
				
			||||||
 | 
								prometheus.NewDesc(
 | 
				
			||||||
 | 
									prometheus.BuildFQName(namespace, diskSubsystem, "queue_depth"),
 | 
				
			||||||
 | 
									"Number of requests in the queue.",
 | 
				
			||||||
 | 
									diskLabelNames, nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								prometheus.GaugeValue,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							rserv: typedDesc{
 | 
				
			||||||
 | 
								prometheus.NewDesc(
 | 
				
			||||||
 | 
									prometheus.BuildFQName(namespace, diskSubsystem, "read_time_seconds_total"),
 | 
				
			||||||
 | 
									"The total time spent servicing read requests.",
 | 
				
			||||||
 | 
									diskLabelNames, nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							wserv: typedDesc{
 | 
				
			||||||
 | 
								prometheus.NewDesc(
 | 
				
			||||||
 | 
									prometheus.BuildFQName(namespace, diskSubsystem, "write_time_seconds_total"),
 | 
				
			||||||
 | 
									"The total time spent servicing write requests.",
 | 
				
			||||||
 | 
									diskLabelNames, nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							xfers: typedDesc{
 | 
				
			||||||
 | 
								prometheus.NewDesc(
 | 
				
			||||||
 | 
									prometheus.BuildFQName(namespace, diskSubsystem, "transfers_total"),
 | 
				
			||||||
 | 
									"The total number of transfers to/from disk.",
 | 
				
			||||||
 | 
									diskLabelNames, nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							xrate: typedDesc{
 | 
				
			||||||
 | 
								prometheus.NewDesc(
 | 
				
			||||||
 | 
									prometheus.BuildFQName(namespace, diskSubsystem, "transfers_to_disk_total"),
 | 
				
			||||||
 | 
									"The total number of transfers from disk.",
 | 
				
			||||||
 | 
									diskLabelNames, nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		deviceFilter: deviceFilter,
 | 
							deviceFilter: deviceFilter,
 | 
				
			||||||
		logger:       logger,
 | 
							logger:       logger,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,7 +132,14 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ch <- c.rbytes.mustNewConstMetric(float64(stat.Rblks*512), stat.Name)
 | 
							ch <- c.rbytes.mustNewConstMetric(float64(stat.Rblks*512), stat.Name)
 | 
				
			||||||
		ch <- c.wbytes.mustNewConstMetric(float64(stat.Wblks*512), stat.Name)
 | 
							ch <- c.wbytes.mustNewConstMetric(float64(stat.Wblks*512), stat.Name)
 | 
				
			||||||
		ch <- c.time.mustNewConstMetric(float64(stat.Time/c.tickPerSecond), stat.Name)
 | 
							ch <- c.time.mustNewConstMetric(float64(stat.Time)/float64(c.tickPerSecond), stat.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ch <- c.bsize.mustNewConstMetric(float64(stat.BSize), stat.Name)
 | 
				
			||||||
 | 
							ch <- c.qdepth.mustNewConstMetric(float64(stat.QDepth), stat.Name)
 | 
				
			||||||
 | 
							ch <- c.rserv.mustNewConstMetric(float64(stat.Rserv)/1e9, stat.Name)
 | 
				
			||||||
 | 
							ch <- c.wserv.mustNewConstMetric(float64(stat.Wserv)/1e9, stat.Name)
 | 
				
			||||||
 | 
							ch <- c.xfers.mustNewConstMetric(float64(stat.Xfers), stat.Name)
 | 
				
			||||||
 | 
							ch <- c.xrate.mustNewConstMetric(float64(stat.XRate), stat.Name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -453,6 +453,7 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Sanitizing the metric names can lead to duplicate metric names. Therefore check for clashes beforehand.
 | 
							// Sanitizing the metric names can lead to duplicate metric names. Therefore check for clashes beforehand.
 | 
				
			||||||
		metricFQNames := make(map[string]string)
 | 
							metricFQNames := make(map[string]string)
 | 
				
			||||||
 | 
							renamedStats := make(map[string]uint64, len(stats))
 | 
				
			||||||
		for metric := range stats {
 | 
							for metric := range stats {
 | 
				
			||||||
			metricName := SanitizeMetricName(metric)
 | 
								metricName := SanitizeMetricName(metric)
 | 
				
			||||||
			if !c.metricsPattern.MatchString(metricName) {
 | 
								if !c.metricsPattern.MatchString(metricName) {
 | 
				
			||||||
| 
						 | 
					@ -467,6 +468,8 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
				metricFQNames[metricFQName] = ""
 | 
									metricFQNames[metricFQName] = ""
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				metricFQNames[metricFQName] = metricName
 | 
									metricFQNames[metricFQName] = metricName
 | 
				
			||||||
 | 
									// Later we'll go look for the stat with the "sanitized" metric name, so we can copy it there already
 | 
				
			||||||
 | 
									renamedStats[metricName] = stats[metric]
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -484,7 +487,7 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			val := stats[metric]
 | 
								val := renamedStats[metric]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Check to see if this metric exists; if not then create it and store it in c.entries.
 | 
								// Check to see if this metric exists; if not then create it and store it in c.entries.
 | 
				
			||||||
			entry := c.entryWithCreate(metric, metricFQName)
 | 
								entry := c.entryWithCreate(metric, metricFQName)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,16 +212,18 @@ func (e *EthtoolFixture) LinkInfo(intf string) (ethtool.EthtoolCmd, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		items := strings.Split(line, ": ")
 | 
							items := strings.Split(line, ": ")
 | 
				
			||||||
		if items[0] == "Supported pause frame use" {
 | 
							if items[0] == "Supported pause frame use" {
 | 
				
			||||||
			if items[1] == "Symmetric" {
 | 
								switch items[1] {
 | 
				
			||||||
 | 
								case "Symmetric":
 | 
				
			||||||
				res.Supported |= (1 << unix.ETHTOOL_LINK_MODE_Pause_BIT)
 | 
									res.Supported |= (1 << unix.ETHTOOL_LINK_MODE_Pause_BIT)
 | 
				
			||||||
			} else if items[1] == "Receive-only" {
 | 
								case "Receive-only":
 | 
				
			||||||
				res.Supported |= (1 << unix.ETHTOOL_LINK_MODE_Asym_Pause_BIT)
 | 
									res.Supported |= (1 << unix.ETHTOOL_LINK_MODE_Asym_Pause_BIT)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if items[0] == "Advertised pause frame use" {
 | 
							if items[0] == "Advertised pause frame use" {
 | 
				
			||||||
			if items[1] == "Symmetric" {
 | 
								switch items[1] {
 | 
				
			||||||
 | 
								case "Symmetric":
 | 
				
			||||||
				res.Advertising |= (1 << unix.ETHTOOL_LINK_MODE_Pause_BIT)
 | 
									res.Advertising |= (1 << unix.ETHTOOL_LINK_MODE_Pause_BIT)
 | 
				
			||||||
			} else if items[1] == "Receive-only" {
 | 
								case "Receive-only":
 | 
				
			||||||
				res.Advertising |= (1 << unix.ETHTOOL_LINK_MODE_Asym_Pause_BIT)
 | 
									res.Advertising |= (1 << unix.ETHTOOL_LINK_MODE_Asym_Pause_BIT)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -269,6 +271,7 @@ func NewEthtoolTestCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestBuildEthtoolFQName(t *testing.T) {
 | 
					func TestBuildEthtoolFQName(t *testing.T) {
 | 
				
			||||||
	testcases := map[string]string{
 | 
						testcases := map[string]string{
 | 
				
			||||||
 | 
							"port.rx_errors":               "node_ethtool_port_received_errors",
 | 
				
			||||||
		"rx_errors":                    "node_ethtool_received_errors",
 | 
							"rx_errors":                    "node_ethtool_received_errors",
 | 
				
			||||||
		"Queue[0] AllocFails":          "node_ethtool_queue_0_allocfails",
 | 
							"Queue[0] AllocFails":          "node_ethtool_queue_0_allocfails",
 | 
				
			||||||
		"Tx LPI entry count":           "node_ethtool_transmitted_lpi_entry_count",
 | 
							"Tx LPI entry count":           "node_ethtool_transmitted_lpi_entry_count",
 | 
				
			||||||
| 
						 | 
					@ -292,6 +295,9 @@ node_ethtool_align_errors{device="eth0"} 0
 | 
				
			||||||
# HELP node_ethtool_info A metric with a constant '1' value labeled by bus_info, device, driver, expansion_rom_version, firmware_version, version.
 | 
					# HELP node_ethtool_info A metric with a constant '1' value labeled by bus_info, device, driver, expansion_rom_version, firmware_version, version.
 | 
				
			||||||
# TYPE node_ethtool_info gauge
 | 
					# TYPE node_ethtool_info gauge
 | 
				
			||||||
node_ethtool_info{bus_info="0000:00:1f.6",device="eth0",driver="e1000e",expansion_rom_version="",firmware_version="0.5-4",version="5.11.0-22-generic"} 1
 | 
					node_ethtool_info{bus_info="0000:00:1f.6",device="eth0",driver="e1000e",expansion_rom_version="",firmware_version="0.5-4",version="5.11.0-22-generic"} 1
 | 
				
			||||||
 | 
					# HELP node_ethtool_port_received_dropped Network interface port_rx_dropped
 | 
				
			||||||
 | 
					# TYPE node_ethtool_port_received_dropped untyped
 | 
				
			||||||
 | 
					node_ethtool_port_received_dropped{device="eth0"} 12028
 | 
				
			||||||
# HELP node_ethtool_received_broadcast Network interface rx_broadcast
 | 
					# HELP node_ethtool_received_broadcast Network interface rx_broadcast
 | 
				
			||||||
# TYPE node_ethtool_received_broadcast untyped
 | 
					# TYPE node_ethtool_received_broadcast untyped
 | 
				
			||||||
node_ethtool_received_broadcast{device="eth0"} 5792
 | 
					node_ethtool_received_broadcast{device="eth0"} 5792
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,9 +53,9 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
 | 
				
			||||||
				mountPoint: stat.MountPoint,
 | 
									mountPoint: stat.MountPoint,
 | 
				
			||||||
				fsType:     fstype,
 | 
									fsType:     fstype,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			size:      float64(stat.TotalBlocks / 512.0),
 | 
								size:      float64(stat.TotalBlocks * 512.0),
 | 
				
			||||||
			free:      float64(stat.FreeBlocks / 512.0),
 | 
								free:      float64(stat.FreeBlocks * 512.0),
 | 
				
			||||||
			avail:     float64(stat.FreeBlocks / 512.0), // AIX doesn't distinguish between free and available blocks.
 | 
								avail:     float64(stat.FreeBlocks * 512.0), // AIX doesn't distinguish between free and available blocks.
 | 
				
			||||||
			files:     float64(stat.TotalInodes),
 | 
								files:     float64(stat.TotalInodes),
 | 
				
			||||||
			filesFree: float64(stat.FreeInodes),
 | 
								filesFree: float64(stat.FreeInodes),
 | 
				
			||||||
			ro:        ro,
 | 
								ro:        ro,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,8 +215,8 @@ func parseFilesystemLabels(r io.Reader) ([]filesystemLabels, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Ensure we handle the translation of \040 and \011
 | 
							// Ensure we handle the translation of \040 and \011
 | 
				
			||||||
		// as per fstab(5).
 | 
							// as per fstab(5).
 | 
				
			||||||
		parts[4] = strings.Replace(parts[4], "\\040", " ", -1)
 | 
							parts[4] = strings.ReplaceAll(parts[4], "\\040", " ")
 | 
				
			||||||
		parts[4] = strings.Replace(parts[4], "\\011", "\t", -1)
 | 
							parts[4] = strings.ReplaceAll(parts[4], "\\011", "\t")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		filesystems = append(filesystems, filesystemLabels{
 | 
							filesystems = append(filesystems, filesystemLabels{
 | 
				
			||||||
			device:      parts[m+3],
 | 
								device:      parts[m+3],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,22 +21,26 @@ package collector
 | 
				
			||||||
#cgo LDFLAGS: -framework Foundation
 | 
					#cgo LDFLAGS: -framework Foundation
 | 
				
			||||||
#import <Foundation/Foundation.h>
 | 
					#import <Foundation/Foundation.h>
 | 
				
			||||||
Float64 purgeable(char *path) {
 | 
					Float64 purgeable(char *path) {
 | 
				
			||||||
  CFNumberRef tmp;
 | 
					  Float64 value = -1.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @autoreleasepool {
 | 
				
			||||||
    NSError *error = nil;
 | 
					    NSError *error = nil;
 | 
				
			||||||
    NSString *str = [NSString stringWithUTF8String:path];
 | 
					    NSString *str = [NSString stringWithUTF8String:path];
 | 
				
			||||||
    NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:str];
 | 
					    NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:str];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NSDictionary *results = [fileURL resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey] error:&error];
 | 
					    NSDictionary *results = [fileURL resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey] error:&error];
 | 
				
			||||||
    if (results) {
 | 
					    if (results) {
 | 
				
			||||||
    if ((tmp = CFDictionaryGetValue((CFDictionaryRef)results, NSURLVolumeAvailableCapacityForImportantUsageKey)) == NULL) {
 | 
					      CFNumberRef tmp = CFDictionaryGetValue((CFDictionaryRef)results, NSURLVolumeAvailableCapacityForImportantUsageKey);
 | 
				
			||||||
      return -1.0f;
 | 
					      if (tmp != NULL) {
 | 
				
			||||||
 | 
					        CFNumberGetValue(tmp, kCFNumberFloat64Type, &value);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    Float64 value;
 | 
					    }
 | 
				
			||||||
    if (CFNumberGetValue(tmp, kCFNumberFloat64Type, &value)) {
 | 
					
 | 
				
			||||||
 | 
					    [fileURL release];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return value;
 | 
					  return value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return -1.0f;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
import "C"
 | 
					import "C"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,6 +92,9 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
 | 
				
			||||||
			ro = 1
 | 
								ro = 1
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mountpointCString := C.CString(mountpoint)
 | 
				
			||||||
 | 
							defer C.free(unsafe.Pointer(mountpointCString))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		stats = append(stats, filesystemStats{
 | 
							stats = append(stats, filesystemStats{
 | 
				
			||||||
			labels: filesystemLabels{
 | 
								labels: filesystemLabels{
 | 
				
			||||||
				device:     device,
 | 
									device:     device,
 | 
				
			||||||
| 
						 | 
					@ -99,7 +106,7 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
 | 
				
			||||||
			avail:     float64(mnt[i].f_bavail) * float64(mnt[i].f_bsize),
 | 
								avail:     float64(mnt[i].f_bavail) * float64(mnt[i].f_bsize),
 | 
				
			||||||
			files:     float64(mnt[i].f_files),
 | 
								files:     float64(mnt[i].f_files),
 | 
				
			||||||
			filesFree: float64(mnt[i].f_ffree),
 | 
								filesFree: float64(mnt[i].f_ffree),
 | 
				
			||||||
			purgeable: float64(C.purgeable(C.CString(mountpoint))),
 | 
								purgeable: float64(C.purgeable(mountpointCString)),
 | 
				
			||||||
			ro:        ro,
 | 
								ro:        ro,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ NIC statistics:
 | 
				
			||||||
     rx_packets: 1260062
 | 
					     rx_packets: 1260062
 | 
				
			||||||
     tx_errors: 0
 | 
					     tx_errors: 0
 | 
				
			||||||
     rx_errors: 0
 | 
					     rx_errors: 0
 | 
				
			||||||
 | 
					     port.rx_dropped: 12028
 | 
				
			||||||
     rx_missed: 401
 | 
					     rx_missed: 401
 | 
				
			||||||
     align_errors: 0
 | 
					     align_errors: 0
 | 
				
			||||||
     tx_single_collisions: 0
 | 
					     tx_single_collisions: 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,4 +2,4 @@ net 70 70 69 45
 | 
				
			||||||
rpc 1218785755 374636 1218815394
 | 
					rpc 1218785755 374636 1218815394
 | 
				
			||||||
proc2 18 16 57 74 52 71 73 45 86 0 52 83 61 17 53 50 23 70 82
 | 
					proc2 18 16 57 74 52 71 73 45 86 0 52 83 61 17 53 50 23 70 82
 | 
				
			||||||
proc3 22 0 1061909262 48906 4077635 117661341 5 29391916 2570425 2993289 590 0 0 7815 15 1130 0 3983 92385 13332 2 1 23729
 | 
					proc3 22 0 1061909262 48906 4077635 117661341 5 29391916 2570425 2993289 590 0 0 7815 15 1130 0 3983 92385 13332 2 1 23729
 | 
				
			||||||
proc4 48 98 51 54 83 85 23 24 1 28 73 68 83 12 84 39 68 59 58 88 29 74 69 96 21 84 15 53 86 54 66 56 97 36 49 32 85 81 11 58 32 67 13 28 35 90 1 26 0
 | 
					proc4 48 98 51 54 83 85 23 24 1 28 73 68 83 12 84 39 68 59 58 88 29 74 69 96 21 84 15 53 86 54 66 56 97 36 49 32 85 81 11 58 32 67 13 28 35 1 90 26 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2174,6 +2174,11 @@ Mode: 755
 | 
				
			||||||
Directory: sys/class/nvme/nvme0
 | 
					Directory: sys/class/nvme/nvme0
 | 
				
			||||||
Mode: 755
 | 
					Mode: 755
 | 
				
			||||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
				
			||||||
 | 
					Path: sys/class/nvme/nvme0/cntlid
 | 
				
			||||||
 | 
					Lines: 1
 | 
				
			||||||
 | 
					1997
 | 
				
			||||||
 | 
					Mode: 644
 | 
				
			||||||
 | 
					# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
				
			||||||
Path: sys/class/nvme/nvme0/firmware_rev
 | 
					Path: sys/class/nvme/nvme0/firmware_rev
 | 
				
			||||||
Lines: 1
 | 
					Lines: 1
 | 
				
			||||||
1B2QEXP7
 | 
					1B2QEXP7
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,5 +43,9 @@ func (c *meminfoCollector) getMemInfo() (map[string]float64, error) {
 | 
				
			||||||
		"total_bytes":              float64(stats.RealTotal * 4096),
 | 
							"total_bytes":              float64(stats.RealTotal * 4096),
 | 
				
			||||||
		"free_bytes":               float64(stats.RealFree * 4096),
 | 
							"free_bytes":               float64(stats.RealFree * 4096),
 | 
				
			||||||
		"available_bytes":          float64(stats.RealAvailable * 4096),
 | 
							"available_bytes":          float64(stats.RealAvailable * 4096),
 | 
				
			||||||
 | 
							"process_bytes":            float64(stats.RealProcess * 4096),
 | 
				
			||||||
 | 
							"paging_space_total_bytes": float64(stats.PgSpTotal * 4096),
 | 
				
			||||||
 | 
							"paging_space_free_bytes":  float64(stats.PgSpFree * 4096),
 | 
				
			||||||
 | 
							"page_scans_total":         float64(stats.Scans),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ func NewMeminfoCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
func (c *meminfoCollector) getMemInfo() (map[string]float64, error) {
 | 
					func (c *meminfoCollector) getMemInfo() (map[string]float64, error) {
 | 
				
			||||||
	meminfo, err := c.fs.Meminfo()
 | 
						meminfo, err := c.fs.Meminfo()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("Failed to get memory info: %s", err)
 | 
							return nil, fmt.Errorf("failed to get memory info: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metrics := make(map[string]float64)
 | 
						metrics := make(map[string]float64)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,16 +32,20 @@ func getNetDevStats(filter *deviceFilter, logger *slog.Logger) (netDevStats, err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, stat := range stats {
 | 
						for _, stat := range stats {
 | 
				
			||||||
		netDev[stat.Name] = map[string]uint64{
 | 
							netDev[stat.Name] = map[string]uint64{
 | 
				
			||||||
			"receive_packets":    uint64(stat.RxPackets),
 | 
					 | 
				
			||||||
			"transmit_packets":   uint64(stat.TxPackets),
 | 
					 | 
				
			||||||
			"receive_bytes":                      uint64(stat.RxBytes),
 | 
								"receive_bytes":                      uint64(stat.RxBytes),
 | 
				
			||||||
			"transmit_bytes":     uint64(stat.TxBytes),
 | 
					 | 
				
			||||||
			"receive_errors":     uint64(stat.RxErrors),
 | 
					 | 
				
			||||||
			"transmit_errors":    uint64(stat.TxErrors),
 | 
					 | 
				
			||||||
			"receive_dropped":                    uint64(stat.RxPacketsDropped),
 | 
								"receive_dropped":                    uint64(stat.RxPacketsDropped),
 | 
				
			||||||
			"transmit_dropped":   uint64(stat.TxPacketsDropped),
 | 
								"receive_errors":                     uint64(stat.RxErrors),
 | 
				
			||||||
			"receive_multicast":                  uint64(stat.RxMulticastPackets),
 | 
								"receive_multicast":                  uint64(stat.RxMulticastPackets),
 | 
				
			||||||
 | 
								"receive_packets":                    uint64(stat.RxPackets),
 | 
				
			||||||
 | 
								"receive_collision_errors":           uint64(stat.RxCollisionErrors),
 | 
				
			||||||
 | 
								"transmit_bytes":                     uint64(stat.TxBytes),
 | 
				
			||||||
 | 
								"transmit_dropped":                   uint64(stat.TxPacketsDropped),
 | 
				
			||||||
 | 
								"transmit_errors":                    uint64(stat.TxErrors),
 | 
				
			||||||
			"transmit_multicast":                 uint64(stat.TxMulticastPackets),
 | 
								"transmit_multicast":                 uint64(stat.TxMulticastPackets),
 | 
				
			||||||
 | 
								"transmit_packets":                   uint64(stat.TxPackets),
 | 
				
			||||||
 | 
								"transmit_queue_overflow":            uint64(stat.TxQueueOverflow),
 | 
				
			||||||
 | 
								"transmit_collision_single_errors":   uint64(stat.TxSingleCollisionCount),
 | 
				
			||||||
 | 
								"transmit_collision_multiple_errors": uint64(stat.TxMultipleCollisionCount),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log/slog"
 | 
						"log/slog"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/sys/unix"
 | 
						"golang.org/x/sys/unix"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -71,51 +72,107 @@ func getIfaceData(index int) (*ifMsghdr2, error) {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = binary.Read(bytes.NewReader(rawData), binary.LittleEndian, &data)
 | 
						err = binary.Read(bytes.NewReader(rawData), binary.LittleEndian, &data)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
		return &data, err
 | 
							return &data, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ifMsghdr2 struct {
 | 
						/*
 | 
				
			||||||
	Msglen    uint16
 | 
							As of macOS Ventura 13.2.1, there’s a kernel bug which truncates traffic values at the 4GiB mark.
 | 
				
			||||||
	Version   uint8
 | 
							This is a workaround to fetch the interface traffic metrics using a sysctl call.
 | 
				
			||||||
	Type      uint8
 | 
							Apple wants to prevent fingerprinting by 3rdparty apps and might fix this bug in future which would break this implementation.
 | 
				
			||||||
	Addrs     int32
 | 
						*/
 | 
				
			||||||
	Flags     int32
 | 
						mib := []int32{
 | 
				
			||||||
	Index     uint16
 | 
							unix.CTL_NET,
 | 
				
			||||||
	_         [2]byte
 | 
							unix.AF_LINK,
 | 
				
			||||||
	SndLen    int32
 | 
							0, // NETLINK_GENERIC: functions not specific to a type of iface
 | 
				
			||||||
	SndMaxlen int32
 | 
							2, //IFMIB_IFDATA: per-interface data table
 | 
				
			||||||
	SndDrops  int32
 | 
							int32(index),
 | 
				
			||||||
	Timer     int32
 | 
							1, // IFDATA_GENERAL: generic stats for all kinds of ifaces
 | 
				
			||||||
	Data      ifData64
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// https://github.com/apple/darwin-xnu/blob/main/bsd/net/if_var.h#L199-L231
 | 
						var mibData ifMibData
 | 
				
			||||||
 | 
						size := unsafe.Sizeof(mibData)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, _, errno := unix.Syscall6(
 | 
				
			||||||
 | 
							unix.SYS___SYSCTL,
 | 
				
			||||||
 | 
							uintptr(unsafe.Pointer(&mib[0])),
 | 
				
			||||||
 | 
							uintptr(len(mib)),
 | 
				
			||||||
 | 
							uintptr(unsafe.Pointer(&mibData)),
 | 
				
			||||||
 | 
							uintptr(unsafe.Pointer(&size)),
 | 
				
			||||||
 | 
							uintptr(unsafe.Pointer(nil)),
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
						); errno != 0 {
 | 
				
			||||||
 | 
							return &data, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var ifdata ifData64
 | 
				
			||||||
 | 
						err = binary.Read(bytes.NewReader(mibData.Data[:]), binary.LittleEndian, &ifdata)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &data, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data.Data.Ibytes = ifdata.Ibytes
 | 
				
			||||||
 | 
						data.Data.Obytes = ifdata.Obytes
 | 
				
			||||||
 | 
						return &data, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://github.com/apple-oss-distributions/xnu/blob/main/bsd/net/if.h#L220-L232
 | 
				
			||||||
 | 
					type ifMsghdr2 struct {
 | 
				
			||||||
 | 
						Msglen    uint16   // to skip over non-understood messages
 | 
				
			||||||
 | 
						Version   uint8    // future binary compatabilit
 | 
				
			||||||
 | 
						Type      uint8    // message type
 | 
				
			||||||
 | 
						Addrs     int32    // like rtm_addrs
 | 
				
			||||||
 | 
						Flags     int32    // value of if_flags
 | 
				
			||||||
 | 
						Index     uint16   // index for associated ifp
 | 
				
			||||||
 | 
						_         [2]byte  // padding for alignment
 | 
				
			||||||
 | 
						SndLen    int32    // instantaneous length of send queue
 | 
				
			||||||
 | 
						SndMaxlen int32    // maximum length of send queue
 | 
				
			||||||
 | 
						SndDrops  int32    // number of drops in send queue
 | 
				
			||||||
 | 
						Timer     int32    // time until if_watchdog called
 | 
				
			||||||
 | 
						Data      ifData64 // statistics and other data
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://github.com/apple-oss-distributions/xnu/blob/main/bsd/net/if_var.h#L207-L235
 | 
				
			||||||
type ifData64 struct {
 | 
					type ifData64 struct {
 | 
				
			||||||
	Type       uint8
 | 
						Type      uint8  // ethernet, tokenring, etc
 | 
				
			||||||
	Typelen    uint8
 | 
						Typelen   uint8  // Length of frame type id
 | 
				
			||||||
	Physical   uint8
 | 
						Physical  uint8  // e.g., AUI, Thinnet, 10base-T, etc
 | 
				
			||||||
	Addrlen    uint8
 | 
						Addrlen   uint8  // media address length
 | 
				
			||||||
	Hdrlen     uint8
 | 
						Hdrlen    uint8  // media header length
 | 
				
			||||||
	Recvquota  uint8
 | 
						Recvquota uint8  // polling quota for receive intrs
 | 
				
			||||||
	Xmitquota  uint8
 | 
						Xmitquota uint8  // polling quota for xmit intrs
 | 
				
			||||||
	Unused1    uint8
 | 
						Unused1   uint8  // for future use
 | 
				
			||||||
	Mtu        uint32
 | 
						Mtu       uint32 // maximum transmission unit
 | 
				
			||||||
	Metric     uint32
 | 
						Metric    uint32 // routing metric (external only)
 | 
				
			||||||
	Baudrate   uint64
 | 
						Baudrate  uint64 // linespeed
 | 
				
			||||||
	Ipackets   uint64
 | 
					
 | 
				
			||||||
	Ierrors    uint64
 | 
						// volatile statistics
 | 
				
			||||||
	Opackets   uint64
 | 
						Ipackets   uint64         // packets received on interface
 | 
				
			||||||
	Oerrors    uint64
 | 
						Ierrors    uint64         // input errors on interface
 | 
				
			||||||
	Collisions uint64
 | 
						Opackets   uint64         // packets sent on interface
 | 
				
			||||||
	Ibytes     uint64
 | 
						Oerrors    uint64         // output errors on interface
 | 
				
			||||||
	Obytes     uint64
 | 
						Collisions uint64         // collisions on csma interfaces
 | 
				
			||||||
	Imcasts    uint64
 | 
						Ibytes     uint64         // total number of octets received
 | 
				
			||||||
	Omcasts    uint64
 | 
						Obytes     uint64         // total number of octets sent
 | 
				
			||||||
	Iqdrops    uint64
 | 
						Imcasts    uint64         // packets received via multicast
 | 
				
			||||||
	Noproto    uint64
 | 
						Omcasts    uint64         // packets sent via multicast
 | 
				
			||||||
	Recvtiming uint32
 | 
						Iqdrops    uint64         // dropped on input, this interface
 | 
				
			||||||
	Xmittiming uint32
 | 
						Noproto    uint64         // destined for unsupported protocol
 | 
				
			||||||
	Lastchange unix.Timeval32
 | 
						Recvtiming uint32         // usec spent receiving when timing
 | 
				
			||||||
 | 
						Xmittiming uint32         // usec spent xmitting when timing
 | 
				
			||||||
 | 
						Lastchange unix.Timeval32 // time of last administrative change
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://github.com/apple-oss-distributions/xnu/blob/main/bsd/net/if_mib.h#L65-L74
 | 
				
			||||||
 | 
					type ifMibData struct {
 | 
				
			||||||
 | 
						Name          [16]byte  // name of interface
 | 
				
			||||||
 | 
						PCount        uint32    // number of promiscuous listeners
 | 
				
			||||||
 | 
						Flags         uint32    // interface flags
 | 
				
			||||||
 | 
						SendLength    uint32    // instantaneous length of send queue
 | 
				
			||||||
 | 
						MaxSendLength uint32    // maximum length of send queue
 | 
				
			||||||
 | 
						SendDrops     uint32    // number of drops in send queue
 | 
				
			||||||
 | 
						_             [4]uint32 // for future expansion
 | 
				
			||||||
 | 
						Data          [128]byte // generic information and statistics
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getNetDevLabels() (map[string]map[string]string, error) {
 | 
					func getNetDevLabels() (map[string]map[string]string, error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										86
									
								
								collector/netinterface_aix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								collector/netinterface_aix.go
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,86 @@
 | 
				
			||||||
 | 
					// Copyright 2025 The Prometheus Authors
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:build !nonetinterface
 | 
				
			||||||
 | 
					// +build !nonetinterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package collector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"log/slog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/power-devops/perfstat"
 | 
				
			||||||
 | 
						"github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type netinterfaceCollector struct {
 | 
				
			||||||
 | 
						logger     *slog.Logger
 | 
				
			||||||
 | 
						collisions *prometheus.Desc
 | 
				
			||||||
 | 
						ibytes     *prometheus.Desc
 | 
				
			||||||
 | 
						ipackets   *prometheus.Desc
 | 
				
			||||||
 | 
						obytes     *prometheus.Desc
 | 
				
			||||||
 | 
						opackets   *prometheus.Desc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						netinterfaceSubsystem = "netinterface"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						registerCollector("netinterface", defaultEnabled, NewNetinterfaceCollector)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewNetinterfaceCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
 | 
						labels := []string{"interface"}
 | 
				
			||||||
 | 
						return &netinterfaceCollector{
 | 
				
			||||||
 | 
							logger: logger,
 | 
				
			||||||
 | 
							collisions: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, netinterfaceSubsystem, "collisions_total"),
 | 
				
			||||||
 | 
								"Total number of CSMA collisions on the interface.", labels, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							ibytes: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, netinterfaceSubsystem, "receive_bytes_total"),
 | 
				
			||||||
 | 
								"Total number of bytes received on the interface.", labels, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							ipackets: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, netinterfaceSubsystem, "receive_packets_total"),
 | 
				
			||||||
 | 
								"Total number of packets received on the interface.", labels, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							obytes: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, netinterfaceSubsystem, "transmit_bytes_total"),
 | 
				
			||||||
 | 
								"Total number of bytes transmitted on the interface.", labels, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							opackets: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, netinterfaceSubsystem, "transmit_packets_total"),
 | 
				
			||||||
 | 
								"Total number of packets transmitted on the interface.", labels, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *netinterfaceCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
 | 
						stats, err := perfstat.NetIfaceStat()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, stat := range stats {
 | 
				
			||||||
 | 
							iface := stat.Name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(c.collisions, prometheus.CounterValue, float64(stat.Collisions), iface)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(c.ibytes, prometheus.CounterValue, float64(stat.IBytes), iface)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(c.ipackets, prometheus.CounterValue, float64(stat.IPackets), iface)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(c.obytes, prometheus.CounterValue, float64(stat.OBytes), iface)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(c.opackets, prometheus.CounterValue, float64(stat.OPackets), iface)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										118
									
								
								collector/partition_aix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								collector/partition_aix.go
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,118 @@
 | 
				
			||||||
 | 
					// Copyright 2025 The Prometheus Authors
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:build !nopartition
 | 
				
			||||||
 | 
					// +build !nopartition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package collector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"log/slog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/power-devops/perfstat"
 | 
				
			||||||
 | 
						"github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type partitionCollector struct {
 | 
				
			||||||
 | 
						logger           *slog.Logger
 | 
				
			||||||
 | 
						entitledCapacity *prometheus.Desc
 | 
				
			||||||
 | 
						memoryMax        *prometheus.Desc
 | 
				
			||||||
 | 
						memoryOnline     *prometheus.Desc
 | 
				
			||||||
 | 
						cpuOnline        *prometheus.Desc
 | 
				
			||||||
 | 
						cpuSys           *prometheus.Desc
 | 
				
			||||||
 | 
						cpuPool          *prometheus.Desc
 | 
				
			||||||
 | 
						powerSaveMode    *prometheus.Desc
 | 
				
			||||||
 | 
						smtThreads       *prometheus.Desc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						partitionCollectorSubsystem = "partition"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						registerCollector("partition", defaultEnabled, NewPartitionCollector)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPartitionCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
 | 
						return &partitionCollector{
 | 
				
			||||||
 | 
							logger: logger,
 | 
				
			||||||
 | 
							entitledCapacity: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "entitled_capacity"),
 | 
				
			||||||
 | 
								"Entitled processor capacity of the partition in CPU units (e.g. 1.0 = one core).",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							memoryMax: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "memory_max"),
 | 
				
			||||||
 | 
								"Maximum memory of the partition in bytes.",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							memoryOnline: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "memory_online"),
 | 
				
			||||||
 | 
								"Online memory of the partition in bytes.",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							cpuOnline: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "cpus_online"),
 | 
				
			||||||
 | 
								"Number of online CPUs in the partition.",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							cpuSys: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "cpus_sys"),
 | 
				
			||||||
 | 
								"Number of physical CPUs in the system.",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							cpuPool: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "cpus_pool"),
 | 
				
			||||||
 | 
								"Number of physical CPUs in the pool.",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							powerSaveMode: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "power_save_mode"),
 | 
				
			||||||
 | 
								"Power save mode of the partition (1 for enabled, 0 for disabled).",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							smtThreads: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, partitionCollectorSubsystem, "smt_threads"),
 | 
				
			||||||
 | 
								"Number of SMT threads per core.",
 | 
				
			||||||
 | 
								nil, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *partitionCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
 | 
						stats, err := perfstat.PartitionStat()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						powerSaveMode := 0.0
 | 
				
			||||||
 | 
						if stats.Conf.PowerSave {
 | 
				
			||||||
 | 
							powerSaveMode = 1.0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.entitledCapacity, prometheus.GaugeValue, float64(stats.EntCapacity)/100.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.memoryMax, prometheus.GaugeValue, float64(stats.Mem.Max)*1024*1024)
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.memoryOnline, prometheus.GaugeValue, float64(stats.Mem.Online)*1024*1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.cpuOnline, prometheus.GaugeValue, float64(stats.VCpus.Online))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.cpuSys, prometheus.GaugeValue, float64(stats.NumProcessors.Online))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.cpuPool, prometheus.GaugeValue, float64(stats.ActiveCpusInPool))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.powerSaveMode, prometheus.GaugeValue, powerSaveMode)
 | 
				
			||||||
 | 
						ch <- prometheus.MustNewConstMetric(c.smtThreads, prometheus.GaugeValue, float64(stats.SmtThreads))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ func canTestPerf(t *testing.T) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Skip("Procfs not mounted, skipping perf tests")
 | 
							t.Skip("Procfs not mounted, skipping perf tests")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	paranoidStr := strings.Replace(string(paranoidBytes), "\n", "", -1)
 | 
						paranoidStr := strings.ReplaceAll(string(paranoidBytes), "\n", "")
 | 
				
			||||||
	paranoid, err := strconv.Atoi(paranoidStr)
 | 
						paranoid, err := strconv.Atoi(paranoidStr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("Expected perf_event_paranoid to be an int, got: %s", paranoidStr)
 | 
							t.Fatalf("Expected perf_event_paranoid to be an int, got: %s", paranoidStr)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ func (c *processCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pidM, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
 | 
						pidM, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return fmt.Errorf("unable to retrieve limit number of maximum pids alloved: %w", err)
 | 
							return fmt.Errorf("unable to retrieve limit number of maximum pids allowed: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ch <- prometheus.MustNewConstMetric(c.pidUsed, prometheus.GaugeValue, float64(pids))
 | 
						ch <- prometheus.MustNewConstMetric(c.pidUsed, prometheus.GaugeValue, float64(pids))
 | 
				
			||||||
	ch <- prometheus.MustNewConstMetric(c.pidMax, prometheus.GaugeValue, float64(pidM))
 | 
						ch <- prometheus.MustNewConstMetric(c.pidMax, prometheus.GaugeValue, float64(pidM))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ func TestReadProcessStatus(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	maxPid, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
 | 
						maxPid, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("Unable to retrieve limit number of maximum pids alloved %v\n", err)
 | 
							t.Fatalf("Unable to retrieve limit number of maximum pids allowed %v\n", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if uint64(pids) > maxPid || pids == 0 {
 | 
						if uint64(pids) > maxPid || pids == 0 {
 | 
				
			||||||
		t.Fatalf("Total running pids cannot be greater than %d or equals to 0", maxPid)
 | 
							t.Fatalf("Total running pids cannot be greater than %d or equals to 0", maxPid)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,11 +122,12 @@ func TestSystemdSummary(t *testing.T) {
 | 
				
			||||||
	summary := summarizeUnits(fixtures[0])
 | 
						summary := summarizeUnits(fixtures[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, state := range unitStatesName {
 | 
						for _, state := range unitStatesName {
 | 
				
			||||||
		if state == "inactive" {
 | 
							switch state {
 | 
				
			||||||
 | 
							case "inactive":
 | 
				
			||||||
			testSummaryHelper(t, state, summary[state], 3.0)
 | 
								testSummaryHelper(t, state, summary[state], 3.0)
 | 
				
			||||||
		} else if state == "active" {
 | 
							case "active":
 | 
				
			||||||
			testSummaryHelper(t, state, summary[state], 1.0)
 | 
								testSummaryHelper(t, state, summary[state], 1.0)
 | 
				
			||||||
		} else {
 | 
							default:
 | 
				
			||||||
			testSummaryHelper(t, state, summary[state], 0.0)
 | 
								testSummaryHelper(t, state, summary[state], 0.0)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -435,5 +435,5 @@ type zfsSysctl string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s zfsSysctl) metricName() string {
 | 
					func (s zfsSysctl) metricName() string {
 | 
				
			||||||
	parts := strings.Split(string(s), ".")
 | 
						parts := strings.Split(string(s), ".")
 | 
				
			||||||
	return strings.Replace(parts[len(parts)-1], "-", "_", -1)
 | 
						return strings.ReplaceAll(parts[len(parts)-1], "-", "_")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										30
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								go.mod
									
									
									
									
									
								
							| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
module github.com/prometheus/node_exporter
 | 
					module github.com/prometheus/node_exporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.23.0
 | 
					go 1.24.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/alecthomas/kingpin/v2 v2.4.0
 | 
						github.com/alecthomas/kingpin/v2 v2.4.0
 | 
				
			||||||
| 
						 | 
					@ -13,23 +13,23 @@ require (
 | 
				
			||||||
	github.com/hodgesds/perf-utils v0.7.0
 | 
						github.com/hodgesds/perf-utils v0.7.0
 | 
				
			||||||
	github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973
 | 
						github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973
 | 
				
			||||||
	github.com/josharian/native v1.1.0
 | 
						github.com/josharian/native v1.1.0
 | 
				
			||||||
	github.com/jsimonetti/rtnetlink/v2 v2.0.2
 | 
						github.com/jsimonetti/rtnetlink/v2 v2.0.5
 | 
				
			||||||
	github.com/lufia/iostat v1.2.1
 | 
						github.com/lufia/iostat v1.2.1
 | 
				
			||||||
	github.com/mattn/go-xmlrpc v0.0.3
 | 
						github.com/mattn/go-xmlrpc v0.0.3
 | 
				
			||||||
	github.com/mdlayher/ethtool v0.2.0
 | 
						github.com/mdlayher/ethtool v0.4.0
 | 
				
			||||||
	github.com/mdlayher/netlink v1.7.2
 | 
						github.com/mdlayher/netlink v1.7.2
 | 
				
			||||||
	github.com/mdlayher/wifi v0.3.1
 | 
						github.com/mdlayher/wifi v0.5.0
 | 
				
			||||||
	github.com/opencontainers/selinux v1.11.1
 | 
						github.com/opencontainers/selinux v1.11.1
 | 
				
			||||||
	github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55
 | 
						github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55
 | 
				
			||||||
	github.com/prometheus-community/go-runit v0.1.0
 | 
						github.com/prometheus-community/go-runit v0.1.0
 | 
				
			||||||
	github.com/prometheus/client_golang v1.21.1
 | 
						github.com/prometheus/client_golang v1.21.1
 | 
				
			||||||
	github.com/prometheus/client_model v0.6.1
 | 
						github.com/prometheus/client_model v0.6.2
 | 
				
			||||||
	github.com/prometheus/common v0.62.0
 | 
						github.com/prometheus/common v0.64.0
 | 
				
			||||||
	github.com/prometheus/exporter-toolkit v0.14.0
 | 
						github.com/prometheus/exporter-toolkit v0.14.0
 | 
				
			||||||
	github.com/prometheus/procfs v0.16.0
 | 
						github.com/prometheus/procfs v0.17.0
 | 
				
			||||||
	github.com/safchain/ethtool v0.5.10
 | 
						github.com/safchain/ethtool v0.6.1
 | 
				
			||||||
	golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
 | 
						golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
 | 
				
			||||||
	golang.org/x/sys v0.30.0
 | 
						golang.org/x/sys v0.33.0
 | 
				
			||||||
	howett.net/plist v1.0.1
 | 
						howett.net/plist v1.0.1
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,11 +51,11 @@ require (
 | 
				
			||||||
	github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
 | 
						github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
 | 
				
			||||||
	go.uber.org/atomic v1.7.0 // indirect
 | 
						go.uber.org/atomic v1.7.0 // indirect
 | 
				
			||||||
	go.uber.org/multierr v1.6.0 // indirect
 | 
						go.uber.org/multierr v1.6.0 // indirect
 | 
				
			||||||
	golang.org/x/crypto v0.35.0 // indirect
 | 
						golang.org/x/crypto v0.38.0 // indirect
 | 
				
			||||||
	golang.org/x/net v0.36.0 // indirect
 | 
						golang.org/x/net v0.40.0 // indirect
 | 
				
			||||||
	golang.org/x/oauth2 v0.24.0 // indirect
 | 
						golang.org/x/oauth2 v0.30.0 // indirect
 | 
				
			||||||
	golang.org/x/sync v0.11.0 // indirect
 | 
						golang.org/x/sync v0.15.0 // indirect
 | 
				
			||||||
	golang.org/x/text v0.22.0 // indirect
 | 
						golang.org/x/text v0.25.0 // indirect
 | 
				
			||||||
	google.golang.org/protobuf v1.36.1 // indirect
 | 
						google.golang.org/protobuf v1.36.6 // indirect
 | 
				
			||||||
	gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
						gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								go.sum
									
									
									
									
									
								
							| 
						 | 
					@ -8,8 +8,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 | 
				
			||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 | 
					github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 | 
				
			||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 | 
					github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 | 
				
			||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
					github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
				
			||||||
github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
 | 
					github.com/cilium/ebpf v0.19.0 h1:Ro/rE64RmFBeA9FGjcTc+KmCeY6jXmryu6FfnzPRIao=
 | 
				
			||||||
github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
 | 
					github.com/cilium/ebpf v0.19.0/go.mod h1:fLCgMo3l8tZmAdM3B2XqdFzXBpwkcSTroaVqN08OWVY=
 | 
				
			||||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
 | 
					github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
 | 
				
			||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 | 
					github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
| 
						 | 
					@ -37,8 +37,8 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
 | 
				
			||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
 | 
					github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
 | 
				
			||||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
 | 
					github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
 | 
				
			||||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 | 
					github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 | 
				
			||||||
github.com/jsimonetti/rtnetlink/v2 v2.0.2 h1:ZKlbCujrIpp4/u3V2Ka0oxlf4BCkt6ojkvpy3nZoCBY=
 | 
					github.com/jsimonetti/rtnetlink/v2 v2.0.5 h1:l5S9iedrSW4thUfgiU+Hzsnk1cOR0upGD5ttt6mirHw=
 | 
				
			||||||
github.com/jsimonetti/rtnetlink/v2 v2.0.2/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
 | 
					github.com/jsimonetti/rtnetlink/v2 v2.0.5/go.mod h1:9yTlq3Ojr1rbmh/Y5L30/KIojpFhTRph2xKeZ+y+Pic=
 | 
				
			||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
 | 
					github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
 | 
				
			||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
 | 
					github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
 | 
				
			||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 | 
					github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 | 
				
			||||||
| 
						 | 
					@ -51,8 +51,8 @@ github.com/lufia/iostat v1.2.1 h1:tnCdZBIglgxD47RyD55kfWQcJMGzO+1QBziSQfesf2k=
 | 
				
			||||||
github.com/lufia/iostat v1.2.1/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg=
 | 
					github.com/lufia/iostat v1.2.1/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg=
 | 
				
			||||||
github.com/mattn/go-xmlrpc v0.0.3 h1:Y6WEMLEsqs3RviBrAa1/7qmbGB7DVD3brZIbqMbQdGY=
 | 
					github.com/mattn/go-xmlrpc v0.0.3 h1:Y6WEMLEsqs3RviBrAa1/7qmbGB7DVD3brZIbqMbQdGY=
 | 
				
			||||||
github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA=
 | 
					github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA=
 | 
				
			||||||
github.com/mdlayher/ethtool v0.2.0 h1:akcA4WZVWozzirPASeMq8qgLkxpF3ykftVXwnrMKrhY=
 | 
					github.com/mdlayher/ethtool v0.4.0 h1:jjMGNSQfqauwFCtSzcqpa57R0AJdxKdQgbQ9mAOtM4Q=
 | 
				
			||||||
github.com/mdlayher/ethtool v0.2.0/go.mod h1:W0pIBrNPK1TslIN4Z9wt1EVbay66Kbvek2z2f29VBfw=
 | 
					github.com/mdlayher/ethtool v0.4.0/go.mod h1:GrljOneAFOTPGazYlf8qpxvYLdu4mo3pdJqXWLZ2Re8=
 | 
				
			||||||
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
 | 
					github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
 | 
				
			||||||
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
 | 
					github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
 | 
				
			||||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
 | 
					github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
 | 
				
			||||||
| 
						 | 
					@ -61,8 +61,8 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
 | 
				
			||||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
 | 
					github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
 | 
				
			||||||
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
 | 
					github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
 | 
				
			||||||
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
 | 
					github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
 | 
				
			||||||
github.com/mdlayher/wifi v0.3.1 h1:bZDuMI1f7z5BtUUO3NgHRdR/R88YtywIe6dsEFI0Txs=
 | 
					github.com/mdlayher/wifi v0.5.0 h1:TGZIcrhL6h3710amshpEJnMzLs74MrZOF+8qbm8Gx/I=
 | 
				
			||||||
github.com/mdlayher/wifi v0.3.1/go.mod h1:ODQaObvsglghTuNhezD9grkTB4shVNc28aJfTXmvSi8=
 | 
					github.com/mdlayher/wifi v0.5.0/go.mod h1:yfQs+5zr1eOIfdsWDcZonWdznnt/Iiz0/4772cfZuHk=
 | 
				
			||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 | 
					github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 | 
				
			||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 | 
					github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 | 
				
			||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
 | 
					github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
 | 
				
			||||||
| 
						 | 
					@ -77,18 +77,18 @@ github.com/prometheus-community/go-runit v0.1.0 h1:uTWEj/Fn2RoLdfg/etSqwzgYNOYPr
 | 
				
			||||||
github.com/prometheus-community/go-runit v0.1.0/go.mod h1:AvJ9Jo3gAFu2lbM4+qfjdpq30FfiLDJZKbQ015u08IQ=
 | 
					github.com/prometheus-community/go-runit v0.1.0/go.mod h1:AvJ9Jo3gAFu2lbM4+qfjdpq30FfiLDJZKbQ015u08IQ=
 | 
				
			||||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
 | 
					github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
 | 
				
			||||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
 | 
					github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
 | 
				
			||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
 | 
					github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
 | 
				
			||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
 | 
					github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
 | 
				
			||||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
 | 
					github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
 | 
				
			||||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
 | 
					github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
 | 
				
			||||||
github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
 | 
					github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
 | 
				
			||||||
github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
 | 
					github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
 | 
				
			||||||
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM=
 | 
					github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
 | 
				
			||||||
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
 | 
					github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
 | 
					github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 | 
					github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 | 
				
			||||||
github.com/safchain/ethtool v0.5.10 h1:Im294gZtuf4pSGJRAOGKaASNi3wMeFaGaWuSaomedpc=
 | 
					github.com/safchain/ethtool v0.6.1 h1:mhRnXE1H8fV8TTXh/HdqE4tXtb57r//BQh5pPYMuM5k=
 | 
				
			||||||
github.com/safchain/ethtool v0.5.10/go.mod h1:w9jh2Lx7YBR4UwzLkzCmWl85UY0W2uZdd7/DckVE5+c=
 | 
					github.com/safchain/ethtool v0.6.1/go.mod h1:JzoNbG8xeg/BeVeVoMCtCb3UPWoppZZbFpA+1WFh+M0=
 | 
				
			||||||
github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973 h1:GfSdC6wKfTGcgCS7BtzF5694Amne1pGCSTY252WhlEY=
 | 
					github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973 h1:GfSdC6wKfTGcgCS7BtzF5694Amne1pGCSTY252WhlEY=
 | 
				
			||||||
github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8=
 | 
					github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8=
 | 
				
			||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
					github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
				
			||||||
| 
						 | 
					@ -102,25 +102,24 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 | 
				
			||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
					go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
				
			||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
 | 
					go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
 | 
				
			||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 | 
					go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 | 
				
			||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
 | 
					golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
 | 
				
			||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
 | 
					golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
 | 
				
			||||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
 | 
					golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
 | 
				
			||||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
 | 
					golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
 | 
				
			||||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
 | 
					golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
 | 
				
			||||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
 | 
					golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
 | 
				
			||||||
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
 | 
					golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
 | 
				
			||||||
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 | 
					golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
 | 
				
			||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
 | 
					golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
 | 
				
			||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
					golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
					golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
 | 
				
			||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
 | 
					golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
				
			||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
					golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
 | 
				
			||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
 | 
					golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
 | 
				
			||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
 | 
					google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
 | 
				
			||||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
 | 
					google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 | 
				
			||||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 | 
					 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
					gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
					gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,7 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		h.logger.Warn("Couldn't create filtered metrics handler:", "err", err)
 | 
							h.logger.Warn("Couldn't create filtered metrics handler:", "err", err)
 | 
				
			||||||
		w.WriteHeader(http.StatusBadRequest)
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
		w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err)))
 | 
							fmt.Fprintf(w, "Couldn't create filtered metrics handler: %s", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	filteredHandler.ServeHTTP(w, r)
 | 
						filteredHandler.ServeHTTP(w, r)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue