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 {
|
||||
// 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]
|
||||
c.updateBtrfsStats(ch, s, ioctlStats)
|
||||
}
|
||||
|
|
|
@ -30,22 +30,50 @@ import (
|
|||
"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 {
|
||||
cpu typedDesc
|
||||
logger *slog.Logger
|
||||
tickPerSecond int64
|
||||
cpu typedDesc
|
||||
cpuPhysical typedDesc
|
||||
cpuRunQueue typedDesc
|
||||
cpuFlags typedDesc
|
||||
cpuContextSwitch typedDesc
|
||||
|
||||
logger *slog.Logger
|
||||
tickPerSecond float64
|
||||
purrTicksPerSecond float64
|
||||
}
|
||||
|
||||
func init() {
|
||||
registerCollector("cpu", defaultEnabled, NewCpuCollector)
|
||||
}
|
||||
|
||||
func tickPerSecond() (int64, error) {
|
||||
func tickPerSecond() (float64, error) {
|
||||
ticks, err := C.sysconf(C._SC_CLK_TCK)
|
||||
if ticks == -1 || err != nil {
|
||||
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) {
|
||||
|
@ -53,10 +81,22 @@ func NewCpuCollector(logger *slog.Logger) (Collector, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pconfig, err := perfstat.PartitionStat()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cpuCollector{
|
||||
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
|
||||
logger: logger,
|
||||
tickPerSecond: ticks,
|
||||
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,
|
||||
tickPerSecond: ticks,
|
||||
purrTicksPerSecond: float64(pconfig.ProcessorMhz * 1e6),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -67,10 +107,26 @@ func (c *cpuCollector) Update(ch chan<- prometheus.Metric) error {
|
|||
}
|
||||
|
||||
for n, stat := range stats {
|
||||
ch <- c.cpu.mustNewConstMetric(float64(stat.User/c.tickPerSecond), strconv.Itoa(n), "user")
|
||||
ch <- c.cpu.mustNewConstMetric(float64(stat.Sys/c.tickPerSecond), strconv.Itoa(n), "system")
|
||||
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")
|
||||
// LPAR metrics
|
||||
ch <- c.cpu.mustNewConstMetric(float64(stat.User)/c.tickPerSecond, strconv.Itoa(n), "user")
|
||||
ch <- c.cpu.mustNewConstMetric(float64(stat.Sys)/c.tickPerSecond, strconv.Itoa(n), "system")
|
||||
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
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ func NewCPUCollector(logger *slog.Logger) (Collector, error) {
|
|||
isolcpus, err := sfs.IsolatedCPUs()
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ func getCPUTemperatures() (map[int]float64, error) {
|
|||
}
|
||||
|
||||
keys := sortFilterSysmonProperties(props, "coretemp")
|
||||
for idx, _ := range keys {
|
||||
for idx := range keys {
|
||||
convertTemperatures(props[keys[idx]], res)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
cpuVulerabilitiesCollector = "cpu_vulnerabilities"
|
||||
cpuVulnerabilitiesCollectorSubsystem = "cpu_vulnerabilities"
|
||||
)
|
||||
|
||||
var (
|
||||
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",
|
||||
[]string{"codename", "state", "mitigation"},
|
||||
nil,
|
||||
|
@ -37,7 +37,7 @@ var (
|
|||
type cpuVulnerabilitiesCollector struct{}
|
||||
|
||||
func init() {
|
||||
registerCollector(cpuVulerabilitiesCollector, defaultDisabled, NewVulnerabilitySysfsCollector)
|
||||
registerCollector(cpuVulnerabilitiesCollectorSubsystem, defaultDisabled, NewVulnerabilitySysfsCollector)
|
||||
}
|
||||
|
||||
func NewVulnerabilitySysfsCollector(logger *slog.Logger) (Collector, error) {
|
||||
|
|
|
@ -30,11 +30,19 @@ type diskstatsCollector struct {
|
|||
rbytes typedDesc
|
||||
wbytes typedDesc
|
||||
time typedDesc
|
||||
bsize typedDesc
|
||||
qdepth typedDesc
|
||||
|
||||
rserv typedDesc
|
||||
wserv typedDesc
|
||||
|
||||
xfers typedDesc
|
||||
xrate typedDesc
|
||||
|
||||
deviceFilter deviceFilter
|
||||
logger *slog.Logger
|
||||
|
||||
tickPerSecond int64
|
||||
tickPerSecond float64
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -57,6 +65,54 @@ func NewDiskstatsCollector(logger *slog.Logger) (Collector, error) {
|
|||
wbytes: typedDesc{writtenBytesDesc, 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,
|
||||
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.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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
metricFQNames := make(map[string]string)
|
||||
renamedStats := make(map[string]uint64, len(stats))
|
||||
for metric := range stats {
|
||||
metricName := SanitizeMetricName(metric)
|
||||
if !c.metricsPattern.MatchString(metricName) {
|
||||
|
@ -467,6 +468,8 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
|
|||
metricFQNames[metricFQName] = ""
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
val := stats[metric]
|
||||
val := renamedStats[metric]
|
||||
|
||||
// Check to see if this metric exists; if not then create it and store it in c.entries.
|
||||
entry := c.entryWithCreate(metric, metricFQName)
|
||||
|
|
|
@ -212,16 +212,18 @@ func (e *EthtoolFixture) LinkInfo(intf string) (ethtool.EthtoolCmd, error) {
|
|||
|
||||
items := strings.Split(line, ": ")
|
||||
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)
|
||||
} else if items[1] == "Receive-only" {
|
||||
case "Receive-only":
|
||||
res.Supported |= (1 << unix.ETHTOOL_LINK_MODE_Asym_Pause_BIT)
|
||||
}
|
||||
}
|
||||
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)
|
||||
} else if items[1] == "Receive-only" {
|
||||
case "Receive-only":
|
||||
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) {
|
||||
testcases := map[string]string{
|
||||
"port.rx_errors": "node_ethtool_port_received_errors",
|
||||
"rx_errors": "node_ethtool_received_errors",
|
||||
"Queue[0] AllocFails": "node_ethtool_queue_0_allocfails",
|
||||
"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.
|
||||
# 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
|
||||
# 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
|
||||
# TYPE node_ethtool_received_broadcast untyped
|
||||
node_ethtool_received_broadcast{device="eth0"} 5792
|
||||
|
|
|
@ -53,9 +53,9 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
|
|||
mountPoint: stat.MountPoint,
|
||||
fsType: fstype,
|
||||
},
|
||||
size: float64(stat.TotalBlocks / 512.0),
|
||||
free: float64(stat.FreeBlocks / 512.0),
|
||||
avail: float64(stat.FreeBlocks / 512.0), // AIX doesn't distinguish between free and available blocks.
|
||||
size: float64(stat.TotalBlocks * 512.0),
|
||||
free: float64(stat.FreeBlocks * 512.0),
|
||||
avail: float64(stat.FreeBlocks * 512.0), // AIX doesn't distinguish between free and available blocks.
|
||||
files: float64(stat.TotalInodes),
|
||||
filesFree: float64(stat.FreeInodes),
|
||||
ro: ro,
|
||||
|
|
|
@ -215,8 +215,8 @@ func parseFilesystemLabels(r io.Reader) ([]filesystemLabels, error) {
|
|||
|
||||
// Ensure we handle the translation of \040 and \011
|
||||
// as per fstab(5).
|
||||
parts[4] = strings.Replace(parts[4], "\\040", " ", -1)
|
||||
parts[4] = strings.Replace(parts[4], "\\011", "\t", -1)
|
||||
parts[4] = strings.ReplaceAll(parts[4], "\\040", " ")
|
||||
parts[4] = strings.ReplaceAll(parts[4], "\\011", "\t")
|
||||
|
||||
filesystems = append(filesystems, filesystemLabels{
|
||||
device: parts[m+3],
|
||||
|
|
|
@ -21,21 +21,25 @@ package collector
|
|||
#cgo LDFLAGS: -framework Foundation
|
||||
#import <Foundation/Foundation.h>
|
||||
Float64 purgeable(char *path) {
|
||||
CFNumberRef tmp;
|
||||
NSError *error = nil;
|
||||
NSString *str = [NSString stringWithUTF8String:path];
|
||||
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:str];
|
||||
NSDictionary *results = [fileURL resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey] error:&error];
|
||||
if (results) {
|
||||
if ((tmp = CFDictionaryGetValue((CFDictionaryRef)results, NSURLVolumeAvailableCapacityForImportantUsageKey)) == NULL) {
|
||||
return -1.0f;
|
||||
}
|
||||
Float64 value;
|
||||
if (CFNumberGetValue(tmp, kCFNumberFloat64Type, &value)) {
|
||||
return value;
|
||||
Float64 value = -1.0f;
|
||||
|
||||
@autoreleasepool {
|
||||
NSError *error = nil;
|
||||
NSString *str = [NSString stringWithUTF8String:path];
|
||||
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:str];
|
||||
|
||||
NSDictionary *results = [fileURL resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey] error:&error];
|
||||
if (results) {
|
||||
CFNumberRef tmp = CFDictionaryGetValue((CFDictionaryRef)results, NSURLVolumeAvailableCapacityForImportantUsageKey);
|
||||
if (tmp != NULL) {
|
||||
CFNumberGetValue(tmp, kCFNumberFloat64Type, &value);
|
||||
}
|
||||
}
|
||||
|
||||
[fileURL release];
|
||||
}
|
||||
return -1.0f;
|
||||
|
||||
return value;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
@ -88,6 +92,9 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
|
|||
ro = 1
|
||||
}
|
||||
|
||||
mountpointCString := C.CString(mountpoint)
|
||||
defer C.free(unsafe.Pointer(mountpointCString))
|
||||
|
||||
stats = append(stats, filesystemStats{
|
||||
labels: filesystemLabels{
|
||||
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),
|
||||
files: float64(mnt[i].f_files),
|
||||
filesFree: float64(mnt[i].f_ffree),
|
||||
purgeable: float64(C.purgeable(C.CString(mountpoint))),
|
||||
purgeable: float64(C.purgeable(mountpointCString)),
|
||||
ro: ro,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ NIC statistics:
|
|||
rx_packets: 1260062
|
||||
tx_errors: 0
|
||||
rx_errors: 0
|
||||
port.rx_dropped: 12028
|
||||
rx_missed: 401
|
||||
align_errors: 0
|
||||
tx_single_collisions: 0
|
||||
|
|
|
@ -2,4 +2,4 @@ net 70 70 69 45
|
|||
rpc 1218785755 374636 1218815394
|
||||
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
|
||||
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
|
||||
Mode: 755
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: sys/class/nvme/nvme0/cntlid
|
||||
Lines: 1
|
||||
1997
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: sys/class/nvme/nvme0/firmware_rev
|
||||
Lines: 1
|
||||
1B2QEXP7
|
||||
|
|
|
@ -40,8 +40,12 @@ func (c *meminfoCollector) getMemInfo() (map[string]float64, error) {
|
|||
}
|
||||
|
||||
return map[string]float64{
|
||||
"total_bytes": float64(stats.RealTotal * 4096),
|
||||
"free_bytes": float64(stats.RealFree * 4096),
|
||||
"available_bytes": float64(stats.RealAvailable * 4096),
|
||||
"total_bytes": float64(stats.RealTotal * 4096),
|
||||
"free_bytes": float64(stats.RealFree * 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
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func NewMeminfoCollector(logger *slog.Logger) (Collector, error) {
|
|||
func (c *meminfoCollector) getMemInfo() (map[string]float64, error) {
|
||||
meminfo, err := c.fs.Meminfo()
|
||||
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)
|
||||
|
|
|
@ -32,16 +32,20 @@ func getNetDevStats(filter *deviceFilter, logger *slog.Logger) (netDevStats, err
|
|||
|
||||
for _, stat := range stats {
|
||||
netDev[stat.Name] = map[string]uint64{
|
||||
"receive_packets": uint64(stat.RxPackets),
|
||||
"transmit_packets": uint64(stat.TxPackets),
|
||||
"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),
|
||||
"transmit_dropped": uint64(stat.TxPacketsDropped),
|
||||
"receive_multicast": uint64(stat.RxMulticastPackets),
|
||||
"transmit_multicast": uint64(stat.TxMulticastPackets),
|
||||
"receive_bytes": uint64(stat.RxBytes),
|
||||
"receive_dropped": uint64(stat.RxPacketsDropped),
|
||||
"receive_errors": uint64(stat.RxErrors),
|
||||
"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_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"
|
||||
"log/slog"
|
||||
"net"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
@ -71,51 +72,107 @@ func getIfaceData(index int) (*ifMsghdr2, error) {
|
|||
return nil, err
|
||||
}
|
||||
err = binary.Read(bytes.NewReader(rawData), binary.LittleEndian, &data)
|
||||
if err != nil {
|
||||
return &data, err
|
||||
}
|
||||
|
||||
/*
|
||||
As of macOS Ventura 13.2.1, there’s a kernel bug which truncates traffic values at the 4GiB mark.
|
||||
This is a workaround to fetch the interface traffic metrics using a sysctl call.
|
||||
Apple wants to prevent fingerprinting by 3rdparty apps and might fix this bug in future which would break this implementation.
|
||||
*/
|
||||
mib := []int32{
|
||||
unix.CTL_NET,
|
||||
unix.AF_LINK,
|
||||
0, // NETLINK_GENERIC: functions not specific to a type of iface
|
||||
2, //IFMIB_IFDATA: per-interface data table
|
||||
int32(index),
|
||||
1, // IFDATA_GENERAL: generic stats for all kinds of ifaces
|
||||
}
|
||||
|
||||
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
|
||||
Version uint8
|
||||
Type uint8
|
||||
Addrs int32
|
||||
Flags int32
|
||||
Index uint16
|
||||
_ [2]byte
|
||||
SndLen int32
|
||||
SndMaxlen int32
|
||||
SndDrops int32
|
||||
Timer int32
|
||||
Data ifData64
|
||||
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/darwin-xnu/blob/main/bsd/net/if_var.h#L199-L231
|
||||
// https://github.com/apple-oss-distributions/xnu/blob/main/bsd/net/if_var.h#L207-L235
|
||||
type ifData64 struct {
|
||||
Type uint8
|
||||
Typelen uint8
|
||||
Physical uint8
|
||||
Addrlen uint8
|
||||
Hdrlen uint8
|
||||
Recvquota uint8
|
||||
Xmitquota uint8
|
||||
Unused1 uint8
|
||||
Mtu uint32
|
||||
Metric uint32
|
||||
Baudrate uint64
|
||||
Ipackets uint64
|
||||
Ierrors uint64
|
||||
Opackets uint64
|
||||
Oerrors uint64
|
||||
Collisions uint64
|
||||
Ibytes uint64
|
||||
Obytes uint64
|
||||
Imcasts uint64
|
||||
Omcasts uint64
|
||||
Iqdrops uint64
|
||||
Noproto uint64
|
||||
Recvtiming uint32
|
||||
Xmittiming uint32
|
||||
Lastchange unix.Timeval32
|
||||
Type uint8 // ethernet, tokenring, etc
|
||||
Typelen uint8 // Length of frame type id
|
||||
Physical uint8 // e.g., AUI, Thinnet, 10base-T, etc
|
||||
Addrlen uint8 // media address length
|
||||
Hdrlen uint8 // media header length
|
||||
Recvquota uint8 // polling quota for receive intrs
|
||||
Xmitquota uint8 // polling quota for xmit intrs
|
||||
Unused1 uint8 // for future use
|
||||
Mtu uint32 // maximum transmission unit
|
||||
Metric uint32 // routing metric (external only)
|
||||
Baudrate uint64 // linespeed
|
||||
|
||||
// volatile statistics
|
||||
Ipackets uint64 // packets received on interface
|
||||
Ierrors uint64 // input errors on interface
|
||||
Opackets uint64 // packets sent on interface
|
||||
Oerrors uint64 // output errors on interface
|
||||
Collisions uint64 // collisions on csma interfaces
|
||||
Ibytes uint64 // total number of octets received
|
||||
Obytes uint64 // total number of octets sent
|
||||
Imcasts uint64 // packets received via multicast
|
||||
Omcasts uint64 // packets sent via multicast
|
||||
Iqdrops uint64 // dropped on input, this interface
|
||||
Noproto uint64 // destined for unsupported protocol
|
||||
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) {
|
||||
|
|
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 {
|
||||
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)
|
||||
if err != nil {
|
||||
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"))
|
||||
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.pidMax, prometheus.GaugeValue, float64(pidM))
|
||||
|
|
|
@ -48,7 +48,7 @@ func TestReadProcessStatus(t *testing.T) {
|
|||
}
|
||||
maxPid, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
|
||||
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 {
|
||||
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])
|
||||
|
||||
for _, state := range unitStatesName {
|
||||
if state == "inactive" {
|
||||
switch state {
|
||||
case "inactive":
|
||||
testSummaryHelper(t, state, summary[state], 3.0)
|
||||
} else if state == "active" {
|
||||
case "active":
|
||||
testSummaryHelper(t, state, summary[state], 1.0)
|
||||
} else {
|
||||
default:
|
||||
testSummaryHelper(t, state, summary[state], 0.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,5 +435,5 @@ type zfsSysctl string
|
|||
|
||||
func (s zfsSysctl) metricName() string {
|
||||
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
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0
|
||||
|
@ -13,23 +13,23 @@ require (
|
|||
github.com/hodgesds/perf-utils v0.7.0
|
||||
github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973
|
||||
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/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/wifi v0.3.1
|
||||
github.com/mdlayher/wifi v0.5.0
|
||||
github.com/opencontainers/selinux v1.11.1
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55
|
||||
github.com/prometheus-community/go-runit v0.1.0
|
||||
github.com/prometheus/client_golang v1.21.1
|
||||
github.com/prometheus/client_model v0.6.1
|
||||
github.com/prometheus/common v0.62.0
|
||||
github.com/prometheus/client_model v0.6.2
|
||||
github.com/prometheus/common v0.64.0
|
||||
github.com/prometheus/exporter-toolkit v0.14.0
|
||||
github.com/prometheus/procfs v0.16.0
|
||||
github.com/safchain/ethtool v0.5.10
|
||||
github.com/prometheus/procfs v0.17.0
|
||||
github.com/safchain/ethtool v0.6.1
|
||||
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
|
||||
)
|
||||
|
||||
|
@ -51,11 +51,11 @@ require (
|
|||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.35.0 // indirect
|
||||
golang.org/x/net v0.36.0 // indirect
|
||||
golang.org/x/oauth2 v0.24.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
google.golang.org/protobuf v1.36.1 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.15.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // 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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
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.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
|
||||
github.com/cilium/ebpf v0.19.0 h1:Ro/rE64RmFBeA9FGjcTc+KmCeY6jXmryu6FfnzPRIao=
|
||||
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/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
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/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
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.2/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
|
||||
github.com/jsimonetti/rtnetlink/v2 v2.0.5 h1:l5S9iedrSW4thUfgiU+Hzsnk1cOR0upGD5ttt6mirHw=
|
||||
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/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
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/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/mdlayher/ethtool v0.2.0 h1:akcA4WZVWozzirPASeMq8qgLkxpF3ykftVXwnrMKrhY=
|
||||
github.com/mdlayher/ethtool v0.2.0/go.mod h1:W0pIBrNPK1TslIN4Z9wt1EVbay66Kbvek2z2f29VBfw=
|
||||
github.com/mdlayher/ethtool v0.4.0 h1:jjMGNSQfqauwFCtSzcqpa57R0AJdxKdQgbQ9mAOtM4Q=
|
||||
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/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
|
||||
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/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
|
||||
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.3.1/go.mod h1:ODQaObvsglghTuNhezD9grkTB4shVNc28aJfTXmvSi8=
|
||||
github.com/mdlayher/wifi v0.5.0 h1:TGZIcrhL6h3710amshpEJnMzLs74MrZOF+8qbm8Gx/I=
|
||||
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/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
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/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_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
|
||||
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/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
|
||||
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM=
|
||||
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
|
||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||
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/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/safchain/ethtool v0.5.10 h1:Im294gZtuf4pSGJRAOGKaASNi3wMeFaGaWuSaomedpc=
|
||||
github.com/safchain/ethtool v0.5.10/go.mod h1:w9jh2Lx7YBR4UwzLkzCmWl85UY0W2uZdd7/DckVE5+c=
|
||||
github.com/safchain/ethtool v0.6.1 h1:mhRnXE1H8fV8TTXh/HdqE4tXtb57r//BQh5pPYMuM5k=
|
||||
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/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8=
|
||||
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/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
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.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
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/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
|
||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
||||
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
|
||||
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
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-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.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
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/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
|
|
@ -112,7 +112,7 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
if err != nil {
|
||||
h.logger.Warn("Couldn't create filtered metrics handler:", "err", err)
|
||||
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
|
||||
}
|
||||
filteredHandler.ServeHTTP(w, r)
|
||||
|
|
Loading…
Reference in a new issue