From 3f95435b898121e5110b801e75a67ed3d4262431 Mon Sep 17 00:00:00 2001 From: Jaime Yera Hidalgo <106755265+jaimeyh@users.noreply.github.com> Date: Wed, 28 Feb 2024 14:12:01 +0000 Subject: [PATCH] SECCOPM-27660: Fix vulnerabilities (#15) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixup codespell (#2455) * Fix some mistakes * Switch to an ignore file. Signed-off-by: Ben Kochie Signed-off-by: Ben Kochie * build(deps): bump github.com/jsimonetti/rtnetlink from 1.2.0 to 1.2.2 (#2459) Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.2.0 to 1.2.2. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.2.0...v1.2.2) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/prometheus/client_golang (#2460) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.12.2 to 1.13.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.12.2...v1.13.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Wrap accesses of c.osFilename and c.osMtime in mutex to prevent race condition. Signed-off-by: Robin Nabel * feat: add support macos version (#2471) Signed-off-by: Serhii Freidin Signed-off-by: Serhii Freidin * Merge metrics descriptions in textfile collector (#2475) The textfile collector will now provide a unified metric description (that will look like "Metric read from file/a.prom, file/b.prom") for metrics collected accross several text-files that don't already have a description. Also change the error handling in the textfile collector tests to ContinueOnError to better mirror the real-life use-case. Signed-off-by: Guillaume Espanel Signed-off-by: Guillaume Espanel * Skip zfs iostats (#2451) skip over the zfs IO metrics if their paths are missing Signed-off-by: tnextday Signed-off-by: tnextday * Add btrfs device error stats (#2193) * Improve metrics filesystem scanning logic * Makes ioctl syscalls to load the device error stats. * Adds filesystem mountpoint labels to existing metrics for ease of use. Signed-off-by: Marcus Cobden * Update common Prometheus files (#2473) Signed-off-by: prombot Signed-off-by: prombot * Release 1.4.0 (#2478) * [CHANGE] Merge metrics descriptions in textfile collector #2475 * [FEATURE] [node-mixin] Add darwin dashboard to mixin #2351 * [FEATURE] Add "isolated" metric on cpu collector on linux #2251 * [FEATURE] Add cgroup summary collector #2408 * [FEATURE] Add selinux collector #2205 * [FEATURE] Add slab info collector #2376 * [FEATURE] Add sysctl collector #2425 * [FEATURE] Also track the CPU Spin time for OpenBSD systems #1971 * [FEATURE] Add support for MacOS version #2471 * [ENHANCEMENT] [node-mixin] Add missing selectors #2426 * [ENHANCEMENT] [node-mixin] Change current datasource to grafana's default #2281 * [ENHANCEMENT] [node-mixin] Change disk graph to disk table #2364 * [ENHANCEMENT] [node-mixin] Change io time units to %util #2375 * [ENHANCEMENT] Ad user_wired_bytes and laundry_bytes on *bsd #2266 * [ENHANCEMENT] Add additional vm_stat memory metrics for darwin #2240 * [ENHANCEMENT] Add device filter flags to arp collector #2254 * [ENHANCEMENT] Add diskstats include and exclude device flags #2417 * [ENHANCEMENT] Add node_softirqs_total metric #2221 * [ENHANCEMENT] Add rapl zone name label option #2401 * [ENHANCEMENT] Add slabinfo collector #1799 * [ENHANCEMENT] Allow user to select port on NTP server to query #2270 * [ENHANCEMENT] collector/diskstats: Add labels and metrics from udev #2404 * [ENHANCEMENT] Enable builds against older macOS SDK #2327 * [ENHANCEMENT] qdisk-linux: Add exclude and include flags for interface name #2432 * [ENHANCEMENT] systemd: Expose systemd minor version #2282 * [ENHANCEMENT] Use netlink for tcpstat collector #2322 * [ENHANCEMENT] Use netlink to get netdev stats #2074 * [ENHANCEMENT] Add additional perf counters for stalled frontend/backend cycles #2191 * [ENHANCEMENT] Add btrfs device error stats #2193 * [BUGFIX] [node-mixin] Fix fsSpaceAvailableCriticalThreshold and fsSpaceAvailableWarning #2352 * [BUGFIX] Fix concurrency issue in ethtool collector #2289 * [BUGFIX] Fix concurrency issue in netdev collector #2267 * [BUGFIX] Fix diskstat reads and write metrics for disks with different sector sizes #2311 * [BUGFIX] Fix iostat on macos broken by deprecation warning #2292 * [BUGFIX] Fix NodeFileDescriptorLimit alerts #2340 * [BUGFIX] Sanitize rapl zone names #2299 * [BUGFIX] Add file descriptor close safely in test #2447 * [BUGFIX] Fix race condition in os_release.go #2454 * [BUGFIX] Skip ZFS IO metrics if their paths are missing #2451 Signed-off-by: Ben Kochie Signed-off-by: Ben Kochie * Archived fixtures/udev similar to fixtures/sys to avoid go-get errors, fixes #2482 (#2485) Signed-off-by: Darshil Chanpura * Fix diskstats exclude flags (#2487) Correctly handle the new `collector.diskstats.device-exclude` flag to avoid errors when using the old `collector.diskstats.ignored-devices` flag. Fixes: https://github.com/prometheus/node_exporter/issues/2486 Signed-off-by: Ben Kochie * Update ISSUE_TEMPLATE.md Signed-off-by: Johannes 'fish' Ziemke * Bump crypto and net CVE-2022-27191 CVE-2022-27664 (#2488) * Bump crypto and net CVE-2022-27191 CVE-2022-27664 Signed-off-by: Jason Culligan * Fix hwmon label sanitizer (#2504) We don't need to fully sanitize the hwmon label values to metric/label name strings. * Just make sure they're valid UTF-8. * Always included the label metric to avoid group_left failures. Signed-off-by: Ben Kochie Signed-off-by: Ben Kochie * build(deps): bump github.com/opencontainers/selinux Bumps [github.com/opencontainers/selinux](https://github.com/opencontainers/selinux) from 1.10.1 to 1.10.2. - [Release notes](https://github.com/opencontainers/selinux/releases) - [Commits](https://github.com/opencontainers/selinux/compare/v1.10.1...v1.10.2) --- updated-dependencies: - dependency-name: github.com/opencontainers/selinux dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/mdlayher/netlink from 1.6.0 to 1.6.2 Bumps [github.com/mdlayher/netlink](https://github.com/mdlayher/netlink) from 1.6.0 to 1.6.2. - [Release notes](https://github.com/mdlayher/netlink/releases) - [Changelog](https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md) - [Commits](https://github.com/mdlayher/netlink/compare/v1.6.0...v1.6.2) --- updated-dependencies: - dependency-name: github.com/mdlayher/netlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/coreos/go-systemd/v22 from 22.3.2 to 22.4.0 (#2493) Bumps [github.com/coreos/go-systemd/v22](https://github.com/coreos/go-systemd) from 22.3.2 to 22.4.0. - [Release notes](https://github.com/coreos/go-systemd/releases) - [Commits](https://github.com/coreos/go-systemd/compare/v22.3.2...v22.4.0) --- updated-dependencies: - dependency-name: github.com/coreos/go-systemd/v22 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs/node-mixin: add fsMointpointSelector to alerts and dashboards (#2446) * docs/node-mixin: add fsMountpointSelector This adds the option to add a `mountpoint` selector to filesystem related alerts. The default is `mountpoint!=""`. * docs/node-mixins: add fsMountpointSelector to dashboards Signed-off-by: Jan Fajerski * Use native endianness when encoding InetDiagMsg (#2508) Note however that the InetDiagMsg struct contains a InetDiagSockID member, which itself contains some members which are explicitly specified as big-endian in Linux kernel source: struct inet_diag_sockid { __be16 idiag_sport; __be16 idiag_dport; __be32 idiag_src[4]; __be32 idiag_dst[4]; __u32 idiag_if; __u32 idiag_cookie[2]; }; node_exporter currently does not use these members for anything, so this is acceptable (for now). Signed-off-by: Daniel Swarbrick * Add multiple listeners and systemd socket listener activation (#2393) Update exporter-toolkit to v0.8.1 to enable new listener support. Signed-off-by: Perry Naseck * Add procfs fallback to netdev collector (#2509) Some systems have broken netlink messages due to patched kernels. Since these messages can not be parsed, add a flag to fall back to parsing from `/proc/net/dev`. Fixes: https://github.com/prometheus/node_exporter/issues/2502 Signed-off-by: Ben Kochie Signed-off-by: Ben Kochie * build(deps): bump github.com/prometheus/client_model from 0.2.0 to 0.3.0 Bumps [github.com/prometheus/client_model](https://github.com/prometheus/client_model) from 0.2.0 to 0.3.0. - [Release notes](https://github.com/prometheus/client_model/releases) - [Commits](https://github.com/prometheus/client_model/compare/v0.2.0...v0.3.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_model dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/jsimonetti/rtnetlink from 1.2.2 to 1.2.3 Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.2.2 to 1.2.3. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.2.2...v1.2.3) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Fix btrfs device stats always being zero (#2516) * Respect rootfs path config option in btrfs ioctl * Fix btrfs device stats always being zero Signed-off-by: Marcus Cobden * readme: remove RHEL/CentOS/Fedora installation info (#2525) Copr community prometheus-exporters repository is obsoleted. Signed-off-by: Otto Sabart Signed-off-by: Otto Sabart * add RTNL version of netclass collector (#2492) * update rtnetlink package to v1.2.3 * add RTNL version of netclass collector that have all the metrics that netdev collector provides, too. Signed-off-by: Haoyu Sun * update to golang.org/x/sys v0.1.0 (#2524) Signed-off-by: Manuel Stausberg * Refactor netclass_rtnl collector (#2528) * Refactor netclass_rtnl collector Merge the netclass_rtnl collector into the netclass collector. * Disabled by default * Followup to #2492 Signed-off-by: Ben Kochie * Default GOMAXPROCS to 1 (#2530) Avoid running on all CPUs by limiting the Go runtime to one CPU by default. Avoids having Go routines schedule on every CPU, driving up the visible run queue length on high CPU count systems. This also helps workaround a kernel deadlock issue with reading from sysfs concurrently. See: * https://github.com/prometheus/node_exporter/issues/1880 * https://github.com/prometheus/node_exporter/issues/2500 Signed-off-by: Ben Kochie * Bump Go modules (#2531) * Update all Go modules to latest. * Update Go minimum version to 1.18. Signed-off-by: Ben Kochie * Release v1.5.0 NOTE: This changes the Go runtime "GOMAXPROCS" to 1. This is done to limit the concurrency of the exporter to 1 CPU thread at a time in order to avoid a race condition problem in the Linux kernel (#2500) and parallel IO issues on nodes with high numbers of CPUs/CPU threads (#1880). * [CHANGE] Default GOMAXPROCS to 1 #2530 * [FEATURE] Add multiple listeners and systemd socket listener activation #2393 * [ENHANCEMENT] Add RTNL version of netclass collector #2492, #2528 * [BUGFIX] Fix diskstats exclude flags #2487 * [BUGFIX] Bump go/x/crypt and go/x/net #2488 * [BUGFIX] Fix hwmon label sanitizer #2504 * [BUGFIX] Use native endianness when encoding InetDiagMsg #2508 * [BUGFIX] Fix btrfs device stats always being zero #2516 * [BUGFIX] Security: Update exporter-toolkit (CVE-2022-46146) #2531 Signed-off-by: Ben Kochie * Correct documentation for --web.config.file flag The --web.config flag changed to --web.config.file in 440a132c389dddd405b44d2d5e47157d1159e4d0 and was realised in the recent v1.5.0 release. Signed-off-by: Joe Groocock * Log current value of GOMAXPROCS With `--runtime.gomaxprocs=0`, the GOMAXPROXS value will default to the number of logical CPUs. In this case, it is more useful to log the actual value than the value set by the user via the command-line. Signed-off-by: Simon Pasquier * add options for perf profilers Signed-off-by: mchtech * fix the docker link in the ISSUE_TEMPLATE Signed-off-by: Yury Vidineev * Replace mistaken ) with }, resulting in parsable promql Signed-off-by: Ryan J. Geyer * Update v1.5.0 release notes Add note about the change to the experimental web flag. Fixes: https://github.com/prometheus/node_exporter/issues/2535 Signed-off-by: Ben Kochie * Update common Prometheus files Signed-off-by: prombot * Migrate arp_linux.go to procfs Signed-off-by: James Bach Signed-off-by: James Bach Signed-off-by: jalev * Change var name to match previous Signed-off-by: James Bach Signed-off-by: jalev * Fix lint issues Signed-off-by: jalev * Bump perf-utils version to 0.6.0 This change updates the perf-utils library to 0.6.0 which has some fixes for automatically detecting the correct tracefs mountpoint if available. Signed-off-by: Daniel Hodges * Fix thermal_zone collector noise Add a check for missing/unreadable thermal zone stats and ignore if not availlable. Fixes: https://github.com/prometheus/node_exporter/issues/2552 Signed-off-by: Ben Kochie * Update common Prometheus files Signed-off-by: prombot * Enable uname collector on NetBSD too This collector works just fine without any further changes. Signed-off-by: Benny Siegert * build(deps): bump github.com/mdlayher/netlink from 1.7.0 to 1.7.1 Bumps [github.com/mdlayher/netlink](https://github.com/mdlayher/netlink) from 1.7.0 to 1.7.1. - [Release notes](https://github.com/mdlayher/netlink/releases) - [Changelog](https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md) - [Commits](https://github.com/mdlayher/netlink/compare/v1.7.0...v1.7.1) --- updated-dependencies: - dependency-name: github.com/mdlayher/netlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/josharian/native from 1.0.0 to 1.1.0 Bumps [github.com/josharian/native](https://github.com/josharian/native) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/josharian/native/releases) - [Commits](https://github.com/josharian/native/compare/v1.0.0...v1.1.0) --- updated-dependencies: - dependency-name: github.com/josharian/native dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix cpustat when some cpus are offline Signed-off-by: Jia Xin * build(deps): bump github.com/prometheus/common from 0.37.0 to 0.39.0 Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.37.0 to 0.39.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.37.0...v0.39.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update e2e output for new common version. Signed-off-by: Ben Kochie * Update common Prometheus files Signed-off-by: prombot * NetBSD support for the meminfo collector This depends on a recent change to golang.org/x/sys that adds a unix.SysctlUvmexp function. Signed-off-by: Benny Siegert * memory_bsd: Fix a problem fetching the user wire count on FreeBSD Signed-off-by: David O'Rourke * Optimize cpufreq collector Move metric descriptiions to package vars to avoid allocating them every time `NewCPUFreqCollector()` is called. Signed-off-by: Ben Kochie * build(deps): bump github.com/hodgesds/perf-utils from 0.6.0 to 0.7.0 Bumps [github.com/hodgesds/perf-utils](https://github.com/hodgesds/perf-utils) from 0.6.0 to 0.7.0. - [Release notes](https://github.com/hodgesds/perf-utils/releases) - [Commits](https://github.com/hodgesds/perf-utils/compare/v0.6.0...v0.7.0) --- updated-dependencies: - dependency-name: github.com/hodgesds/perf-utils dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Deprecate ntp collector The ntp collector has always been a source of confusion and problems. The data it produces is more of a blackbox probe against an NTP server. The time sync / offset data produced is not what users expect. Mark this collector as deprecated to be removed in v2.0.0 Signed-off-by: Ben Kochie * Update common Prometheus files Signed-off-by: prombot * build(deps): bump golang.org/x/net from 0.4.0 to 0.7.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.4.0 to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.4.0...v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] * Remove metrics of offline CPUs in CPU collector Signed-off-by: Haoyu Sun * build(deps): bump github.com/jsimonetti/rtnetlink from 1.3.0 to 1.3.1 Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.3.0 to 1.3.1. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.3.0...v1.3.1) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/opencontainers/selinux Bumps [github.com/opencontainers/selinux](https://github.com/opencontainers/selinux) from 1.10.2 to 1.11.0. - [Release notes](https://github.com/opencontainers/selinux/releases) - [Commits](https://github.com/opencontainers/selinux/compare/v1.10.2...v1.11.0) --- updated-dependencies: - dependency-name: github.com/opencontainers/selinux dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump golang.org/x/sys from 0.5.0 to 0.6.0 Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.5.0 to 0.6.0. - [Release notes](https://github.com/golang/sys/releases) - [Commits](https://github.com/golang/sys/compare/v0.5.0...v0.6.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update exporter-toolkit * Bump exporter-toolkit to the latest release. * Use new toolkit landing page function. * Update kingpin flags. Signed-off-by: Ben Kochie * Bump exporter-toolkit Pick up the fixes for 32-bit mode and updated HTML template. Signed-off-by: Ben Kochie * Update build * Update Go to 1.20 * Update golangci-lint. * Update CI orb. * Fix staticcheck issue in perf collector. Signed-off-by: Ben Kochie * Allow root path as metrics path. (#2590) Signed-off-by: LamGC * Fix spelling issues Minor typo fixup. Signed-off-by: Ben Kochie * interrupts_linux: Fix fields on aarch64 (#2631) * interrupts_linux: Fix fields on aarch64 Fixes #2557 --------- Signed-off-by: Daniël van Eeden * feat: add support for cpu freq governor metrics Signed-off-by: Lukas Coppens * feat: add support for cpu freq governor metrics Signed-off-by: Lukas Coppens * Reduce priviliges needed for btrfs device stats Signed-off-by: Marcus Cobden * Update common Prometheus files Signed-off-by: prombot * build(deps): bump github.com/safchain/ethtool from 0.2.0 to 0.3.0 Bumps [github.com/safchain/ethtool](https://github.com/safchain/ethtool) from 0.2.0 to 0.3.0. - [Release notes](https://github.com/safchain/ethtool/releases) - [Commits](https://github.com/safchain/ethtool/compare/v0.2.0...v0.3.0) --- updated-dependencies: - dependency-name: github.com/safchain/ethtool dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/prometheus/common from 0.41.0 to 0.42.0 Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.41.0 to 0.42.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.41.0...v0.42.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * NetBSD support for CPU collector (#2626) * Added CPU collector for NetBSD to provide load and temperature statistics --------- Signed-off-by: Matthias Petermann * feat: added suspended as a node_zfs_zpool_state (#2449) Signed-off-by: Pablo Caderno * build(deps): bump github.com/mdlayher/netlink from 1.7.1 to 1.7.2 Bumps [github.com/mdlayher/netlink](https://github.com/mdlayher/netlink) from 1.7.1 to 1.7.2. - [Release notes](https://github.com/mdlayher/netlink/releases) - [Changelog](https://github.com/mdlayher/netlink/blob/main/CHANGELOG.md) - [Commits](https://github.com/mdlayher/netlink/compare/v1.7.1...v1.7.2) --- updated-dependencies: - dependency-name: github.com/mdlayher/netlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/prometheus/client_golang Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.14.0 to 1.15.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.14.0...v1.15.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * doc: added undocumented include and exclude flags (#2670) * doc: added undocumented exclude flags Signed-off-by: David Calvert * Expose administrative state of network interfaces as 'adminstate'. (#2515) Signed-off-by: Maximilian Wilhelm * Use go-runit fork, mark collector as deprecated Signed-off-by: Johannes Ziemke * build(deps): bump github.com/jsimonetti/rtnetlink from 1.3.1 to 1.3.2 (#2673) Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.3.1 to 1.3.2. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.3.1...v1.3.2) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs (node/mixin): fix annotation for Skew alert (#2671) This updates the annotation for the NodeClockSkewDetected mixin alert to match the new threshold set. Original discussion was in this PR: https://github.com/prometheus/node_exporter/pull/1480 I spent an embarrassingly large amount of time trying to figure out how the heck that alert would mean 300s of clock skew. Turns out the annotation was just left the same after the threshold change. Signed-off-by: Will Bollock * collector/netisr_freebsd.go: Added collector for netisr subsystem. (#2668) Signed-off-by: Jonathan Davies * Do not hand define struct clockinfo here. Instead use the version from (#2663) x/sys/unix. The clockinfo struct was altered beginning of 2021 and this code was not adjusted. Signed-off-by: Claudio Jeker * Fix filesystem collector for OpenBSD to not print loads of zero bytes in name (#2637) Use the filesystem collector for all OpenBSD archs, there is no reason to only use it on amd64 systems. Signed-off-by: Claudio Jeker * collector: fix comment and remove redundant parentheses (#2691) Signed-off-by: cui fliter * bcache: remove cache_readaheads_totals metrics #2103 (#2583) * bcache: remove cache_readaheads_totals metrics #2103 Signed-off-by: Saleh Sal <0xack13@gmail.com> * Append bcacheReadaheadMetrics when CacheReadaheads value exists Signed-off-by: Saleh Sal <0xack13@gmail.com> * Update test cases for cachereadahead greater than zero Signed-off-by: Saleh Sal <0xack13@gmail.com> --------- Signed-off-by: Saleh Sal <0xack13@gmail.com> * Fix CVE-2022-41723 by upgrading x/net to v0.10.0 (#2694) Signed-off-by: Nitin Shelke * Update e2e output fixtures (#2696) Fix up correct e2e output for node_power_supply_info. Signed-off-by: Ben Kochie * Update Go modules (#2695) Update Prometheus modules to latest releases. * Add missing fixtures for cpus online/offline. Signed-off-by: Ben Kochie * fix(zfs): add `memory_available_bytes`, fix `dbufstats` filename on Linux (#2687) * Fix zfs memory_available_bytes collector * Fix zfs dbufstats collector --------- Signed-off-by: dongjiang1989 * Update Go module for ema/qdisc (#2700) * Update Go module for ema/qdisc --------- Signed-off-by: jbradleynh * Deprecate supervisord collector Mark the `supervisord` as deprecated. This process supevisor, like `runit`, is of scope for the node_exporter. Signed-off-by: Ben Kochie * collector/diskstats: Use SCSI_IDENT_SERIAL as serial (#2612) On most hard drives, `ID_SERIAL_SHORT` and `SCSI_IDENT_SERIAL` are identical, but on some SAS drives they do differ. In that case, `SCSI_IDENT_SERIAL` corresponds to the serial number printed on the drive label, and to the value returned by `smartctl -i`. So use that value by default for the `serial` label on the `node_disk_info` metric, and fallback to `ID_SERIAL_SHORT` only if it's undefined. Signed-off-by: Benoît Knecht * softnet: additionals metrics from softnet_data, (#2592) * softnet: additionals metrics from softnet_data, https://github.com/prometheus/procfs/pull/473 --------- Signed-off-by: remi Signed-off-by: Rémi Jouannet * exposing softirq metrics (#2294) Signed-off-by: abbeywoodyear * netlink: read missing attributes from sysfs (#2669) Read missing dev_id, name_assign_type, and addr_assign_type from sysfs, since they only take a device-specific lock and not the whole RTNL lock. This means reading them is much less impactful on other system processes than many of the other attributes in sysfs that do take the RTNL lock. Signed-off-by: Dan Williams * Update ansible role in README.md (#2702) https://github.com/cloudalchemy/ansible-node-exporter has been deprecated Signed-off-by: Johannes Dilli * Release v1.6.0 (#2701) * [CHANGE] Fix cpustat when some cpus are offline #2318 * [CHANGE] Remove metrics of offline CPUs in CPU collector #2605 * [CHANGE] Deprecate ntp collector #2603 * [CHANGE] Remove bcache `cache_readaheads_totals` metrics #2583 * [CHANGE] Deprecate supervisord collector #2685 * [FEATURE] Enable uname collector on NetBSD #2559 * [FEATURE] NetBSD support for the meminfo collector #2570 * [FEATURE] NetBSD support for CPU collector #2626 * [FEATURE] Add FreeBSD collector for netisr subsystem #2668 * [FEATURE] Add softirqs collector #2669 * [ENHANCEMENT] Add suspended as a `node_zfs_zpool_state` #2449 * [ENHANCEMENT] Add administrative state of Linux network interfaces #2515 * [ENHANCEMENT] Log current value of GOMAXPROCS #2537 * [ENHANCEMENT] Add profiler options for perf collector #2542 * [ENHANCEMENT] Allow root path as metrics path #2590 * [ENHANCEMENT] Add cpu frequency governor metrics #2569 * [ENHANCEMENT] Add new landing page #2622 * [ENHANCEMENT] Reduce privileges needed for btrfs device stats #2634 * [ENHANCEMENT] Add ZFS `memory_available_bytes` #2687 * [ENHANCEMENT] Use `SCSI_IDENT_SERIAL` as serial in diskstats #2612 * [ENHANCEMENT] Read missing from netlink netclass attributes from sysfs #2669 * [BUGFIX] perf: fixes for automatically detecting the correct tracefs mountpoints #2553 * [BUGFIX] Fix `thermal_zone` collector noise @2554 * [BUGFIX] Fix a problem fetching the user wire count on FreeBSD 2584 * [BUGFIX] interrupts: Fix fields on linux aarch64 #2631 * [BUGFIX] Remove metrics of offline CPUs in CPU collector #2605 * [BUGFIX] Fix OpenBSD filesystem collector string parsing #2637 * [BUGFIX] Fix bad reporting of `node_cpu_seconds_total` in OpenBSD #2663 Signed-off-by: Ben Kochie * build(deps): bump github.com/beevik/ntp from 0.3.0 to 1.0.0 Bumps [github.com/beevik/ntp](https://github.com/beevik/ntp) from 0.3.0 to 1.0.0. - [Release notes](https://github.com/beevik/ntp/releases) - [Changelog](https://github.com/beevik/ntp/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/beevik/ntp/compare/v0.3.0...v1.0.0) --- updated-dependencies: - dependency-name: github.com/beevik/ntp dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/prometheus/procfs from 0.10.0 to 0.10.1 Bumps [github.com/prometheus/procfs](https://github.com/prometheus/procfs) from 0.10.0 to 0.10.1. - [Release notes](https://github.com/prometheus/procfs/releases) - [Commits](https://github.com/prometheus/procfs/compare/v0.10.0...v0.10.1) --- updated-dependencies: - dependency-name: github.com/prometheus/procfs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/jsimonetti/rtnetlink from 1.3.2 to 1.3.3 Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.3.2 to 1.3.3. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.3.2...v1.3.3) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Parallelize stat calls in Linux filesystem collector. This change adds the ability to process multiple stat calls in parallel. Processing is rate-limited based on the new flag `collector.filesystem.stat-workers` (default 4). Caveat: filesystem stats information is no longer in the same order as returned by `/proc/1/mounts`. This should not be an issue. Caveat: This change currently uses unbuffered channels to prove correctness without reliance on buffers. Buffered channels will yield superior performance. Signed-off-by: Erica Mays * fix misspel in CHANGELOG.md (#2717) Signed-off-by: juzhao * Bump wifi Go module (#2719) Update github.com/mdlayher/wifi to the latest commit. Signed-off-by: Ben Kochie * Bump ethtool library (#2720) Update to latest release. Signed-off-by: Ben Kochie * add missing linkspeeds (#2711) Signed-off-by: Cam Cope * Update common Prometheus files (#2723) Signed-off-by: prombot * Update golangci-lint config (#2722) * Migrate from Python codespell to golangci-lint misspell. * Inline errcheck exclude list in the golangci-lint config. Signed-off-by: Ben Kochie * Add mountpoint to NodeFilesystem alerts This helps to identify alerting filesystem. Signed-off-by: Vitaly Zhuravlev * Decrease NodeFilesystem pending time to 15m 30m is too long and there is a risk of running out of disk space/inodes completely if something is filling up disk very fast (like log file). Signed-off-by: Vitaly Zhuravlev * Add CPU and memory alerts Signed-off-by: Vitaly Zhuravlev * Add failed systemd service alert Signed-off-by: Vitaly Zhuravlev * Decrease NodeNetwork*Errs pending period Signed-off-by: Vitaly Zhuravlev * Set 'at' everywhere as preposition for instance Signed-off-by: Vitaly Zhuravlev * Add NodeDiskIOSaturation alert Signed-off-by: Vitaly Zhuravlev * Add %(nodeExporterSelector)s to Network and conntrack alerts Signed-off-by: Vitaly Zhuravlev * Add diskDevice selector Signed-off-by: Vitaly Zhuravlev * Fix NodeMemoryHighUtilization alert Signed-off-by: Vitaly Zhuravlev * Add NodeSystemSaturation and NodeMemoryMajorPagesFaults Signed-off-by: Vitaly Zhuravlev * Decrease NodeSystemdServiceFailed severity to warning Signed-off-by: Vitaly Zhuravlev * Extend alert description Signed-off-by: Vitaly Zhuravlev * Add comma after 'mounted on' Signed-off-by: Vitaly Zhuravlev * Add thresholds for memory alerts Signed-off-by: Vitaly Zhuravlev * Add thresholds for memory, disk and system alerts Signed-off-by: Vitaly Zhuravlev * Set severity to NodeCPUHighUsage to info Signed-off-by: Vitaly Zhuravlev * Update NodeSystemSaturation severity Signed-off-by: Vitaly Zhuravlev * Revert alerts pending durtions Signed-off-by: Vitaly Zhuravlev * Update common Prometheus files Signed-off-by: prombot * Add cpu vulnerabilities reporting from sysfs (#2721) * Add cpu vulnerabilities reporting from sysfs --------- Signed-off-by: Michal Wasilewski * build(deps): bump github.com/beevik/ntp from 1.0.0 to 1.1.1 Bumps [github.com/beevik/ntp](https://github.com/beevik/ntp) from 1.0.0 to 1.1.1. - [Release notes](https://github.com/beevik/ntp/releases) - [Changelog](https://github.com/beevik/ntp/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/beevik/ntp/compare/v1.0.0...v1.1.1) --- updated-dependencies: - dependency-name: github.com/beevik/ntp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/prometheus/client_golang Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.15.1 to 1.16.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.15.1...v1.16.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Add include and exclude filter for hwmon collector (#2699) * Add include and exclude flags chip name flags to hwmon collector, following example in systemd collector --------- Signed-off-by: Conall O'Brien Co-authored-by: Ben Kochie * Add missing ethtool flag documentation (#2743) Signed-off-by: Gabi Davar * Update all Include and Exclude variables to use the systemdUnit naming (#2740) prefix. Leave an annotation about using regexps instead of device_filter.go, so @SuperQ doesn't need to remember everything. Signed-off-by: Conall O'Brien * Fixup hwmon chip include (#2739) Use the correct include value to the device filter function. * Add new bogus hwmon fixture. * Update end-to-end test to use hwmon chip include flag. Signed-off-by: Ben Kochie * Release v1.6.1 (#2747) Rebuild with latest Go compiler bugfix release. Signed-off-by: Ben Kochie * Synchronize common files from prometheus/prometheus (#2736) * Update common Prometheus files Signed-off-by: prombot * Fixup linting issues * Disbale unused-parameter check. * Fixup minor linting issues. Signed-off-by: Ben Kochie --------- Signed-off-by: prombot Signed-off-by: Ben Kochie Co-authored-by: Ben Kochie * Update common Prometheus files (#2752) Signed-off-by: prombot * Include drm collector in README The DRM collector was missing in the README, this change includes it together with a short description. Signed-off-by: L <3177243+LukeLR@users.noreply.github.com> * collector/netdev_linux.go: Fallback to 32-bit stats (#2757) On some platforms, `msg.Attributes.Stats64` is `nil` because the kernel doesn't expose 64-bit stats. In that case, return `msg.Attributes.Stats` instead, which are the 32-bit equivalent. Note that `RXOtherhostDropped` isn't available in that case, so we hardcode it to zero. Fixes #2756. Signed-off-by: Benoît Knecht * build(deps): bump github.com/beevik/ntp from 1.1.1 to 1.3.0 (#2762) Signed-off-by: Ben Kochie * build(deps): bump github.com/prometheus/procfs from 0.11.0 to 0.11.1 (#2763) Bumps [github.com/prometheus/procfs](https://github.com/prometheus/procfs) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/prometheus/procfs/releases) - [Commits](https://github.com/prometheus/procfs/compare/v0.11.0...v0.11.1) --- updated-dependencies: - dependency-name: github.com/prometheus/procfs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/jsimonetti/rtnetlink from 1.3.3 to 1.3.4 (#2765) Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.3.3 to 1.3.4. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.3.3...v1.3.4) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Drop redundant GOOS build tags if already in filename Drop redundant GOOS build tags at start of file if the constraint is already specified by the filename, e.g. foo_GOOS.go or foo_GOOS_GOARCH.go, avoiding potential confusion in future. cf. https://pkg.go.dev/cmd/go#hdr-Build_constraints Signed-off-by: Daniel Swarbrick * Sync build tags in *_test.go (#2767) Ensure that unwanted tests are correctly excluded when various build tags are specified, i.e. when the code that they test would be excluded from compilation. Signed-off-by: Daniel Swarbrick * Upgrade github.com/ema/qdisc to v1.0.0 to improve qdisc collector (#2779) performance Signed-off-by: Oliver Geiselhardt-Herms Co-authored-by: Oliver Geiselhardt-Herms * Add CPU MHz as the value for "node_cpu_info" metric For CPUs which don't have an available (or insertable) cpufreq driver, the /proc/cpuinfo file can sometimes have accurate CPU core frequency measurements. This change replaces the constant value of "1" for the "node_cpu_info" metric with the parsed CPU MHz value from /proc/cpuinfo for each core. Signed-off-by: John Kordich * Update e2e-output.txt with new expected metric values Changes the e2e-output.txt file to have the expected CPU MHz values for the node_cpu_info metric. Signed-off-by: John Kordich * Add new node_cpu_frequency_hertz metric Revert changes to node_cpu_info and add new node_cpu_frequency_hertz metric for measuring CPU frequency from /proc/cpuinfo Signed-off-by: John Kordich * Change log message from Warn to Debug Signed-off-by: John Kordich Co-authored-by: Ben Kochie Signed-off-by: John Kordich * fix(qdisc) flag naming corrected for consistency (#2782) * fix collector qdisc flag naming for consistency --------- Signed-off-by: jbradleynh * btrfs: close btrfs.FS handle after use Despite being quite hard to provoke (< 10% in my testing), the btrfs collector would occasionally leave stale FDs relating to btrfs mountpoints, making the filesystems unable to be unmounted. Fixes: #2772. Signed-off-by: Daniel Swarbrick * Update to Go 1.21 (#2796) * Update Go build to 1.21. * Update machine images to Ubuntu 22.04 current. Signed-off-by: Ben Kochie * Optionally fetch ARP stats via rtnetlink instead of procfs (#2777) * Optionally fetch ARP stats via rtnetlink instead of procfs Implement collection of ARP stats via rtnetlink to work around shortcomings in the output of /proc/net/arp, which truncates InfiniBand link-layer addresses. Fixes: #2776 --------- Signed-off-by: Daniel Swarbrick Co-authored-by: Ben Kochie * build(deps): bump golang.org/x/sys from 0.10.0 to 0.12.0 (#2797) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.10.0 to 0.12.0. - [Commits](https://github.com/golang/sys/compare/v0.10.0...v0.12.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update common Prometheus files (#2798) Signed-off-by: prombot * Add ZFS freebsd per dataset stats (#2753) * Rename parsePoolObjsetFile to parseLinuxPoolObjsetFile to better reflect it's scope * Create a new parseFreeBSDPoolObjsetStats function, to generate a list of per pool metrics to be queried via sysctl --------- Signed-off-by: Conall O'Brien * Move RO status before error return Signed-off-by: Metbog * Update common Prometheus files Signed-off-by: prombot * fix(zfs) zfs `arcstats.p` on FreeBSD 14.0+ (#2754) * dongjiang, fix zfs arcstats.p Signed-off-by: dongjiang1989 * dongjiang, fix gofmt -s Signed-off-by: dongjiang1989 * change warn log to debug log by code review Signed-off-by: dongjiang1989 --------- Signed-off-by: dongjiang1989 * Fix promhttp_metric_handler_errors_total metric not being disabled by flag Signed-off-by: ToMe25 * build(deps): bump github.com/prometheus/client_golang (#2815) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.16.0 to 1.17.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.16.0...v1.17.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix inconsistent variable name, to address compilation issue (#2820) https://github.com/prometheus/node_exporter/issues/2819 Signed-off-by: Conall O'Brien * Update README.md: update the 'more details' url in the section 'TLS endpoint' (#2814) * Update README.md: correct the wrong url(link to exporter-toolkit web-config) in the section 'TLS endpoint' Signed-off-by: yang-stressfree <68363665+yang-stressfree@users.noreply.github.com> * Update README.md Co-authored-by: Ben Kochie Signed-off-by: yang-stressfree <68363665+yang-stressfree@users.noreply.github.com> --------- Signed-off-by: yang-stressfree <68363665+yang-stressfree@users.noreply.github.com> Co-authored-by: Ben Kochie * Update common Prometheus files Signed-off-by: prombot * build(deps): bump golang.org/x/net from 0.11.0 to 0.17.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.11.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.11.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump github.com/prometheus/procfs from 0.11.1 to 0.12.0 Bumps [github.com/prometheus/procfs](https://github.com/prometheus/procfs) from 0.11.1 to 0.12.0. - [Release notes](https://github.com/prometheus/procfs/releases) - [Commits](https://github.com/prometheus/procfs/compare/v0.11.1...v0.12.0) --- updated-dependencies: - dependency-name: github.com/prometheus/procfs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update e2e fixtures Update for fixes in https://github.com/prometheus/procfs/pull/543 Signed-off-by: Ben Kochie * NFSd: fix nfsd v4 index miss (#2824) * fix nfsd v4 index miss --------- Signed-off-by: dongjiang1989 * fix readme about expose memory statistics Signed-off-by: joey * Fix typo in CHANGELOG.md (#2836) Use # consistently for PR number. Signed-off-by: nemobis * Update common Prometheus files (#2840) Signed-off-by: prombot * build(deps): bump github.com/prometheus/common from 0.44.0 to 0.45.0 (#2837) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.44.0 to 0.45.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.44.0...v0.45.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/prometheus/client_model (#2838) Bumps [github.com/prometheus/client_model](https://github.com/prometheus/client_model) from 0.4.1-0.20230718164431-9a2bf3000d16 to 0.5.0. - [Release notes](https://github.com/prometheus/client_model/releases) - [Commits](https://github.com/prometheus/client_model/commits/v0.5.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_model dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Release 1.7.0 (#2845) * [FEATURE] Add ZFS freebsd per dataset stats #2753 * [FEATURE] Add cpu vulnerabilities reporting from sysfs #2721 * [ENHANCEMENT] Parallelize stat calls in Linux filesystem collector #1772 * [ENHANCEMENT] Add missing linkspeeds to ethtool collector 2711 * [ENHANCEMENT] Add CPU MHz as the value for `node_cpu_info` metric #2778 * [ENHANCEMENT] Improve qdisc collector performance #2779 * [ENHANCEMENT] Add include and exclude filter for hwmon collector #2699 * [ENHANCEMENT] Optionally fetch ARP stats via rtnetlink instead of procfs #2777 * [BUFFIX] Fix ZFS arcstats on FreeBSD 14.0+ 2754 * [BUGFIX] Fallback to 32-bit stats in netdev #2757 * [BUGFIX] Close btrfs.FS handle after use #2780 * [BUGFIX] Move RO status before error return #2807 * [BUFFIX] Fix `promhttp_metric_handler_errors_total` being always active #2808 * [BUGFIX] Fix nfsd v4 index miss #2824 Signed-off-by: Ben Kochie * Add NodeBondingDegraded alert (#2843) Signed-off-by: Ayoub Nasr * Make filesystem space prediction window configurable (#2844) Signed-off-by: fitz123 * NFSd: handle new wdeleg_getattr attribute in /proc/net/rpc/nfsd (#2810) This attribute was introduced it v6.6-rc1. The relevant changes in procfs were merged here: https://github.com/prometheus/procfs/pull/574 and are part of procfs v0.11.2 I have also figured out that the stat should be part of the v4 ops counters struct, but that will need changes to both procfs and this code. Since people are already using 6.6-rc1, I think it's better to get the code out there --- even if they don't care about wdeleg_getattr, currently they get _no_ nfsd stats with 6.6-rc1. I will make two follow-up PRs to clean this up in the next releases of procfs and node-exporter. Signed-off-by: Tobias Klausmann * Update common Prometheus files (#2851) Signed-off-by: prombot * Update containerization warnings (#2855) Running node_exporter in containers is now a fairly well understood problem. Replace the warnings with something less dire and more prescriptive. Signed-off-by: Ben Kochie * Fix debug log in cpu collector (#2857) Signed-off-by: Simon Pasquier * build(deps): bump github.com/alecthomas/kingpin/v2 from 2.3.2 to 2.4.0 (#2865) Bumps [github.com/alecthomas/kingpin/v2](https://github.com/alecthomas/kingpin) from 2.3.2 to 2.4.0. - [Release notes](https://github.com/alecthomas/kingpin/releases) - [Commits](https://github.com/alecthomas/kingpin/compare/v2.3.2...v2.4.0) --- updated-dependencies: - dependency-name: github.com/alecthomas/kingpin/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump howett.net/plist from 1.0.0 to 1.0.1 (#2862) Bumps [howett.net/plist](https://github.com/DHowett/go-plist) from 1.0.0 to 1.0.1. - [Commits](https://github.com/DHowett/go-plist/compare/v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: howett.net/plist dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add new collector and metrics for XFRM (#2544) (#2866) Signed-off-by: Gavin Lam * build(deps): bump github.com/jsimonetti/rtnetlink from 1.3.5 to 1.4.0 (#2864) Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.3.5 to 1.4.0. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.3.5...v1.4.0) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump golang.org/x/sys from 0.13.0 to 0.15.0 (#2863) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.13.0 to 0.15.0. - [Commits](https://github.com/golang/sys/compare/v0.13.0...v0.15.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add TCPOFOQueue to default netstat metrics (#2867) Adds a count for TCP packets received out of orders. This can be an indication that there is packet loss on the way packets travel towards this server. In that case, the sender will retransmit (and we can already monitor the Tcp_RetransSegs there), but we have no way to monitor the packet loss on the receiver side. When a packet is received and the receiver detects previous one missing, it will increase the TCPOFOQueue counter and reply with selective ACK to the sender, both possible indications of packet loss. Confirmation of packet loss can be achieved by taking packet captures, ignoring wireshark analysis, and carefully looking at data being retransmitted based on the TCP seq. Just like RetransSegs, TCPOFOQueue should be interesting for any deployment as a mean to detect packet loss, so here suggesting adding it to the default list. Signed-off-by: François Rigault Co-authored-by: François Rigault * Update common Prometheus files (#2870) Signed-off-by: prombot * Add mitigation information to the linux vulnerabilities collector (#2806) While the CPU vulnerabilities collector has been added in https://github.com/prometheus/node_exporter/pull/2721 , it's currently not including information regarding the mitigation strategy used for a given vulnerability. This information can be quite valuable, as often times different mitigation strategies come with a different performance impact. This commit adds a third label to the cpu_vulnerabilities_info metric, to include the "mitigation" used for a given vulnerability - if a given vulnerability is not affecting a node or the node is still vulnerable, the mitigation is expected to be empty. Signed-off-by: João Lima * Update common Prometheus files (#2872) Signed-off-by: prombot * build(deps): bump golang.org/x/crypto from 0.14.0 to 0.17.0 (#2877) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update common Prometheus files (#2879) Signed-off-by: prombot * build(deps): bump github.com/prometheus/exporter-toolkit (#2885) Bumps [github.com/prometheus/exporter-toolkit](https://github.com/prometheus/exporter-toolkit) from 0.10.0 to 0.11.0. - [Release notes](https://github.com/prometheus/exporter-toolkit/releases) - [Changelog](https://github.com/prometheus/exporter-toolkit/blob/master/CHANGELOG.md) - [Commits](https://github.com/prometheus/exporter-toolkit/compare/v0.10.0...v0.11.0) --- updated-dependencies: - dependency-name: github.com/prometheus/exporter-toolkit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/beevik/ntp from 1.3.0 to 1.3.1 (#2886) Bumps [github.com/beevik/ntp](https://github.com/beevik/ntp) from 1.3.0 to 1.3.1. - [Release notes](https://github.com/beevik/ntp/releases) - [Changelog](https://github.com/beevik/ntp/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/beevik/ntp/compare/v1.3.0...v1.3.1) --- updated-dependencies: - dependency-name: github.com/beevik/ntp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/prometheus/client_golang (#2887) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.17.0 to 1.18.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.17.0...v1.18.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update common Prometheus files (#2897) Signed-off-by: prombot * diskstats: ignore zram devices on linux systems by default (#2898) Signed-off-by: DBS-ST-VIT Co-authored-by: DBS-ST-VIT * Bump golang-builder version (#2908) Signed-off-by: Alper Polat * exec_bsd: Fix labels for vm.stats.sys.v_syscall sysctl (#2895) Signed-off-by: David O'Rourke * chore:remove constant from function (#2884) Signed-off-by: tyltr * build(deps): bump github.com/prometheus/common from 0.45.0 to 0.46.0 (#2910) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.45.0 to 0.46.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.45.0...v0.46.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/jsimonetti/rtnetlink from 1.4.0 to 1.4.1 (#2909) Bumps [github.com/jsimonetti/rtnetlink](https://github.com/jsimonetti/rtnetlink) from 1.4.0 to 1.4.1. - [Release notes](https://github.com/jsimonetti/rtnetlink/releases) - [Commits](https://github.com/jsimonetti/rtnetlink/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: github.com/jsimonetti/rtnetlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix hwmon nil ptr (#2873) * fix hwmon nil ptr syslink maybe lost in some cases. --------- Signed-off-by: TaoGe <6657718+yowenter@users.noreply.github.com> * Fix hwmon error capture (#2915) Fix golangci-lint "ineffectual assignment" by correctly capturing any errors within the hwmon gathering loop. Signed-off-by: Ben Kochie * Update common Prometheus files (#2917) Signed-off-by: prombot * Revert "Add ZFS freebsd per dataset stats (#2753)" (#2925) This reverts commit f34aaa61092fe7e3c6618fdb0b0d16a68a291ff7. Signed-off-by: Caleb Webber * filesystem: fix mountTimeout not working issue (#2903) Signed-off-by: DongWei * Fix description for NodeDiskIOSaturation alert (#2929) NodeDiskIOSaturation description should say 30m per the "for" clause Signed-off-by: Taylor Sly * Enforce no subprocess policy (#2926) Add depguard to golangci-lint to enforce the no-os/exec policy. Signed-off-by: Ben Kochie * filesystem: surface device errors (#2923) filesystem: surface filesystem device error Fixes: #2918 --------- Signed-off-by: Pamela Mei i540369 * Revert "filesystem: fix mountTimeout not working issue (#2903)" (#2932) This reverts commit 9f1f791ac2e1377781c4f8807a23d86d92ad6499. Signed-off-by: Ben Kochie * Update common Prometheus files (#2939) Signed-off-by: prombot * UPDATE base image golang version * UPDATE vulnerabilities dependencies * UPDATE dependencies --------- Signed-off-by: Ben Kochie Signed-off-by: dependabot[bot] Signed-off-by: Robin Nabel Signed-off-by: Serhii Freidin Signed-off-by: Guillaume Espanel Signed-off-by: tnextday Signed-off-by: Marcus Cobden Signed-off-by: prombot Signed-off-by: Darshil Chanpura Signed-off-by: Johannes 'fish' Ziemke Signed-off-by: Jason Culligan Signed-off-by: Jan Fajerski Signed-off-by: Daniel Swarbrick Signed-off-by: Perry Naseck Signed-off-by: Otto Sabart Signed-off-by: Haoyu Sun Signed-off-by: Manuel Stausberg Signed-off-by: Joe Groocock Signed-off-by: Simon Pasquier Signed-off-by: mchtech Signed-off-by: Yury Vidineev Signed-off-by: Ryan J. Geyer Signed-off-by: James Bach Signed-off-by: James Bach Signed-off-by: jalev Signed-off-by: Daniel Hodges Signed-off-by: Benny Siegert Signed-off-by: Jia Xin Signed-off-by: David O'Rourke Signed-off-by: LamGC Signed-off-by: Daniël van Eeden Signed-off-by: Lukas Coppens Signed-off-by: Matthias Petermann Signed-off-by: Pablo Caderno Signed-off-by: David Calvert Signed-off-by: Maximilian Wilhelm Signed-off-by: Johannes Ziemke Signed-off-by: Will Bollock Signed-off-by: Jonathan Davies Signed-off-by: Claudio Jeker Signed-off-by: cui fliter Signed-off-by: Saleh Sal <0xack13@gmail.com> Signed-off-by: Nitin Shelke Signed-off-by: dongjiang1989 Signed-off-by: jbradleynh Signed-off-by: Benoît Knecht Signed-off-by: remi Signed-off-by: Rémi Jouannet Signed-off-by: abbeywoodyear Signed-off-by: Dan Williams Signed-off-by: Johannes Dilli Signed-off-by: Erica Mays Signed-off-by: juzhao Signed-off-by: Cam Cope Signed-off-by: Vitaly Zhuravlev Signed-off-by: Michal Wasilewski Signed-off-by: Conall O'Brien Signed-off-by: Gabi Davar Signed-off-by: L <3177243+LukeLR@users.noreply.github.com> Signed-off-by: Oliver Geiselhardt-Herms Signed-off-by: John Kordich Signed-off-by: Metbog Signed-off-by: ToMe25 Signed-off-by: yang-stressfree <68363665+yang-stressfree@users.noreply.github.com> Signed-off-by: joey Signed-off-by: nemobis Signed-off-by: Ayoub Nasr Signed-off-by: fitz123 Signed-off-by: Tobias Klausmann Signed-off-by: Gavin Lam Signed-off-by: François Rigault Signed-off-by: João Lima Signed-off-by: DBS-ST-VIT Signed-off-by: Alper Polat Signed-off-by: tyltr Signed-off-by: TaoGe <6657718+yowenter@users.noreply.github.com> Signed-off-by: Caleb Webber Signed-off-by: DongWei Signed-off-by: Taylor Sly Signed-off-by: Pamela Mei i540369 Co-authored-by: Ben Kochie Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Robin Nabel Co-authored-by: sfreydin Co-authored-by: Guillaume E Co-authored-by: tnextday Co-authored-by: Marcus Cobden <52370+leth@users.noreply.github.com> Co-authored-by: PrometheusBot Co-authored-by: Darshil Chanpura Co-authored-by: Johannes 'fish' Ziemke Co-authored-by: Jason Culligan Co-authored-by: Jan Fajerski Co-authored-by: Daniel Swarbrick Co-authored-by: Perry Naseck <4472083+DaAwesomeP@users.noreply.github.com> Co-authored-by: Sabart Otto Co-authored-by: SUN Haoyu Co-authored-by: manu Co-authored-by: Joe Groocock Co-authored-by: Simon Pasquier Co-authored-by: mchtech Co-authored-by: Yury Vidineev Co-authored-by: Ryan J. Geyer Co-authored-by: James Bach Co-authored-by: James Bach Co-authored-by: Daniel Hodges Co-authored-by: Benny Siegert Co-authored-by: Jia Xin Co-authored-by: David O'Rourke Co-authored-by: Haoyu Sun Co-authored-by: LamGC Co-authored-by: Daniël van Eeden Co-authored-by: Lukas Coppens Co-authored-by: Marcus Cobden Co-authored-by: Matthias Petermann <37493510+MatthiasPetermann@users.noreply.github.com> Co-authored-by: Pablo Caderno Co-authored-by: David Calvert Co-authored-by: Maximilian Wilhelm Co-authored-by: Will Bollock Co-authored-by: Jonathan Davies Co-authored-by: Claudio Jeker Co-authored-by: cui fliter Co-authored-by: Sal Sal Co-authored-by: Nitin Shelke <58942444+nshelke777@users.noreply.github.com> Co-authored-by: dongjiang Co-authored-by: Josh Bradley <49180168+jbradleynh@users.noreply.github.com> Co-authored-by: Benoît Knecht Co-authored-by: Remi Jouannet Co-authored-by: Abbey Woodyear <81559466+abbeywoodyear@users.noreply.github.com> Co-authored-by: Dan Williams Co-authored-by: Johannes Dilli Co-authored-by: Erica Mays Co-authored-by: Junqi Zhao Co-authored-by: Cam Cope Co-authored-by: Vitaly Zhuravlev Co-authored-by: Vitaly Zhuravlev Co-authored-by: Michal Co-authored-by: Conall O'Brien Co-authored-by: Gabi Davar Co-authored-by: L <3177243+LukeLR@users.noreply.github.com> Co-authored-by: takt Co-authored-by: Oliver Geiselhardt-Herms Co-authored-by: John Kordich Co-authored-by: Metbog Co-authored-by: ToMe25 Co-authored-by: yang-stressfree <68363665+yang-stressfree@users.noreply.github.com> Co-authored-by: joey Co-authored-by: nemobis Co-authored-by: Ayoub NASR Co-authored-by: Anton Lugovoi Co-authored-by: Tobias Klausmann Co-authored-by: Gavin Lam Co-authored-by: frigo Co-authored-by: François Rigault Co-authored-by: João Pedro Lima Co-authored-by: DBS-ST-VIT <142572752+DBS-ST-VIT@users.noreply.github.com> Co-authored-by: DBS-ST-VIT Co-authored-by: Alper Polat <101826653+gitperr@users.noreply.github.com> Co-authored-by: David O'Rourke Co-authored-by: tyltr Co-authored-by: TaoGe <6657718+yowenter@users.noreply.github.com> Co-authored-by: Caleb Webber Co-authored-by: DongWei Co-authored-by: Taylor Sly Co-authored-by: Pamela Mei <126221706+PamelaMei-SAP@users.noreply.github.com> --- .circleci/config.yml | 42 +- .github/ISSUE_TEMPLATE.md | 10 +- .github/dependabot.yml | 6 + .github/workflows/golangci-lint.yml | 38 + .gitignore | 1 + .golangci.yml | 22 +- .promu-cgo.yml | 2 +- .promu.yml | 2 +- .yamllint | 8 +- CHANGELOG.md | 163 +- CODE_OF_CONDUCT.md | 4 +- Dockerfile | 2 +- Makefile | 15 +- Makefile.common | 106 +- README.md | 163 +- SECURITY.md | 2 +- VERSION | 2 +- collector/arp_linux.go | 113 +- collector/bcache_linux.go | 23 +- collector/bonding_linux.go | 9 +- collector/bonding_linux_test.go | 3 + collector/boot_time_bsd.go | 24 +- collector/boot_time_openbsd_amd64.go | 62 - collector/boot_time_solaris.go | 4 +- collector/btrfs_linux.go | 262 +++- collector/btrfs_linux_test.go | 14 +- collector/cgroups_linux.go | 73 + collector/collector.go | 48 +- collector/cpu_darwin.go | 1 + collector/cpu_linux.go | 153 +- collector/cpu_linux_test.go | 198 ++- collector/cpu_netbsd.go | 277 ++++ collector/cpu_netbsd_test.go | 44 + collector/cpu_openbsd.go | 53 +- collector/cpu_openbsd_amd64.go | 96 -- collector/cpu_solaris.go | 4 +- collector/cpu_vulnerabilities_linux.go | 69 + collector/cpufreq_common.go | 59 + collector/cpufreq_linux.go | 72 +- collector/cpufreq_solaris.go | 22 +- .../{netdev_filter.go => device_filter.go} | 12 +- ...v_filter_test.go => device_filter_test.go} | 4 +- collector/diskstats_common.go | 45 + collector/diskstats_darwin.go | 20 +- collector/diskstats_linux.go | 221 ++- collector/diskstats_linux_test.go | 73 +- collector/diskstats_openbsd.go | 23 +- collector/diskstats_openbsd_amd64.go | 19 +- collector/dmi.go | 3 +- collector/drm_linux.go | 6 +- collector/ethtool_linux.go | 182 ++- collector/ethtool_linux_test.go | 3 + collector/fibrechannel_linux.go | 6 +- collector/filefd_linux.go | 4 +- collector/filefd_linux_test.go | 3 + collector/filesystem_bsd.go | 4 +- collector/filesystem_common.go | 27 +- collector/filesystem_freebsd.go | 19 +- collector/filesystem_linux.go | 159 +- collector/filesystem_linux_test.go | 7 +- ...openbsd_amd64.go => filesystem_openbsd.go} | 10 +- collector/fixtures/e2e-64k-page-output.txt | 1380 +++++++++++++---- collector/fixtures/e2e-output.txt | 710 +++++---- collector/fixtures/ethtool/eth0/statistics | 2 + collector/fixtures/proc/cgroups | 13 + collector/fixtures/proc/diskstats | 10 +- collector/fixtures/proc/interrupts_aarch64 | 61 + collector/fixtures/proc/net/arp | 1 + collector/fixtures/proc/net/dev | 12 - collector/fixtures/proc/net/netstat | 4 +- collector/fixtures/proc/net/rpc/nfsd | 1 + collector/fixtures/proc/net/tcpstat | 3 - collector/fixtures/proc/net/xfrm_stat | 28 + collector/fixtures/proc/slabinfo | 6 + collector/fixtures/proc/softirqs | 11 + .../spl/kstat/zfs/{dbuf_stats => dbufstats} | 0 .../fixtures/proc/spl/kstat/zfs/pool2/state | 1 + .../proc/sys/kernel/seccomp/actions_avail | 1 + collector/fixtures/sys.ttar | 125 +- .../textfile/metrics_merge_different_help.out | 11 + .../metrics_merge_different_help/a.prom | 5 + .../metrics_merge_different_help/b.prom | 5 + .../textfile/metrics_merge_empty_help.out | 13 + .../textfile/metrics_merge_empty_help/a.prom | 5 + .../textfile/metrics_merge_empty_help/b.prom | 5 + .../textfile/metrics_merge_no_help.out | 13 + .../textfile/metrics_merge_no_help/a.prom | 4 + .../textfile/metrics_merge_no_help/b.prom | 4 + .../textfile/metrics_merge_same_help.out | 13 + .../textfile/metrics_merge_same_help/a.prom | 5 + .../textfile/metrics_merge_same_help/b.prom | 5 + collector/fixtures/udev.ttar | 529 +++++++ collector/helper.go | 20 +- collector/helper_test.go | 45 - collector/hwmon_linux.go | 58 +- collector/infiniband_linux.go | 4 +- collector/interrupts_linux.go | 35 +- collector/interrupts_linux_test.go | 36 +- collector/interrupts_openbsd.go | 4 +- collector/ipvs_linux.go | 2 +- collector/ipvs_linux_test.go | 12 +- collector/lnstat_linux.go | 4 +- collector/loadavg_linux.go | 4 +- collector/loadavg_linux_test.go | 3 + collector/logind_linux.go | 2 +- collector/logind_linux_test.go | 5 +- collector/meminfo.go | 4 +- collector/meminfo_darwin.go | 2 + collector/meminfo_linux_test.go | 3 + collector/meminfo_netbsd.go | 43 + collector/meminfo_numa_linux_test.go | 3 + collector/meminfo_openbsd.go | 4 +- collector/memory_bsd.go | 13 + collector/netclass_linux.go | 129 +- collector/netclass_rtnl_linux.go | 230 +++ collector/netdev_bsd.go | 10 +- collector/netdev_common.go | 96 +- collector/netdev_darwin.go | 10 +- collector/netdev_linux.go | 188 ++- collector/netdev_linux_test.go | 308 +++- collector/netdev_openbsd.go | 16 +- collector/netdev_openbsd_amd64.go | 12 +- collector/netisr_freebsd.go | 105 ++ collector/netstat_linux.go | 4 +- collector/netstat_linux_test.go | 3 + collector/nfsd_linux.go | 6 + collector/ntp.go | 10 +- collector/nvme_linux.go | 4 +- collector/os_release.go | 71 +- collector/os_release_test.go | 2 + collector/paths.go | 13 +- collector/paths_test.go | 2 +- collector/perf_linux.go | 211 ++- collector/perf_linux_test.go | 11 +- collector/powersupplyclass.go | 2 +- collector/powersupplyclass_darwin.go | 4 +- collector/processes_linux_test.go | 2 +- collector/qdisc_linux.go | 60 +- collector/rapl_linux.go | 81 +- collector/runit.go | 6 +- collector/selinux_linux.go | 78 + collector/slabinfo_linux.go | 121 ++ collector/softirq_linux.go | 68 + collector/softirqs_common.go | 50 + collector/softnet_linux.go | 64 +- collector/stat_linux.go | 31 + collector/supervisord.go | 4 +- collector/sysctl_bsd.go | 25 - collector/sysctl_linux.go | 218 +++ collector/systemd_linux.go | 139 +- collector/systemd_linux_test.go | 9 +- collector/tapestats_linux.go | 2 +- collector/tcpstat_linux.go | 135 +- collector/tcpstat_linux_test.go | 125 +- collector/textfile.go | 55 +- collector/textfile_test.go | 27 +- collector/thermal_darwin.go | 7 +- collector/thermal_zone_linux.go | 7 + collector/time.go | 32 +- collector/time_linux.go | 48 + collector/time_other.go | 25 + collector/timex.go | 5 +- collector/uname.go | 4 +- collector/uname_bsd.go | 15 +- collector/uname_linux.go | 18 +- collector/vmstat_linux.go | 2 +- collector/wifi_linux.go | 5 +- collector/xfrm.go | 228 +++ collector/xfrm_test.go | 151 ++ collector/zfs.go | 2 +- collector/zfs_freebsd.go | 29 +- collector/zfs_linux.go | 10 +- collector/zfs_linux_test.go | 11 +- collector/zfs_solaris.go | 4 +- docs/TIME.md | 2 + ...mple-16-compatibility-rules-new-to-old.yml | 2 +- docs/example-16-compatibility-rules.yml | 4 +- docs/node-mixin/README.md | 19 +- docs/node-mixin/alerts/alerts.libsonnet | 212 ++- docs/node-mixin/config.libsonnet | 39 +- docs/node-mixin/dashboards/node.libsonnet | 255 +-- docs/node-mixin/dashboards/use.libsonnet | 14 +- docs/node-mixin/jsonnetfile.json | 13 +- docs/node-mixin/lib/prom-mixin.libsonnet | 504 ++++++ end-to-end-test.sh | 50 +- examples/systemd/README.md | 2 +- examples/systemd/node_exporter.service | 3 +- examples/systemd/node_exporter.socket | 8 + go.mod | 74 +- go.sum | 641 ++------ node_exporter.go | 85 +- node_exporter_test.go | 10 +- scripts/errcheck_excludes.txt | 4 - 193 files changed, 8650 insertions(+), 3054 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/golangci-lint.yml delete mode 100644 collector/boot_time_openbsd_amd64.go create mode 100644 collector/cgroups_linux.go create mode 100644 collector/cpu_netbsd.go create mode 100644 collector/cpu_netbsd_test.go delete mode 100644 collector/cpu_openbsd_amd64.go create mode 100644 collector/cpu_vulnerabilities_linux.go create mode 100644 collector/cpufreq_common.go rename collector/{netdev_filter.go => device_filter.go} (76%) rename collector/{netdev_filter_test.go => device_filter_test.go} (92%) rename collector/{filesystem_openbsd_amd64.go => filesystem_openbsd.go} (90%) create mode 100644 collector/fixtures/proc/cgroups create mode 100644 collector/fixtures/proc/interrupts_aarch64 delete mode 100644 collector/fixtures/proc/net/dev delete mode 100644 collector/fixtures/proc/net/tcpstat create mode 100644 collector/fixtures/proc/net/xfrm_stat create mode 100644 collector/fixtures/proc/slabinfo create mode 100644 collector/fixtures/proc/softirqs rename collector/fixtures/proc/spl/kstat/zfs/{dbuf_stats => dbufstats} (100%) create mode 100644 collector/fixtures/proc/spl/kstat/zfs/pool2/state create mode 100644 collector/fixtures/proc/sys/kernel/seccomp/actions_avail create mode 100644 collector/fixtures/textfile/metrics_merge_different_help.out create mode 100644 collector/fixtures/textfile/metrics_merge_different_help/a.prom create mode 100644 collector/fixtures/textfile/metrics_merge_different_help/b.prom create mode 100644 collector/fixtures/textfile/metrics_merge_empty_help.out create mode 100644 collector/fixtures/textfile/metrics_merge_empty_help/a.prom create mode 100644 collector/fixtures/textfile/metrics_merge_empty_help/b.prom create mode 100644 collector/fixtures/textfile/metrics_merge_no_help.out create mode 100644 collector/fixtures/textfile/metrics_merge_no_help/a.prom create mode 100644 collector/fixtures/textfile/metrics_merge_no_help/b.prom create mode 100644 collector/fixtures/textfile/metrics_merge_same_help.out create mode 100644 collector/fixtures/textfile/metrics_merge_same_help/a.prom create mode 100644 collector/fixtures/textfile/metrics_merge_same_help/b.prom create mode 100644 collector/fixtures/udev.ttar create mode 100644 collector/meminfo_netbsd.go create mode 100644 collector/netclass_rtnl_linux.go create mode 100644 collector/netisr_freebsd.go create mode 100644 collector/selinux_linux.go create mode 100644 collector/slabinfo_linux.go create mode 100644 collector/softirq_linux.go create mode 100644 collector/softirqs_common.go create mode 100644 collector/sysctl_linux.go create mode 100644 collector/time_linux.go create mode 100644 collector/time_other.go create mode 100644 collector/xfrm.go create mode 100644 collector/xfrm_test.go create mode 100644 docs/node-mixin/lib/prom-mixin.libsonnet create mode 100644 examples/systemd/node_exporter.socket delete mode 100644 scripts/errcheck_excludes.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index c31a6a82c2..3715e300dc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,36 +1,33 @@ --- version: 2.1 - orbs: - prometheus: prometheus/prometheus@0.11.0 - + prometheus: prometheus/prometheus@0.17.1 executors: # Whenever the Go version is updated here, .promu.yml and .promu-cgo.yml # should also be updated. golang: docker: - - image: circleci/golang:1.17 + - image: cimg/go:1.21 + arm: + machine: + image: ubuntu-2204:current + resource_class: arm.medium jobs: test: executor: golang - steps: - prometheus/setup_environment - run: go mod download - run: make - prometheus/store_artifact: file: node_exporter - - codespell: - docker: - - image: circleci/python - + test-arm: + executor: arm steps: - checkout - - run: sudo pip install codespell - - run: codespell --skip=".git,./vendor,ttar,go.mod,go.sum,*pem,./collector/fixtures" -L uint,packages\',uptodate - + - run: uname -a + - run: make test-e2e test_mixins: executor: golang steps: @@ -43,16 +40,13 @@ jobs: - run: make -C docs/node-mixin jb_install - run: make -C docs/node-mixin - run: git diff --exit-code - build: machine: - image: ubuntu-2004:202101-01 - + image: ubuntu-2204:current parallelism: 3 - steps: - prometheus/setup_environment - - run: docker run --privileged linuxkit/binfmt:v0.8 + - run: docker run --privileged linuxkit/binfmt:af88a591f9cc896a52ce596b9cf7ca26a061ef97 - run: promu crossbuild -v --parallelism $CIRCLE_NODE_TOTAL --parallelism-thread $CIRCLE_NODE_INDEX - run: promu --config .promu-cgo.yml crossbuild -v --parallelism $CIRCLE_NODE_TOTAL --parallelism-thread $CIRCLE_NODE_INDEX - persist_to_workspace: @@ -62,15 +56,12 @@ jobs: - store_artifacts: path: .build destination: /build - test_docker: machine: - image: ubuntu-2004:202101-01 - + image: ubuntu-2204:current environment: - DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.16-base + DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.21-base REPO_PATH: github.com/prometheus/node_exporter - steps: - prometheus/setup_environment - attach_workspace: @@ -91,7 +82,6 @@ jobs: else make test-docker fi - workflows: version: 2 node_exporter: @@ -100,11 +90,11 @@ workflows: filters: tags: only: /.*/ - - build: + - test-arm: filters: tags: only: /.*/ - - codespell: + - build: filters: tags: only: /.*/ diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index c76c887bf9..ff07009480 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,14 +1,12 @@ +### node_exporter log output + ### Are you running node_exporter in Docker? diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..202ae2366a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000000..0e8515722f --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,38 @@ +--- +# This action is synced from https://github.com/prometheus/prometheus +name: golangci-lint +on: + push: + paths: + - "go.sum" + - "go.mod" + - "**.go" + - "scripts/errcheck_excludes.txt" + - ".github/workflows/golangci-lint.yml" + - ".golangci.yml" + pull_request: + +permissions: # added using https://github.com/step-security/secure-repo + contents: read + +jobs: + golangci: + permissions: + contents: read # for actions/checkout to fetch code + pull-requests: read # for golangci/golangci-lint-action to fetch pull requests + name: lint + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: install Go + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version: 1.22.x + - name: Install snmp_exporter/generator dependencies + run: sudo apt-get update && sudo apt-get -y install libsnmp-dev + if: github.repository == 'prometheus/snmp_exporter' + - name: Lint + uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 + with: + version: v1.55.2 diff --git a/.gitignore b/.gitignore index 8fb3d18214..fcfd9727be 100644 --- a/.gitignore +++ b/.gitignore @@ -34,5 +34,6 @@ dependencies-stamp # Test files extracted from ttar collector/fixtures/sys/ +collector/fixtures/udev/ /vendor diff --git a/.golangci.yml b/.golangci.yml index 0412d93b82..472b3a5e13 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,7 @@ linters: enable: + - depguard + - misspell - revive disable: # Disable soon to deprecated[1] linters that lead to false @@ -18,5 +20,23 @@ issues: - errcheck linters-settings: + depguard: + rules: + no_exec_policy: + files: + - "!$test" + deny: + - pkg: "os/exec" + desc: "Using os/exec to run sub processes it not allowed by policy" errcheck: - exclude: scripts/errcheck_excludes.txt + exclude-functions: + # Used in HTTP handlers, any error is handled by the server itself. + - (net/http.ResponseWriter).Write + # Never check for logger errors. + - (github.com/go-kit/log.Logger).Log + revive: + rules: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter + - name: unused-parameter + severity: warning + disabled: true diff --git a/.promu-cgo.yml b/.promu-cgo.yml index 7179a566d7..d6f825299e 100644 --- a/.promu-cgo.yml +++ b/.promu-cgo.yml @@ -1,7 +1,7 @@ go: # Whenever the Go version is updated here, .circle/config.yml and # .promu.yml should also be updated. - version: 1.17 + version: 1.21 cgo: true repository: path: github.com/prometheus/node_exporter diff --git a/.promu.yml b/.promu.yml index 373000dd74..d0a66635f2 100644 --- a/.promu.yml +++ b/.promu.yml @@ -1,7 +1,7 @@ go: # Whenever the Go version is updated here, .circle/config.yml and # .promu-cgo.yml should also be updated. - version: 1.17 + version: 1.21 repository: path: github.com/prometheus/node_exporter build: diff --git a/.yamllint b/.yamllint index 281c946463..955a5a6270 100644 --- a/.yamllint +++ b/.yamllint @@ -14,14 +14,10 @@ rules: document-start: disable indentation: spaces: consistent + indent-sequences: consistent key-duplicates: ignore: | config/testdata/section_key_dup.bad.yml line-length: disable truthy: - ignore: | - .github/workflows/codeql-analysis.yml - .github/workflows/funcbench.yml - .github/workflows/fuzzing.yml - .github/workflows/prombench.yml - .github/workflows/golangci-lint.yml + check-keys: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e8b2f8f3..096c0b1024 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,160 @@ * [ENHANCEMENT] * [BUGFIX] +## 1.7.0 / 2023-11-11 + +* [FEATURE] Add ZFS freebsd per dataset stats #2753 +* [FEATURE] Add cpu vulnerabilities reporting from sysfs #2721 +* [ENHANCEMENT] Parallelize stat calls in Linux filesystem collector #1772 +* [ENHANCEMENT] Add missing linkspeeds to ethtool collector 2711 +* [ENHANCEMENT] Add CPU MHz as the value for `node_cpu_info` metric #2778 +* [ENHANCEMENT] Improve qdisc collector performance #2779 +* [ENHANCEMENT] Add include and exclude filter for hwmon collector #2699 +* [ENHANCEMENT] Optionally fetch ARP stats via rtnetlink instead of procfs #2777 +* [BUFFIX] Fix ZFS arcstats on FreeBSD 14.0+ 2754 +* [BUGFIX] Fallback to 32-bit stats in netdev #2757 +* [BUGFIX] Close btrfs.FS handle after use #2780 +* [BUGFIX] Move RO status before error return #2807 +* [BUFFIX] Fix `promhttp_metric_handler_errors_total` being always active #2808 +* [BUGFIX] Fix nfsd v4 index miss #2824 + +## 1.6.1 / 2023-06-17 + +Rebuild with latest Go compiler bugfix release. + +## 1.6.0 / 2023-05-27 + +* [CHANGE] Fix cpustat when some cpus are offline #2318 +* [CHANGE] Remove metrics of offline CPUs in CPU collector #2605 +* [CHANGE] Deprecate ntp collector #2603 +* [CHANGE] Remove bcache `cache_readaheads_totals` metrics #2583 +* [CHANGE] Deprecate supervisord collector #2685 +* [FEATURE] Enable uname collector on NetBSD #2559 +* [FEATURE] NetBSD support for the meminfo collector #2570 +* [FEATURE] NetBSD support for CPU collector #2626 +* [FEATURE] Add FreeBSD collector for netisr subsystem #2668 +* [FEATURE] Add softirqs collector #2669 +* [ENHANCEMENT] Add suspended as a `node_zfs_zpool_state` #2449 +* [ENHANCEMENT] Add administrative state of Linux network interfaces #2515 +* [ENHANCEMENT] Log current value of GOMAXPROCS #2537 +* [ENHANCEMENT] Add profiler options for perf collector #2542 +* [ENHANCEMENT] Allow root path as metrics path #2590 +* [ENHANCEMENT] Add cpu frequency governor metrics #2569 +* [ENHANCEMENT] Add new landing page #2622 +* [ENHANCEMENT] Reduce privileges needed for btrfs device stats #2634 +* [ENHANCEMENT] Add ZFS `memory_available_bytes` #2687 +* [ENHANCEMENT] Use `SCSI_IDENT_SERIAL` as serial in diskstats #2612 +* [ENHANCEMENT] Read missing from netlink netclass attributes from sysfs #2669 +* [BUGFIX] perf: fixes for automatically detecting the correct tracefs mountpoints #2553 +* [BUGFIX] Fix `thermal_zone` collector noise #2554 +* [BUGFIX] Fix a problem fetching the user wire count on FreeBSD #2584 +* [BUGFIX] interrupts: Fix fields on linux aarch64 #2631 +* [BUGFIX] Remove metrics of offline CPUs in CPU collector #2605 +* [BUGFIX] Fix OpenBSD filesystem collector string parsing #2637 +* [BUGFIX] Fix bad reporting of `node_cpu_seconds_total` in OpenBSD #2663 + +## 1.5.0 / 2022-11-29 + +NOTE: This changes the Go runtime "GOMAXPROCS" to 1. This is done to limit the + concurrency of the exporter to 1 CPU thread at a time in order to avoid a + race condition problem in the Linux kernel (#2500) and parallel IO issues + on nodes with high numbers of CPUs/CPU threads (#1880). + +NOTE: A command line arg has been changed from `--web.config` to `--web.config.file`. + +* [CHANGE] Default GOMAXPROCS to 1 #2530 +* [FEATURE] Add multiple listeners and systemd socket listener activation #2393 +* [ENHANCEMENT] Add RTNL version of netclass collector #2492, #2528 +* [BUGFIX] Fix diskstats exclude flags #2487 +* [BUGFIX] Bump go/x/crypt and go/x/net #2488 +* [BUGFIX] Fix hwmon label sanitizer #2504 +* [BUGFIX] Use native endianness when encoding InetDiagMsg #2508 +* [BUGFIX] Fix btrfs device stats always being zero #2516 +* [BUGFIX] Security: Update exporter-toolkit (CVE-2022-46146) #2531 + +## 1.4.1 / 2022-11-29 + +* [BUGFIX] Fix diskstats exclude flags #2487 +* [BUGFIX] Security: Update go/x/crypto and go/x/net (CVE-2022-27191 CVE-2022-27664) #2488 +* [BUGFIX] Security: Update exporter-toolkit (CVE-2022-46146) #2531 + +## 1.4.0 / 2022-09-24 + +* [CHANGE] Merge metrics descriptions in textfile collector #2475 +* [FEATURE] [node-mixin] Add darwin dashboard to mixin #2351 +* [FEATURE] Add "isolated" metric on cpu collector on linux #2251 +* [FEATURE] Add cgroup summary collector #2408 +* [FEATURE] Add selinux collector #2205 +* [FEATURE] Add slab info collector #2376 +* [FEATURE] Add sysctl collector #2425 +* [FEATURE] Also track the CPU Spin time for OpenBSD systems #1971 +* [FEATURE] Add support for MacOS version #2471 +* [ENHANCEMENT] [node-mixin] Add missing selectors #2426 +* [ENHANCEMENT] [node-mixin] Change current datasource to grafana's default #2281 +* [ENHANCEMENT] [node-mixin] Change disk graph to disk table #2364 +* [ENHANCEMENT] [node-mixin] Change io time units to %util #2375 +* [ENHANCEMENT] Ad user_wired_bytes and laundry_bytes on *bsd #2266 +* [ENHANCEMENT] Add additional vm_stat memory metrics for darwin #2240 +* [ENHANCEMENT] Add device filter flags to arp collector #2254 +* [ENHANCEMENT] Add diskstats include and exclude device flags #2417 +* [ENHANCEMENT] Add node_softirqs_total metric #2221 +* [ENHANCEMENT] Add rapl zone name label option #2401 +* [ENHANCEMENT] Add slabinfo collector #1799 +* [ENHANCEMENT] Allow user to select port on NTP server to query #2270 +* [ENHANCEMENT] collector/diskstats: Add labels and metrics from udev #2404 +* [ENHANCEMENT] Enable builds against older macOS SDK #2327 +* [ENHANCEMENT] qdisk-linux: Add exclude and include flags for interface name #2432 +* [ENHANCEMENT] systemd: Expose systemd minor version #2282 +* [ENHANCEMENT] Use netlink for tcpstat collector #2322 +* [ENHANCEMENT] Use netlink to get netdev stats #2074 +* [ENHANCEMENT] Add additional perf counters for stalled frontend/backend cycles #2191 +* [ENHANCEMENT] Add btrfs device error stats #2193 +* [BUGFIX] [node-mixin] Fix fsSpaceAvailableCriticalThreshold and fsSpaceAvailableWarning #2352 +* [BUGFIX] Fix concurrency issue in ethtool collector #2289 +* [BUGFIX] Fix concurrency issue in netdev collector #2267 +* [BUGFIX] Fix diskstat reads and write metrics for disks with different sector sizes #2311 +* [BUGFIX] Fix iostat on macos broken by deprecation warning #2292 +* [BUGFIX] Fix NodeFileDescriptorLimit alerts #2340 +* [BUGFIX] Sanitize rapl zone names #2299 +* [BUGFIX] Add file descriptor close safely in test #2447 +* [BUGFIX] Fix race condition in os_release.go #2454 +* [BUGFIX] Skip ZFS IO metrics if their paths are missing #2451 + +## 1.3.1 / 2021-12-01 + +* [BUGFIX] Handle nil CPU thermal power status on M1 #2218 +* [BUGFIX] bsd: Ignore filesystems flagged as MNT_IGNORE. #2227 +* [BUGFIX] Sanitize UTF-8 in dmi collector #2229 + +## 1.3.0 / 2021-10-20 + +NOTE: In order to support globs in the textfile collector path, filenames exposed by + `node_textfile_mtime_seconds` now contain the full path name. + +* [CHANGE] Add path label to rapl collector #2146 +* [CHANGE] Exclude filesystems under /run/credentials #2157 +* [CHANGE] Add TCPTimeouts to netstat default filter #2189 +* [FEATURE] Add lnstat collector for metrics from /proc/net/stat/ #1771 +* [FEATURE] Add darwin powersupply collector #1777 +* [FEATURE] Add support for monitoring GPUs on Linux #1998 +* [FEATURE] Add Darwin thermal collector #2032 +* [FEATURE] Add os release collector #2094 +* [FEATURE] Add netdev.address-info collector #2105 +* [FEATURE] Add clocksource metrics to time collector #2197 +* [ENHANCEMENT] Support glob textfile collector directories #1985 +* [ENHANCEMENT] ethtool: Expose node_ethtool_info metric #2080 +* [ENHANCEMENT] Use include/exclude flags for ethtool filtering #2165 * [ENHANCEMENT] Add flag to disable guest CPU metrics #2123 -* [ENHANCEMENT] Add DMI collector #303 +* [ENHANCEMENT] Add DMI collector #2131 +* [ENHANCEMENT] Add threads metrics to processes collector #2164 +* [ENHANCEMENT] Reduce timer GC delays in the Linux filesystem collector #2169 +* [ENHANCEMENT] Add TCPTimeouts to netstat default filter #2189 +* [ENHANCEMENT] Use SysctlTimeval for boottime collector on BSD #2208 +* [BUGFIX] ethtool: Sanitize metric names #2093 +* [BUGFIX] Fix ethtool collector for multiple interfaces #2126 * [BUGFIX] Fix possible panic on macOS #2133 +* [BUGFIX] Collect flag_info and bug_info only for one core #2156 +* [BUGFIX] Prevent duplicate ethtool metric names #2187 ## 1.2.2 / 2021-08-06 @@ -40,7 +191,7 @@ NOTE: Filesystem collector flags have been renamed. `--collector.filesystem.igno * [BUGFIX] Fix wrong value for OpenBSD memory buffer cache #2015 * [BUGFIX] Only initiate collectors once #2048 * [BUGFIX] Handle small backwards jumps in CPU idle #2067 - + ## 1.1.2 / 2021-03-05 * [BUGFIX] Handle errors from disabled PSI subsystem #1983 @@ -287,7 +438,7 @@ Other breaking changes: * [CHANGE] Greatly reduce the metrics vmstat returns by default. #874 * [CHANGE] Greatly trim what netstat collector exposes by default #876 * [CHANGE] Drop `exec_` prefix and move `node_boot_time_seconds` from `exec` to new `boottime` collector and enable for Darwin/Dragonfly/FreeBSD/NetBSD/OpenBSD. #839, #901 -* [CHANGE] Remove depreated gmond collector #852 +* [CHANGE] Remove deprecated gmond collector #852 * [CHANGE] align Darwin disk stat names with Linux #930 * [FEATURE] Add `collect[]` parameter #699 * [FEATURE] Add text collector conversion for ipmitool output. #746 @@ -332,7 +483,7 @@ Other breaking changes: **Breaking changes** This release contains major breaking changes to flag handling. -* The flag library has been changed, all flags now require double-dashs. (`-foo` becomes `--foo`). +* The flag library has been changed, all flags now require double-dashes. (`-foo` becomes `--foo`). * The collector selection flag has been replaced by individual boolean flags. * The `-collector.procfs` and `-collector.sysfs` flags have been renamed to `--path.procfs` and `--path.sysfs` respectively. @@ -348,14 +499,14 @@ Windows support is now removed, the [wmi_exporter](https://github.com/martinlind * [CHANGE] Switch to kingpin flags #639 * [CHANGE] Replace --collectors.enabled with per-collector flags #640 * [FEATURE] Add ARP collector for Linux #540 -* [FEATURE] Add XFS colector for Linux #568, #575 +* [FEATURE] Add XFS collector for Linux #568, #575 * [FEATURE] Add qdisc collector for Linux #580 * [FEATURE] Add cpufreq stats for Linux #548 * [FEATURE] Add diskstats for Darwin #593 * [FEATURE] Add bcache collector for Linux #597 * [FEATURE] Add parsing /proc/net/snmp6 file for Linux #615 * [FEATURE] Add timex collector for Linux #664 -* [ENHANCEMENT] Include overal health status in smartmon.sh example script #546 +* [ENHANCEMENT] Include overall health status in smartmon.sh example script #546 * [ENHANCEMENT] Include `guest_nice` in CPU collector #554 * [ENHANCEMENT] Add exec_boot_time for freebsd, dragonfly #550 * [ENHANCEMENT] Get full resolution for node_time #555 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 9a1aff4127..d325872bdf 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ -## Prometheus Community Code of Conduct +# Prometheus Community Code of Conduct -Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). +Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). diff --git a/Dockerfile b/Dockerfile index d2a3867940..2452c1349d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.0 as builder +FROM golang:1.20.0 as builder WORKDIR /go/src/github.com/prometheus/node_exporter diff --git a/Makefile b/Makefile index e72dea5dff..0edd9a125a 100644 --- a/Makefile +++ b/Makefile @@ -60,12 +60,13 @@ endif PROMU := $(FIRST_GOPATH)/bin/promu --config $(PROMU_CONF) +e2e-out-64k-page = collector/fixtures/e2e-64k-page-output.txt e2e-out = collector/fixtures/e2e-output.txt ifeq ($(MACH), ppc64le) - e2e-out = collector/fixtures/e2e-64k-page-output.txt + e2e-out = $(e2e-out-64k-page) endif ifeq ($(MACH), aarch64) - e2e-out = collector/fixtures/e2e-64k-page-output.txt + e2e-out = $(e2e-out-64k-page) endif # 64bit -> 32bit mapping for cross-checking. At least for amd64/386, the 64bit CPU can execute 32bit code but not the other way around, so we don't support cross-testing upwards. @@ -87,12 +88,12 @@ $(eval $(call goarch_pair,mips64el,mipsel)) all:: vet checkmetrics checkrules common-all $(cross-test) $(test-e2e) .PHONY: test -test: collector/fixtures/sys/.unpacked +test: collector/fixtures/sys/.unpacked collector/fixtures/udev/.unpacked @echo ">> running tests" $(GO) test -short $(test-flags) $(pkgs) .PHONY: test-32bit -test-32bit: collector/fixtures/sys/.unpacked +test-32bit: collector/fixtures/sys/.unpacked collector/fixtures/udev/.unpacked @echo ">> running tests in 32-bit mode" @env GOARCH=$(GOARCH_CROSS) $(GO) test $(pkgs) @@ -109,9 +110,12 @@ skip-test-32bit: update_fixtures: rm -vf collector/fixtures/sys/.unpacked ./ttar -C collector/fixtures -c -f collector/fixtures/sys.ttar sys + rm -vf collector/fixtures/udev/.unpacked + ./ttar -C collector/fixtures -c -f collector/fixtures/udev.ttar udev + .PHONY: test-e2e -test-e2e: build collector/fixtures/sys/.unpacked +test-e2e: build collector/fixtures/sys/.unpacked collector/fixtures/udev/.unpacked @echo ">> running end-to-end tests" ./end-to-end-test.sh @@ -123,6 +127,7 @@ skip-test-e2e: checkmetrics: $(PROMTOOL) @echo ">> checking metrics for correctness" ./checkmetrics.sh $(PROMTOOL) $(e2e-out) + ./checkmetrics.sh $(PROMTOOL) $(e2e-out-64k-page) .PHONY: checkrules checkrules: $(PROMTOOL) diff --git a/Makefile.common b/Makefile.common index ed7d1826e4..5fd1782371 100644 --- a/Makefile.common +++ b/Makefile.common @@ -36,29 +36,6 @@ GO_VERSION ?= $(shell $(GO) version) GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') -GOVENDOR := -GO111MODULE := -ifeq (, $(PRE_GO_111)) - ifneq (,$(wildcard go.mod)) - # Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI). - GO111MODULE := on - - ifneq (,$(wildcard vendor)) - # Always use the local vendor/ directory to satisfy the dependencies. - GOOPTS := $(GOOPTS) -mod=vendor - endif - endif -else - ifneq (,$(wildcard go.mod)) - ifneq (,$(wildcard vendor)) -$(warning This repository requires Go >= 1.11 because of Go modules) -$(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)') - endif - else - # This repository isn't using Go modules (yet). - GOVENDOR := $(FIRST_GOPATH)/bin/govendor - endif -endif PROMU := $(FIRST_GOPATH)/bin/promu pkgs = ./... @@ -72,25 +49,28 @@ endif GOTEST := $(GO) test GOTEST_DIR := ifneq ($(CIRCLE_JOB),) -ifneq ($(shell which gotestsum),) +ifneq ($(shell command -v gotestsum > /dev/null),) GOTEST_DIR := test-results GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml -- endif endif -PROMU_VERSION ?= 0.12.0 +PROMU_VERSION ?= 0.15.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz +SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.42.0 -# golangci-lint only supports linux, darwin and windows platforms on i386/amd64. +GOLANGCI_LINT_VERSION ?= v1.55.2 +# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) - ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386)) + ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386 arm64)) # If we're in CI and there is an Actions file, that means the linter # is being run in Actions, so we don't need to run it here. - ifeq (,$(CIRCLE_JOB)) + ifneq (,$(SKIP_GOLANGCI_LINT)) + GOLANGCI_LINT := + else ifeq (,$(CIRCLE_JOB)) GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint else ifeq (,$(wildcard .github/workflows/golangci-lint.yml)) GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint @@ -111,6 +91,8 @@ BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS)) PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS)) TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS)) +SANITIZED_DOCKER_IMAGE_TAG := $(subst +,-,$(DOCKER_IMAGE_TAG)) + ifeq ($(GOHOSTARCH),amd64) ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows)) # Only supported on amd64 @@ -150,11 +132,7 @@ common-check_license: .PHONY: common-deps common-deps: @echo ">> getting dependencies" -ifdef GO111MODULE - GO111MODULE=$(GO111MODULE) $(GO) mod download -else - $(GO) get $(GOOPTS) -t ./... -endif + $(GO) mod download .PHONY: update-go-deps update-go-deps: @@ -162,20 +140,17 @@ update-go-deps: @for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ $(GO) get -d $$m; \ done - GO111MODULE=$(GO111MODULE) $(GO) mod tidy -ifneq (,$(wildcard vendor)) - GO111MODULE=$(GO111MODULE) $(GO) mod vendor -endif + $(GO) mod tidy .PHONY: common-test-short common-test-short: $(GOTEST_DIR) @echo ">> running short tests" - GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs) + $(GOTEST) -short $(GOOPTS) $(pkgs) .PHONY: common-test common-test: $(GOTEST_DIR) @echo ">> running all tests" - GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) + $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) $(GOTEST_DIR): @mkdir -p $@ @@ -183,31 +158,27 @@ $(GOTEST_DIR): .PHONY: common-format common-format: @echo ">> formatting code" - GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) + $(GO) fmt $(pkgs) .PHONY: common-vet common-vet: @echo ">> vetting code" - GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs) + $(GO) vet $(GOOPTS) $(pkgs) .PHONY: common-lint common-lint: $(GOLANGCI_LINT) ifdef GOLANGCI_LINT @echo ">> running golangci-lint" -ifdef GO111MODULE # 'go list' needs to be executed before staticcheck to prepopulate the modules cache. # Otherwise staticcheck might fail randomly for some reason not yet explained. - GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null - GO111MODULE=$(GO111MODULE) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) -else - $(GOLANGCI_LINT) run $(pkgs) -endif + $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null + $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) endif .PHONY: common-yamllint common-yamllint: @echo ">> running yamllint on all YAML files in the repository" -ifeq (, $(shell which yamllint)) +ifeq (, $(shell command -v yamllint > /dev/null)) @echo "yamllint not installed so skipping" else yamllint . @@ -218,28 +189,15 @@ endif common-staticcheck: lint .PHONY: common-unused -common-unused: $(GOVENDOR) -ifdef GOVENDOR - @echo ">> running check for unused packages" - @$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages' -else -ifdef GO111MODULE +common-unused: @echo ">> running check for unused/missing packages in go.mod" - GO111MODULE=$(GO111MODULE) $(GO) mod tidy -ifeq (,$(wildcard vendor)) + $(GO) mod tidy @git diff --exit-code -- go.sum go.mod -else - @echo ">> running check for unused packages in vendor/" - GO111MODULE=$(GO111MODULE) $(GO) mod vendor - @git diff --exit-code -- go.sum go.mod vendor/ -endif -endif -endif .PHONY: common-build common-build: promu @echo ">> building binaries" - GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) + $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) .PHONY: common-tarball common-tarball: promu @@ -249,7 +207,7 @@ common-tarball: promu .PHONY: common-docker $(BUILD_DOCKER_ARCHS) common-docker: $(BUILD_DOCKER_ARCHS) $(BUILD_DOCKER_ARCHS): common-docker-%: - docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \ + docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \ -f $(DOCKERFILE_PATH) \ --build-arg ARCH="$*" \ --build-arg OS="linux" \ @@ -258,19 +216,19 @@ $(BUILD_DOCKER_ARCHS): common-docker-%: .PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS) common-docker-publish: $(PUBLISH_DOCKER_ARCHS) $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%: - docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" + docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION))) .PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS) common-docker-tag-latest: $(TAG_DOCKER_ARCHS) $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%: - docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" - docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" .PHONY: common-docker-manifest common-docker-manifest: - DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(DOCKER_IMAGE_TAG)) - DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(SANITIZED_DOCKER_IMAGE_TAG)) + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" .PHONY: promu promu: $(PROMU) @@ -295,12 +253,6 @@ $(GOLANGCI_LINT): | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) endif -ifdef GOVENDOR -.PHONY: $(GOVENDOR) -$(GOVENDOR): - GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor -endif - .PHONY: precheck precheck:: diff --git a/README.md b/README.md index 594941b522..87b4e4ba01 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ in Go with pluggable metric collectors. The [Windows exporter](https://github.com/prometheus-community/windows_exporter) is recommended for Windows users. To expose NVIDIA GPU metrics, [prometheus-dcgm -](https://github.com/NVIDIA/gpu-monitoring-tools#dcgm-exporter) +](https://github.com/NVIDIA/dcgm-exporter) can be used. ## Installation and Usage @@ -22,18 +22,14 @@ The `node_exporter` listens on HTTP port 9100 by default. See the `--help` outpu ### Ansible -For automated installs with [Ansible](https://www.ansible.com/), there is the [Cloud Alchemy role](https://github.com/cloudalchemy/ansible-node-exporter). - -### RHEL/CentOS/Fedora - -There is a [community-supplied COPR repository](https://copr.fedorainfracloud.org/coprs/ibotty/prometheus-exporters/) which closely follows upstream releases. +For automated installs with [Ansible](https://www.ansible.com/), there is the [Prometheus Community role](https://github.com/prometheus-community/ansible). ### Docker -The `node_exporter` is designed to monitor the host system. It's not recommended -to deploy it as a Docker container because it requires access to the host system. +The `node_exporter` is designed to monitor the host system. Deploying in containers requires +extra care in order to avoid monitoring the container itself. -For situations where Docker deployment is needed, some extra flags must be used to allow +For situations where containerized deployment is needed, some extra flags must be used to allow the `node_exporter` access to the host namespaces. Be aware that any non-root mount points you want to monitor will need to be bind-mounted @@ -83,6 +79,34 @@ Collectors are enabled by providing a `--collector.` flag. Collectors that are enabled by default can be disabled by providing a `--no-collector.` flag. To enable only some specific collector(s), use `--collector.disable-defaults --collector. ...`. +### Include & Exclude flags + +A few collectors can be configured to include or exclude certain patterns using dedicated flags. The exclude flags are used to indicate "all except", while the include flags are used to say "none except". Note that these flags are mutually exclusive on collectors that support both. + +Example: + +```txt +--collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/.+)($|/) +``` + +List: + +Collector | Scope | Include Flag | Exclude Flag +--- | --- | --- | --- +arp | device | --collector.arp.device-include | --collector.arp.device-exclude +cpu | bugs | --collector.cpu.info.bugs-include | N/A +cpu | flags | --collector.cpu.info.flags-include | N/A +diskstats | device | --collector.diskstats.device-include | --collector.diskstats.device-exclude +ethtool | device | --collector.ethtool.device-include | --collector.ethtool.device-exclude +ethtool | metrics | --collector.ethtool.metrics-include | N/A +filesystem | fs-types | N/A | --collector.filesystem.fs-types-exclude +filesystem | mount-points | N/A | --collector.filesystem.mount-points-exclude +hwmon | chip | --collector.hwmon.chip-include | --collector.hwmon.chip-exclude +netdev | device | --collector.netdev.device-include | --collector.netdev.device-exclude +qdisk | device | --collector.qdisk.device-include | --collector.qdisk.device-exclude +sysctl | all | --collector.sysctl.include | N/A +systemd | unit | --collector.systemd.unit-include | --collector.systemd.unit-exclude + ### Enabled by default Name | Description | OS @@ -106,12 +130,12 @@ filesystem | Exposes filesystem statistics, such as disk space used. | Darwin, D hwmon | Expose hardware monitoring and sensor data from `/sys/class/hwmon/`. | Linux infiniband | Exposes network statistics specific to InfiniBand and Intel OmniPath configurations. | Linux ipvs | Exposes IPVS status from `/proc/net/ip_vs` and stats from `/proc/net/ip_vs_stats`. | Linux -lnstat | Exposes stats from `/proc/net/stat/`. | Linux loadavg | Exposes load average. | Darwin, Dragonfly, FreeBSD, Linux, NetBSD, OpenBSD, Solaris mdadm | Exposes statistics about devices in `/proc/mdstat` (does nothing if no `/proc/mdstat` present). | Linux meminfo | Exposes memory statistics. | Darwin, Dragonfly, FreeBSD, Linux, OpenBSD netclass | Exposes network interface info from `/sys/class/net/` | Linux netdev | Exposes network interface statistics such as bytes transferred. | Darwin, Dragonfly, FreeBSD, Linux, OpenBSD +netisr | Exposes netisr statistics | FreeBSD netstat | Exposes network statistics from `/proc/net/netstat`. This is the same information as `netstat -s`. | Linux nfs | Exposes NFS client statistics from `/proc/net/rpc/nfs`. This is the same information as `nfsstat -c`. | Linux nfsd | Exposes NFS kernel server statistics from `/proc/net/rpc/nfsd`. This is the same information as `nfsstat -s`. | Linux @@ -121,6 +145,7 @@ powersupplyclass | Exposes Power Supply statistics from `/sys/class/power_supply pressure | Exposes pressure stall statistics from `/proc/pressure/`. | Linux (kernel 4.20+ and/or [CONFIG\_PSI](https://www.kernel.org/doc/html/latest/accounting/psi.html)) rapl | Exposes various statistics from `/sys/class/powercap`. | Linux schedstat | Exposes task scheduler statistics from `/proc/schedstat`. | Linux +selinux | Exposes SELinux statistics. | Linux sockstat | Exposes various statistics from `/proc/net/sockstat`. | Linux softnet | Exposes statistics from `/proc/net/softnet_stat`. | Linux stat | Exposes various statistics from `/proc/stat`. This includes boot time, forks and interrupts. | Linux @@ -134,7 +159,7 @@ udp_queues | Exposes UDP total lengths of the rx_queue and tx_queue from `/proc/ uname | Exposes system information as provided by the uname system call. | Darwin, FreeBSD, Linux, OpenBSD vmstat | Exposes statistics from `/proc/vmstat`. | Linux xfs | Exposes XFS runtime statistics. | Linux (kernel 4.4+) -zfs | Exposes [ZFS](http://open-zfs.org/) performance statistics. | [Linux](http://zfsonlinux.org/), Solaris +zfs | Exposes [ZFS](http://open-zfs.org/) performance statistics. | FreeBSD, [Linux](http://zfsonlinux.org/), Solaris ### Disabled by default @@ -155,6 +180,46 @@ and does not time out. In addition, monitor the `scrape_samples_post_metric_relabeling` metric to see the changes in cardinality. +Name | Description | OS +---------|-------------|---- +buddyinfo | Exposes statistics of memory fragments as reported by /proc/buddyinfo. | Linux +cgroups | A summary of the number of active and enabled cgroups | Linux +cpu\_vulnerabilities | Exposes CPU vulnerability information from sysfs. | Linux +devstat | Exposes device statistics | Dragonfly, FreeBSD +drm | Expose GPU metrics using sysfs / DRM, `amdgpu` is the only driver which exposes this information through DRM | Linux +drbd | Exposes Distributed Replicated Block Device statistics (to version 8.4) | Linux +ethtool | Exposes network interface information and network driver statistics equivalent to `ethtool`, `ethtool -S`, and `ethtool -i`. | Linux +interrupts | Exposes detailed interrupts statistics. | Linux, OpenBSD +ksmd | Exposes kernel and system statistics from `/sys/kernel/mm/ksm`. | Linux +lnstat | Exposes stats from `/proc/net/stat/`. | Linux +logind | Exposes session counts from [logind](http://www.freedesktop.org/wiki/Software/systemd/logind/). | Linux +meminfo\_numa | Exposes memory statistics from `/sys/devices/system/node/node[0-9]*/meminfo`, `/sys/devices/system/node/node[0-9]*/numastat`. | Linux +mountstats | Exposes filesystem statistics from `/proc/self/mountstats`. Exposes detailed NFS client statistics. | Linux +network_route | Exposes the routing table as metrics | Linux +perf | Exposes perf based metrics (Warning: Metrics are dependent on kernel configuration and settings). | Linux +processes | Exposes aggregate process statistics from `/proc`. | Linux +qdisc | Exposes [queuing discipline](https://en.wikipedia.org/wiki/Network_scheduler#Linux_kernel) statistics | Linux +slabinfo | Exposes slab statistics from `/proc/slabinfo`. Note that permission of `/proc/slabinfo` is usually 0400, so set it appropriately. | Linux +softirqs | Exposes detailed softirq statistics from `/proc/softirqs`. | Linux +sysctl | Expose sysctl values from `/proc/sys`. Use `--collector.sysctl.include(-info)` to configure. | Linux +systemd | Exposes service and system status from [systemd](http://www.freedesktop.org/wiki/Software/systemd/). | Linux +tcpstat | Exposes TCP connection status information from `/proc/net/tcp` and `/proc/net/tcp6`. (Warning: the current version has potential performance issues in high load situations.) | Linux +wifi | Exposes WiFi device and station statistics. | Linux +xfrm | Exposes statistics from `/proc/net/xfrm_stat` | Linux +zoneinfo | Exposes NUMA memory zone metrics. | Linux + +### Deprecated + +These collectors are deprecated and will be removed in the next major release. + +Name | Description | OS +---------|-------------|---- +ntp | Exposes local NTP daemon health to check [time](./docs/TIME.md) | _any_ +runit | Exposes service status from [runit](http://smarden.org/runit/). | _any_ +supervisord | Exposes service status from [supervisord](http://supervisord.org/). | _any_ + +### Perf Collector + The `perf` collector may not work out of the box on some Linux systems due to kernel configuration and security settings. To allow access, set the following `sysctl` parameter: @@ -190,30 +255,56 @@ found using [`perf list`](http://man7.org/linux/man-pages/man1/perf.1.html) or from debugfs. And example usage of this would be `--collector.perf.tracepoint="sched:sched_process_exec"`. +### Sysctl Collector -Name | Description | OS ----------|-------------|---- -buddyinfo | Exposes statistics of memory fragments as reported by /proc/buddyinfo. | Linux -devstat | Exposes device statistics | Dragonfly, FreeBSD -drbd | Exposes Distributed Replicated Block Device statistics (to version 8.4) | Linux -ethtool | Exposes network interface information and network driver statistics equivalent to `ethtool`, `ethtool -S`, and `ethtool -i`. | Linux -interrupts | Exposes detailed interrupts statistics. | Linux, OpenBSD -ksmd | Exposes kernel and system statistics from `/sys/kernel/mm/ksm`. | Linux -logind | Exposes session counts from [logind](http://www.freedesktop.org/wiki/Software/systemd/logind/). | Linux -meminfo\_numa | Exposes memory statistics from `/proc/meminfo_numa`. | Linux -mountstats | Exposes filesystem statistics from `/proc/self/mountstats`. Exposes detailed NFS client statistics. | Linux -network_route | Exposes the routing table as metrics | Linux -ntp | Exposes local NTP daemon health to check [time](./docs/TIME.md) | _any_ -perf | Exposes perf based metrics (Warning: Metrics are dependent on kernel configuration and settings). | Linux -processes | Exposes aggregate process statistics from `/proc`. | Linux -qdisc | Exposes [queuing discipline](https://en.wikipedia.org/wiki/Network_scheduler#Linux_kernel) statistics | Linux -runit | Exposes service status from [runit](http://smarden.org/runit/). | _any_ -supervisord | Exposes service status from [supervisord](http://supervisord.org/). | _any_ -systemd | Exposes service and system status from [systemd](http://www.freedesktop.org/wiki/Software/systemd/). | Linux -tcpstat | Exposes TCP connection status information from `/proc/net/tcp` and `/proc/net/tcp6`. (Warning: the current version has potential performance issues in high load situations.) | Linux -wifi | Exposes WiFi device and station statistics. | Linux -zoneinfo | Exposes NUMA memory zone metrics. | Linux +The `sysctl` collector can be enabled with `--collector.sysctl`. It supports exposing numeric sysctl values +as metrics using the `--collector.sysctl.include` flag and string values as info metrics by using the +`--collector.sysctl.include-info` flag. The flags can be repeated. For sysctl with multiple numeric values, +an optional mapping can be given to expose each value as its own metric. Otherwise an `index` label is used +to identify the different fields. + +#### Examples +##### Numeric values +###### Single values +Using `--collector.sysctl.include=vm.user_reserve_kbytes`: +`vm.user_reserve_kbytes = 131072` -> `node_sysctl_vm_user_reserve_kbytes 131072` + +###### Multiple values +A sysctl can contain multiple values, for example: +``` +net.ipv4.tcp_rmem = 4096 131072 6291456 +``` +Using `--collector.sysctl.include=net.ipv4.tcp_rmem` the collector will expose: +``` +node_sysctl_net_ipv4_tcp_rmem{index="0"} 4096 +node_sysctl_net_ipv4_tcp_rmem{index="1"} 131072 +node_sysctl_net_ipv4_tcp_rmem{index="2"} 6291456 +``` +If the indexes have defined meaning like in this case, the values can be mapped to multiple metrics by appending the mapping to the --collector.sysctl.include flag: +Using `--collector.sysctl.include=net.ipv4.tcp_rmem:min,default,max` the collector will expose: +``` +node_sysctl_net_ipv4_tcp_rmem_min 4096 +node_sysctl_net_ipv4_tcp_rmem_default 131072 +node_sysctl_net_ipv4_tcp_rmem_max 6291456 +``` + +##### String values +String values need to be exposed as info metric. The user selects them by using the `--collector.sysctl.include-info` flag. + +###### Single values +`kernel.core_pattern = core` -> `node_sysctl_info{key="kernel.core_pattern_info", value="core"} 1` +###### Multiple values +Given the following sysctl: +``` +kernel.seccomp.actions_avail = kill_process kill_thread trap errno trace log allow +``` +Setting `--collector.sysctl.include-info=kernel.seccomp.actions_avail` will yield: +``` +node_sysctl_info{key="kernel.seccomp.actions_avail", index="0", value="kill_process"} 1 +node_sysctl_info{key="kernel.seccomp.actions_avail", index="1", value="kill_thread"} 1 +... +``` ### Textfile Collector @@ -266,7 +357,7 @@ Building: git clone https://github.com/prometheus/node_exporter.git cd node_exporter - make + make build ./node_exporter To see all available configuration flags: @@ -284,10 +375,10 @@ To see all available configuration flags: The exporter supports TLS via a new web configuration file. ```console -./node_exporter --web.config=web-config.yml +./node_exporter --web.config.file=web-config.yml ``` -See the [exporter-toolkit https package](https://github.com/prometheus/exporter-toolkit/blob/v0.1.0/https/README.md) for more details. +See the [exporter-toolkit web-configuration](https://github.com/prometheus/exporter-toolkit/blob/master/docs/web-configuration.md) for more details. [travis]: https://travis-ci.org/prometheus/node_exporter [hub]: https://hub.docker.com/r/prom/node-exporter/ diff --git a/SECURITY.md b/SECURITY.md index 67741f015a..fed02d85c7 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,4 +3,4 @@ The Prometheus security policy, including how to report vulnerabilities, can be found here: -https://prometheus.io/docs/operating/security/ + diff --git a/VERSION b/VERSION index 23aa839063..bd8bf882d0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.2 +1.7.0 diff --git a/collector/arp_linux.go b/collector/arp_linux.go index 99b8acfab5..c7861156f3 100644 --- a/collector/arp_linux.go +++ b/collector/arp_linux.go @@ -17,19 +17,29 @@ package collector import ( - "bufio" + "errors" "fmt" - "io" - "os" - "strings" + "net" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" + "github.com/jsimonetti/rtnetlink" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs" + "golang.org/x/sys/unix" +) + +var ( + arpDeviceInclude = kingpin.Flag("collector.arp.device-include", "Regexp of arp devices to include (mutually exclusive to device-exclude).").String() + arpDeviceExclude = kingpin.Flag("collector.arp.device-exclude", "Regexp of arp devices to exclude (mutually exclusive to device-include).").String() + arpNetlink = kingpin.Flag("collector.arp.netlink", "Use netlink to gather stats instead of /proc/net/arp.").Default("true").Bool() ) type arpCollector struct { - entries *prometheus.Desc - logger log.Logger + fs procfs.FS + deviceFilter deviceFilter + entries *prometheus.Desc + logger log.Logger } func init() { @@ -38,7 +48,14 @@ func init() { // NewARPCollector returns a new Collector exposing ARP stats. func NewARPCollector(logger log.Logger) (Collector, error) { + fs, err := procfs.NewFS(*procPath) + if err != nil { + return nil, fmt.Errorf("failed to open procfs: %w", err) + } + return &arpCollector{ + fs: fs, + deviceFilter: newDeviceFilter(*arpDeviceExclude, *arpDeviceInclude), entries: prometheus.NewDesc( prometheus.BuildFQName(namespace, "arp", "entries"), "ARP entries by device", @@ -48,56 +65,80 @@ func NewARPCollector(logger log.Logger) (Collector, error) { }, nil } -func getARPEntries() (map[string]uint32, error) { - file, err := os.Open(procFilePath("net/arp")) +func getTotalArpEntries(deviceEntries []procfs.ARPEntry) map[string]uint32 { + entries := make(map[string]uint32) + + for _, device := range deviceEntries { + entries[device.Device]++ + } + + return entries +} + +func getTotalArpEntriesRTNL() (map[string]uint32, error) { + conn, err := rtnetlink.Dial(nil) if err != nil { return nil, err } - defer file.Close() + defer conn.Close() - entries, err := parseARPEntries(file) + neighbors, err := conn.Neigh.List() if err != nil { return nil, err } - return entries, nil -} + ifIndexEntries := make(map[uint32]uint32) -// TODO: This should get extracted to the github.com/prometheus/procfs package -// to support more complete parsing of /proc/net/arp. Instead of adding -// more fields to this function's return values it should get moved and -// changed to support each field. -func parseARPEntries(data io.Reader) (map[string]uint32, error) { - scanner := bufio.NewScanner(data) - entries := make(map[string]uint32) - - for scanner.Scan() { - columns := strings.Fields(scanner.Text()) - - if len(columns) < 6 { - return nil, fmt.Errorf("unexpected ARP table format") + for _, n := range neighbors { + // Neighbors will also contain IPv6 neighbors, but since this is purely an ARP collector, + // restrict to AF_INET. Also skip entries which have state NUD_NOARP to conform to output + // of /proc/net/arp. + if n.Family == unix.AF_INET && n.State&unix.NUD_NOARP == 0 { + ifIndexEntries[n.Index]++ } + } - if columns[0] != "IP" { - deviceIndex := len(columns) - 1 - entries[columns[deviceIndex]]++ + enumEntries := make(map[string]uint32) + + // Convert interface indexes to names. + for ifIndex, entryCount := range ifIndexEntries { + iface, err := net.InterfaceByIndex(int(ifIndex)) + if err != nil { + if errors.Unwrap(err).Error() == "no such network interface" { + continue + } + return nil, err } - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("failed to parse ARP info: %w", err) + enumEntries[iface.Name] = entryCount } - return entries, nil + return enumEntries, nil } func (c *arpCollector) Update(ch chan<- prometheus.Metric) error { - entries, err := getARPEntries() - if err != nil { - return fmt.Errorf("could not get ARP entries: %w", err) + var enumeratedEntry map[string]uint32 + + if *arpNetlink { + var err error + + enumeratedEntry, err = getTotalArpEntriesRTNL() + if err != nil { + return fmt.Errorf("could not get ARP entries: %w", err) + } + } else { + entries, err := c.fs.GatherARPEntries() + if err != nil { + return fmt.Errorf("could not get ARP entries: %w", err) + } + + enumeratedEntry = getTotalArpEntries(entries) } - for device, entryCount := range entries { + for device, entryCount := range enumeratedEntry { + if c.deviceFilter.ignored(device) { + continue + } ch <- prometheus.MustNewConstMetric( c.entries, prometheus.GaugeValue, float64(entryCount), device) } diff --git a/collector/bcache_linux.go b/collector/bcache_linux.go index 63a22d033a..1d402d3ff5 100644 --- a/collector/bcache_linux.go +++ b/collector/bcache_linux.go @@ -19,10 +19,10 @@ package collector import ( "fmt" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/bcache" - "gopkg.in/alecthomas/kingpin.v2" ) var ( @@ -134,14 +134,19 @@ func bcachePeriodStatsToMetric(ps *bcache.PeriodStats, labelValue string) []bcac extraLabel: label, extraLabelValue: labelValue, }, - { - name: "cache_readaheads_total", - desc: "Count of times readahead occurred.", - value: float64(ps.CacheReadaheads), - metricType: prometheus.CounterValue, - extraLabel: label, - extraLabelValue: labelValue, - }, + } + if ps.CacheReadaheads != 0 { + bcacheReadaheadMetrics := []bcacheMetric{ + { + name: "cache_readaheads_total", + desc: "Count of times readahead occurred.", + value: float64(ps.CacheReadaheads), + metricType: prometheus.CounterValue, + extraLabel: label, + extraLabelValue: labelValue, + }, + } + metrics = append(metrics, bcacheReadaheadMetrics...) } return metrics } diff --git a/collector/bonding_linux.go b/collector/bonding_linux.go index 4c62207c9a..d9d04e222c 100644 --- a/collector/bonding_linux.go +++ b/collector/bonding_linux.go @@ -19,7 +19,6 @@ package collector import ( "errors" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -76,21 +75,21 @@ func (c *bondingCollector) Update(ch chan<- prometheus.Metric) error { func readBondingStats(root string) (status map[string][2]int, err error) { status = map[string][2]int{} - masters, err := ioutil.ReadFile(filepath.Join(root, "bonding_masters")) + masters, err := os.ReadFile(filepath.Join(root, "bonding_masters")) if err != nil { return nil, err } for _, master := range strings.Fields(string(masters)) { - slaves, err := ioutil.ReadFile(filepath.Join(root, master, "bonding", "slaves")) + slaves, err := os.ReadFile(filepath.Join(root, master, "bonding", "slaves")) if err != nil { return nil, err } sstat := [2]int{0, 0} for _, slave := range strings.Fields(string(slaves)) { - state, err := ioutil.ReadFile(filepath.Join(root, master, fmt.Sprintf("lower_%s", slave), "bonding_slave", "mii_status")) + state, err := os.ReadFile(filepath.Join(root, master, fmt.Sprintf("lower_%s", slave), "bonding_slave", "mii_status")) if errors.Is(err, os.ErrNotExist) { // some older? kernels use slave_ prefix - state, err = ioutil.ReadFile(filepath.Join(root, master, fmt.Sprintf("slave_%s", slave), "bonding_slave", "mii_status")) + state, err = os.ReadFile(filepath.Join(root, master, fmt.Sprintf("slave_%s", slave), "bonding_slave", "mii_status")) } if err != nil { return nil, err diff --git a/collector/bonding_linux_test.go b/collector/bonding_linux_test.go index 564cf01e25..98af73fad8 100644 --- a/collector/bonding_linux_test.go +++ b/collector/bonding_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nobonding +// +build !nobonding + package collector import ( diff --git a/collector/boot_time_bsd.go b/collector/boot_time_bsd.go index f6eea02d28..8a9c17b31a 100644 --- a/collector/boot_time_bsd.go +++ b/collector/boot_time_bsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build (freebsd || dragonfly || (openbsd && !amd64) || netbsd || darwin) && !noboottime -// +build freebsd dragonfly openbsd,!amd64 netbsd darwin +//go:build (freebsd || dragonfly || openbsd || netbsd || darwin) && !noboottime +// +build freebsd dragonfly openbsd netbsd darwin // +build !noboottime package collector @@ -20,11 +20,11 @@ package collector import ( "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/unix" ) type bootTimeCollector struct { - boottime bsdSysctl - logger log.Logger + logger log.Logger } func init() { @@ -34,27 +34,25 @@ func init() { // newBootTimeCollector returns a new Collector exposing system boot time on BSD systems. func newBootTimeCollector(logger log.Logger) (Collector, error) { return &bootTimeCollector{ - boottime: bsdSysctl{ - name: "boot_time_seconds", - description: "Unix time of last boot, including microseconds.", - mib: "kern.boottime", - dataType: bsdSysctlTypeStructTimeval, - }, logger: logger, }, nil } // Update pushes boot time onto ch func (c *bootTimeCollector) Update(ch chan<- prometheus.Metric) error { - v, err := c.boottime.Value() + tv, err := unix.SysctlTimeval("kern.boottime") if err != nil { return err } + // This conversion maintains the usec precision. Using the time + // package did not. + v := float64(tv.Sec) + (float64(tv.Usec) / float64(1000*1000)) + ch <- prometheus.MustNewConstMetric( prometheus.NewDesc( - prometheus.BuildFQName(namespace, "", c.boottime.name), - c.boottime.description, + prometheus.BuildFQName(namespace, "", "boot_time_seconds"), + "Unix time of last boot, including microseconds.", nil, nil, ), prometheus.GaugeValue, v) diff --git a/collector/boot_time_openbsd_amd64.go b/collector/boot_time_openbsd_amd64.go deleted file mode 100644 index c8e9d65cf0..0000000000 --- a/collector/boot_time_openbsd_amd64.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2020 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 !noboottime -// +build !noboottime - -package collector - -import ( - "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" - "golang.org/x/sys/unix" - "unsafe" -) - -type bootTimeCollector struct { - name, description string - logger log.Logger -} - -func init() { - registerCollector("boottime", defaultEnabled, newBootTimeCollector) -} - -// newBootTimeCollector returns a new Collector exposing system boot time on BSD systems. -func newBootTimeCollector(logger log.Logger) (Collector, error) { - return &bootTimeCollector{ - name: "boot_time_seconds", - description: "Unix time of last boot, including microseconds.", - logger: logger, - }, nil -} - -// Update pushes boot time onto ch -func (c *bootTimeCollector) Update(ch chan<- prometheus.Metric) error { - raw, err := unix.SysctlRaw("kern.boottime") - if err != nil { - return err - } - - tv := *(*unix.Timeval)(unsafe.Pointer(&raw[0])) - v := (float64(tv.Sec) + (float64(tv.Usec) / float64(1000*1000))) - - ch <- prometheus.MustNewConstMetric( - prometheus.NewDesc( - prometheus.BuildFQName(namespace, "", c.name), - c.description, - nil, nil, - ), prometheus.GaugeValue, v) - - return nil -} diff --git a/collector/boot_time_solaris.go b/collector/boot_time_solaris.go index 3d55e7835f..15955121f7 100644 --- a/collector/boot_time_solaris.go +++ b/collector/boot_time_solaris.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build solaris && !noboottime -// +build solaris,!noboottime +//go:build !noboottime +// +build !noboottime package collector diff --git a/collector/btrfs_linux.go b/collector/btrfs_linux.go index 01971c7c1a..f1490541a9 100644 --- a/collector/btrfs_linux.go +++ b/collector/btrfs_linux.go @@ -18,8 +18,13 @@ package collector import ( "fmt" + "path" + "strings" + "syscall" + dennwc "github.com/dennwc/btrfs" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/btrfs" ) @@ -52,19 +57,166 @@ func NewBtrfsCollector(logger log.Logger) (Collector, error) { func (c *btrfsCollector) Update(ch chan<- prometheus.Metric) error { stats, err := c.fs.Stats() if err != nil { - return fmt.Errorf("failed to retrieve Btrfs stats: %w", err) + return fmt.Errorf("failed to retrieve Btrfs stats from procfs: %w", err) + } + + ioctlStatsMap, err := c.getIoctlStats() + if err != nil { + level.Debug(c.logger).Log( + "msg", "Error querying btrfs device stats with ioctl", + "err", err) + ioctlStatsMap = make(map[string]*btrfsIoctlFsStats) } for _, s := range stats { - c.updateBtrfsStats(ch, s) + // match up procfs and ioctl info by filesystem UUID (without dashes) + var fsUUID = strings.Replace(s.UUID, "-", "", -1) + ioctlStats := ioctlStatsMap[fsUUID] + c.updateBtrfsStats(ch, s, ioctlStats) } return nil } +type btrfsIoctlFsDevStats struct { + path string + uuid string + + bytesUsed uint64 + totalBytes uint64 + + // The error stats below match the following upstream lists: + // https://github.com/dennwc/btrfs/blob/b3db0b2dedac3bf580f412034d77e0bf4b420167/btrfs.go#L132-L140 + // https://github.com/torvalds/linux/blob/70d605cbeecb408dd884b1f0cd3963eeeaac144c/include/uapi/linux/btrfs.h#L680-L692 + writeErrs uint64 + readErrs uint64 + flushErrs uint64 + corruptionErrs uint64 + generationErrs uint64 +} + +type btrfsIoctlFsStats struct { + uuid string + devices []btrfsIoctlFsDevStats +} + +func (c *btrfsCollector) getIoctlStats() (map[string]*btrfsIoctlFsStats, error) { + // Instead of introducing more ioctl calls to scan for all btrfs + // filesystems re-use our mount point utils to find known mounts + mountsList, err := mountPointDetails(c.logger) + if err != nil { + return nil, err + } + + // Track devices we have successfully scanned, by device path. + devicesDone := make(map[string]struct{}) + // Filesystems scann results by UUID. + fsStats := make(map[string]*btrfsIoctlFsStats) + + for _, mount := range mountsList { + if mount.fsType != "btrfs" { + continue + } + + if _, found := devicesDone[mount.device]; found { + // We already found this filesystem by another mount point. + continue + } + + mountPath := rootfsFilePath(mount.mountPoint) + + fs, err := dennwc.Open(mountPath, true) + if err != nil { + // Failed to open this mount point, maybe we didn't have permission + // maybe we'll find another mount point for this FS later. + level.Debug(c.logger).Log( + "msg", "Error inspecting btrfs mountpoint", + "mountPoint", mountPath, + "err", err) + continue + } + defer fs.Close() + + fsInfo, err := fs.Info() + if err != nil { + // Failed to get the FS info for some reason, + // perhaps it'll work with a different mount point + level.Debug(c.logger).Log( + "msg", "Error querying btrfs filesystem", + "mountPoint", mountPath, + "err", err) + continue + } + + fsID := fsInfo.FSID.String() + if _, found := fsStats[fsID]; found { + // We already found this filesystem by another mount point + continue + } + + deviceStats, err := c.getIoctlDeviceStats(fs, &fsInfo) + if err != nil { + level.Debug(c.logger).Log( + "msg", "Error querying btrfs device stats", + "mountPoint", mountPath, + "err", err) + continue + } + + devicesDone[mount.device] = struct{}{} + fsStats[fsID] = &btrfsIoctlFsStats{ + uuid: fsID, + devices: deviceStats, + } + } + + return fsStats, nil +} + +func (c *btrfsCollector) getIoctlDeviceStats(fs *dennwc.FS, fsInfo *dennwc.Info) ([]btrfsIoctlFsDevStats, error) { + devices := make([]btrfsIoctlFsDevStats, 0, fsInfo.NumDevices) + + for i := uint64(0); i <= fsInfo.MaxID; i++ { + deviceInfo, err := fs.GetDevInfo(i) + + if err != nil { + if errno, ok := err.(syscall.Errno); ok && errno == syscall.ENODEV { + // Device IDs do not consistently start at 0, nor are ranges contiguous, so we expect this. + continue + } + return nil, err + } + + deviceStats, err := fs.GetDevStats(i) + if err != nil { + return nil, err + } + + devices = append(devices, btrfsIoctlFsDevStats{ + path: deviceInfo.Path, + uuid: deviceInfo.UUID.String(), + bytesUsed: deviceInfo.BytesUsed, + totalBytes: deviceInfo.TotalBytes, + + writeErrs: deviceStats.WriteErrs, + readErrs: deviceStats.ReadErrs, + flushErrs: deviceStats.FlushErrs, + corruptionErrs: deviceStats.CorruptionErrs, + generationErrs: deviceStats.GenerationErrs, + }) + + if uint64(len(devices)) == fsInfo.NumDevices { + break + } + } + + return devices, nil +} + // btrfsMetric represents a single Btrfs metric that is converted into a Prometheus Metric. type btrfsMetric struct { name string + metricType prometheus.ValueType desc string value float64 extraLabel []string @@ -72,14 +224,14 @@ type btrfsMetric struct { } // updateBtrfsStats collects statistics for one bcache ID. -func (c *btrfsCollector) updateBtrfsStats(ch chan<- prometheus.Metric, s *btrfs.Stats) { +func (c *btrfsCollector) updateBtrfsStats(ch chan<- prometheus.Metric, s *btrfs.Stats, ioctlStats *btrfsIoctlFsStats) { const subsystem = "btrfs" // Basic information about the filesystem. devLabels := []string{"uuid"} // Retrieve the metrics. - metrics := c.getMetrics(s) + metrics := c.getMetrics(s, ioctlStats) // Convert all gathered metrics to Prometheus Metrics and add to channel. for _, m := range metrics { @@ -99,7 +251,7 @@ func (c *btrfsCollector) updateBtrfsStats(ch chan<- prometheus.Metric, s *btrfs. ch <- prometheus.MustNewConstMetric( desc, - prometheus.GaugeValue, + m.metricType, m.value, labelValues..., ) @@ -107,38 +259,104 @@ func (c *btrfsCollector) updateBtrfsStats(ch chan<- prometheus.Metric, s *btrfs. } // getMetrics returns metrics for the given Btrfs statistics. -func (c *btrfsCollector) getMetrics(s *btrfs.Stats) []btrfsMetric { +func (c *btrfsCollector) getMetrics(s *btrfs.Stats, ioctlStats *btrfsIoctlFsStats) []btrfsMetric { metrics := []btrfsMetric{ { name: "info", desc: "Filesystem information", value: 1, + metricType: prometheus.GaugeValue, extraLabel: []string{"label"}, extraLabelValue: []string{s.Label}, }, { - name: "global_rsv_size_bytes", - desc: "Size of global reserve.", - value: float64(s.Allocation.GlobalRsvSize), + name: "global_rsv_size_bytes", + desc: "Size of global reserve.", + metricType: prometheus.GaugeValue, + value: float64(s.Allocation.GlobalRsvSize), }, } - // Information about devices. - for n, dev := range s.Devices { - metrics = append(metrics, btrfsMetric{ - name: "device_size_bytes", - desc: "Size of a device that is part of the filesystem.", - value: float64(dev.Size), - extraLabel: []string{"device"}, - extraLabelValue: []string{n}, - }) - } - // Information about data, metadata and system data. metrics = append(metrics, c.getAllocationStats("data", s.Allocation.Data)...) metrics = append(metrics, c.getAllocationStats("metadata", s.Allocation.Metadata)...) metrics = append(metrics, c.getAllocationStats("system", s.Allocation.System)...) + // Information about devices. + if ioctlStats == nil { + for n, dev := range s.Devices { + metrics = append(metrics, btrfsMetric{ + name: "device_size_bytes", + desc: "Size of a device that is part of the filesystem.", + metricType: prometheus.GaugeValue, + value: float64(dev.Size), + extraLabel: []string{"device"}, + extraLabelValue: []string{n}, + }) + } + return metrics + } + + for _, dev := range ioctlStats.devices { + // trim the path prefix from the device name so the value should match + // the value used in the fallback branch above. + // e.g. /dev/sda -> sda, /rootfs/dev/md1 -> md1 + _, device := path.Split(dev.path) + + extraLabels := []string{"device", "btrfs_dev_uuid"} + extraLabelValues := []string{device, dev.uuid} + + metrics = append(metrics, + btrfsMetric{ + name: "device_size_bytes", + desc: "Size of a device that is part of the filesystem.", + metricType: prometheus.GaugeValue, + value: float64(dev.totalBytes), + extraLabel: extraLabels, + extraLabelValue: extraLabelValues, + }, + // A bytes available metric is probably more useful than a + // bytes used metric, because large numbers of bytes will + // suffer from floating point representation issues + // and we probably care more about the number when it's low anyway + btrfsMetric{ + name: "device_unused_bytes", + desc: "Unused bytes unused on a device that is part of the filesystem.", + metricType: prometheus.GaugeValue, + value: float64(dev.totalBytes - dev.bytesUsed), + extraLabel: extraLabels, + extraLabelValue: extraLabelValues, + }) + + errorLabels := append([]string{"type"}, extraLabels...) + values := []uint64{ + dev.writeErrs, + dev.readErrs, + dev.flushErrs, + dev.corruptionErrs, + dev.generationErrs, + } + btrfsErrorTypeNames := []string{ + "write", + "read", + "flush", + "corruption", + "generation", + } + + for i, errorType := range btrfsErrorTypeNames { + metrics = append(metrics, + btrfsMetric{ + name: "device_errors_total", + desc: "Errors reported for the device", + metricType: prometheus.CounterValue, + value: float64(values[i]), + extraLabel: errorLabels, + extraLabelValue: append([]string{errorType}, extraLabelValues...), + }) + } + } + return metrics } @@ -148,6 +366,7 @@ func (c *btrfsCollector) getAllocationStats(a string, s *btrfs.AllocationStats) { name: "reserved_bytes", desc: "Amount of space reserved for a data type", + metricType: prometheus.GaugeValue, value: float64(s.ReservedBytes), extraLabel: []string{"block_group_type"}, extraLabelValue: []string{a}, @@ -168,6 +387,7 @@ func (c *btrfsCollector) getLayoutStats(a, l string, s *btrfs.LayoutUsage) []btr { name: "used_bytes", desc: "Amount of used space by a layout/data type", + metricType: prometheus.GaugeValue, value: float64(s.UsedBytes), extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{a, l}, @@ -175,6 +395,7 @@ func (c *btrfsCollector) getLayoutStats(a, l string, s *btrfs.LayoutUsage) []btr { name: "size_bytes", desc: "Amount of space allocated for a layout/data type", + metricType: prometheus.GaugeValue, value: float64(s.TotalBytes), extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{a, l}, @@ -182,6 +403,7 @@ func (c *btrfsCollector) getLayoutStats(a, l string, s *btrfs.LayoutUsage) []btr { name: "allocation_ratio", desc: "Data allocation ratio for a layout/data type", + metricType: prometheus.GaugeValue, value: s.Ratio, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{a, l}, diff --git a/collector/btrfs_linux_test.go b/collector/btrfs_linux_test.go index 7ce19aafab..fcd6f9f995 100644 --- a/collector/btrfs_linux_test.go +++ b/collector/btrfs_linux_test.go @@ -27,8 +27,6 @@ var expectedBtrfsMetrics = [][]btrfsMetric{ { {name: "info", value: 1, extraLabel: []string{"label"}, extraLabelValue: []string{"fixture"}}, {name: "global_rsv_size_bytes", value: 1.6777216e+07}, - {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop25"}}, - {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop26"}}, {name: "reserved_bytes", value: 0, extraLabel: []string{"block_group_type"}, extraLabelValue: []string{"data"}}, {name: "used_bytes", value: 8.08189952e+08, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"data", "raid0"}}, {name: "size_bytes", value: 2.147483648e+09, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"data", "raid0"}}, @@ -41,14 +39,12 @@ var expectedBtrfsMetrics = [][]btrfsMetric{ {name: "used_bytes", value: 16384, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"system", "raid1"}}, {name: "size_bytes", value: 8.388608e+06, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"system", "raid1"}}, {name: "allocation_ratio", value: 2, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"system", "raid1"}}, + {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop25"}}, + {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop26"}}, }, { {name: "info", value: 1, extraLabel: []string{"label"}, extraLabelValue: []string{""}}, {name: "global_rsv_size_bytes", value: 1.6777216e+07}, - {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop22"}}, - {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop23"}}, - {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop24"}}, - {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop25"}}, {name: "reserved_bytes", value: 0, extraLabel: []string{"block_group_type"}, extraLabelValue: []string{"data"}}, {name: "used_bytes", value: 0, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"data", "raid5"}}, {name: "size_bytes", value: 6.44087808e+08, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"data", "raid5"}}, @@ -61,6 +57,10 @@ var expectedBtrfsMetrics = [][]btrfsMetric{ {name: "used_bytes", value: 16384, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"system", "raid6"}}, {name: "size_bytes", value: 1.6777216e+07, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"system", "raid6"}}, {name: "allocation_ratio", value: 2, extraLabel: []string{"block_group_type", "mode"}, extraLabelValue: []string{"system", "raid6"}}, + {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop22"}}, + {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop23"}}, + {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop24"}}, + {name: "device_size_bytes", value: 1.073741824e+10, extraLabel: []string{"device"}, extraLabelValue: []string{"loop25"}}, }, } @@ -104,7 +104,7 @@ func TestBtrfs(t *testing.T) { } for i, s := range stats { - metrics := collector.getMetrics(s) + metrics := collector.getMetrics(s, nil) if len(metrics) != len(expectedBtrfsMetrics[i]) { t.Fatalf("Unexpected number of Btrfs metrics: expected %v, got %v", len(expectedBtrfsMetrics[i]), len(metrics)) } diff --git a/collector/cgroups_linux.go b/collector/cgroups_linux.go new file mode 100644 index 0000000000..9f6d01a465 --- /dev/null +++ b/collector/cgroups_linux.go @@ -0,0 +1,73 @@ +// Copyright 2022 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 !nostat +// +build !nostat + +package collector + +import ( + "fmt" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs" +) + +const cgroupsCollectorSubsystem = "cgroups" + +type cgroupSummaryCollector struct { + fs procfs.FS + cgroups *prometheus.Desc + enabled *prometheus.Desc + logger log.Logger +} + +func init() { + registerCollector(cgroupsCollectorSubsystem, defaultDisabled, NewCgroupSummaryCollector) +} + +// NewCgroupSummaryCollector returns a new Collector exposing a summary of cgroups. +func NewCgroupSummaryCollector(logger log.Logger) (Collector, error) { + fs, err := procfs.NewFS(*procPath) + if err != nil { + return nil, fmt.Errorf("failed to open procfs: %w", err) + } + return &cgroupSummaryCollector{ + fs: fs, + cgroups: prometheus.NewDesc( + prometheus.BuildFQName(namespace, cgroupsCollectorSubsystem, "cgroups"), + "Current cgroup number of the subsystem.", + []string{"subsys_name"}, nil, + ), + enabled: prometheus.NewDesc( + prometheus.BuildFQName(namespace, cgroupsCollectorSubsystem, "enabled"), + "Current cgroup number of the subsystem.", + []string{"subsys_name"}, nil, + ), + logger: logger, + }, nil +} + +// Update implements Collector and exposes cgroup statistics. +func (c *cgroupSummaryCollector) Update(ch chan<- prometheus.Metric) error { + cgroupSummarys, err := c.fs.CgroupSummarys() + if err != nil { + return err + } + for _, cs := range cgroupSummarys { + ch <- prometheus.MustNewConstMetric(c.cgroups, prometheus.GaugeValue, float64(cs.Cgroups), cs.SubsysName) + ch <- prometheus.MustNewConstMetric(c.enabled, prometheus.GaugeValue, float64(cs.Enabled), cs.SubsysName) + } + return nil +} diff --git a/collector/collector.go b/collector/collector.go index 54f0ff6d58..3112c78970 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -20,10 +20,10 @@ import ( "sync" "time" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) // Namespace defines the common namespace to be used by all metrics. @@ -198,3 +198,49 @@ var ErrNoData = errors.New("collector returned no data") func IsNoDataError(err error) bool { return err == ErrNoData } + +// pushMetric helps construct and convert a variety of value types into Prometheus float64 metrics. +func pushMetric(ch chan<- prometheus.Metric, fieldDesc *prometheus.Desc, name string, value interface{}, valueType prometheus.ValueType, labelValues ...string) { + var fVal float64 + switch val := value.(type) { + case uint8: + fVal = float64(val) + case uint16: + fVal = float64(val) + case uint32: + fVal = float64(val) + case uint64: + fVal = float64(val) + case int64: + fVal = float64(val) + case *uint8: + if val == nil { + return + } + fVal = float64(*val) + case *uint16: + if val == nil { + return + } + fVal = float64(*val) + case *uint32: + if val == nil { + return + } + fVal = float64(*val) + case *uint64: + if val == nil { + return + } + fVal = float64(*val) + case *int64: + if val == nil { + return + } + fVal = float64(*val) + default: + return + } + + ch <- prometheus.MustNewConstMetric(fieldDesc, valueType, fVal, labelValues...) +} diff --git a/collector/cpu_darwin.go b/collector/cpu_darwin.go index 2a2b006201..6c461cc348 100644 --- a/collector/cpu_darwin.go +++ b/collector/cpu_darwin.go @@ -39,6 +39,7 @@ import ( #include #include #include +#include #if TARGET_OS_MAC #include #endif diff --git a/collector/cpu_linux.go b/collector/cpu_linux.go index 2ddb9c4b94..fcbf651b22 100644 --- a/collector/cpu_linux.go +++ b/collector/cpu_linux.go @@ -18,30 +18,37 @@ package collector import ( "fmt" + "os" "path/filepath" "regexp" "strconv" "sync" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs" - "gopkg.in/alecthomas/kingpin.v2" + "github.com/prometheus/procfs/sysfs" + "golang.org/x/exp/maps" + "golang.org/x/exp/slices" ) type cpuCollector struct { fs procfs.FS cpu *prometheus.Desc cpuInfo *prometheus.Desc + cpuFrequencyHz *prometheus.Desc cpuFlagsInfo *prometheus.Desc cpuBugsInfo *prometheus.Desc cpuGuest *prometheus.Desc cpuCoreThrottle *prometheus.Desc cpuPackageThrottle *prometheus.Desc + cpuIsolated *prometheus.Desc logger log.Logger - cpuStats []procfs.CPUStat + cpuStats map[int64]procfs.CPUStat cpuStatsMutex sync.Mutex + isolatedCpus []uint16 cpuFlagsIncludeRegexp *regexp.Regexp cpuBugsIncludeRegexp *regexp.Regexp @@ -68,6 +75,20 @@ func NewCPUCollector(logger log.Logger) (Collector, error) { if err != nil { return nil, fmt.Errorf("failed to open procfs: %w", err) } + + sysfs, err := sysfs.NewFS(*sysPath) + if err != nil { + return nil, fmt.Errorf("failed to open sysfs: %w", err) + } + + isolcpus, err := sysfs.IsolatedCPUs() + if err != nil { + if !os.IsNotExist(err) { + return nil, fmt.Errorf("Unable to get isolated cpus: %w", err) + } + level.Debug(logger).Log("msg", "Could not open isolated file", "error", err) + } + c := &cpuCollector{ fs: fs, cpu: nodeCPUSecondsDesc, @@ -76,6 +97,11 @@ func NewCPUCollector(logger log.Logger) (Collector, error) { "CPU information from /proc/cpuinfo.", []string{"package", "core", "cpu", "vendor", "family", "model", "model_name", "microcode", "stepping", "cachesize"}, nil, ), + cpuFrequencyHz: prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"), + "CPU frequency in hertz from /proc/cpuinfo.", + []string{"package", "core", "cpu"}, nil, + ), cpuFlagsInfo: prometheus.NewDesc( prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "flag_info"), "The `flags` field of CPU information from /proc/cpuinfo taken from the first core.", @@ -101,7 +127,14 @@ func NewCPUCollector(logger log.Logger) (Collector, error) { "Number of times this CPU package has been throttled.", []string{"package"}, nil, ), - logger: logger, + cpuIsolated: prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "isolated"), + "Whether each core is isolated, information from /sys/devices/system/cpu/isolated.", + []string{"cpu"}, nil, + ), + logger: logger, + isolatedCpus: isolcpus, + cpuStats: make(map[int64]procfs.CPUStat), } err = c.compileIncludeFlags(flagsInclude, bugsInclude) if err != nil { @@ -142,10 +175,10 @@ func (c *cpuCollector) Update(ch chan<- prometheus.Metric) error { if err := c.updateStat(ch); err != nil { return err } - if err := c.updateThermalThrottle(ch); err != nil { - return err + if c.isolatedCpus != nil { + c.updateIsolated(ch) } - return nil + return c.updateThermalThrottle(ch) } // updateInfo reads /proc/cpuinfo @@ -170,6 +203,20 @@ func (c *cpuCollector) updateInfo(ch chan<- prometheus.Metric) error { cpu.CacheSize) } + cpuFreqEnabled, ok := collectorState["cpufreq"] + if !ok || cpuFreqEnabled == nil { + level.Debug(c.logger).Log("msg", "cpufreq key missing or nil value in collectorState map") + } else if !*cpuFreqEnabled { + for _, cpu := range info { + ch <- prometheus.MustNewConstMetric(c.cpuFrequencyHz, + prometheus.GaugeValue, + cpu.CPUMHz*1e6, + cpu.PhysicalID, + cpu.CoreID, + strconv.Itoa(int(cpu.Processor))) + } + } + if len(info) != 0 { cpu := info[0] if err := updateFieldInfo(cpu.Flags, c.cpuFlagsIncludeRegexp, c.cpuFlagsInfo, ch); err != nil { @@ -279,6 +326,14 @@ func (c *cpuCollector) updateThermalThrottle(ch chan<- prometheus.Metric) error return nil } +// updateIsolated reads /sys/devices/system/cpu/isolated through sysfs and exports isolation level metrics. +func (c *cpuCollector) updateIsolated(ch chan<- prometheus.Metric) { + for _, cpu := range c.isolatedCpus { + cpuNum := strconv.Itoa(int(cpu)) + ch <- prometheus.MustNewConstMetric(c.cpuIsolated, prometheus.GaugeValue, 1.0, cpuNum) + } +} + // updateStat reads /proc/stat through procfs and exports CPU-related metrics. func (c *cpuCollector) updateStat(ch chan<- prometheus.Metric) error { stats, err := c.fs.Stat() @@ -292,7 +347,7 @@ func (c *cpuCollector) updateStat(ch chan<- prometheus.Metric) error { c.cpuStatsMutex.Lock() defer c.cpuStatsMutex.Unlock() for cpuID, cpuStat := range c.cpuStats { - cpuNum := strconv.Itoa(cpuID) + cpuNum := strconv.Itoa(int(cpuID)) ch <- prometheus.MustNewConstMetric(c.cpu, prometheus.CounterValue, cpuStat.User, cpuNum, "user") ch <- prometheus.MustNewConstMetric(c.cpu, prometheus.CounterValue, cpuStat.Nice, cpuNum, "nice") ch <- prometheus.MustNewConstMetric(c.cpu, prometheus.CounterValue, cpuStat.System, cpuNum, "system") @@ -313,82 +368,90 @@ func (c *cpuCollector) updateStat(ch chan<- prometheus.Metric) error { } // updateCPUStats updates the internal cache of CPU stats. -func (c *cpuCollector) updateCPUStats(newStats []procfs.CPUStat) { +func (c *cpuCollector) updateCPUStats(newStats map[int64]procfs.CPUStat) { // Acquire a lock to update the stats. c.cpuStatsMutex.Lock() defer c.cpuStatsMutex.Unlock() // Reset the cache if the list of CPUs has changed. - if len(c.cpuStats) != len(newStats) { - c.cpuStats = make([]procfs.CPUStat, len(newStats)) - } - for i, n := range newStats { + cpuStats := c.cpuStats[i] + // If idle jumps backwards by more than X seconds, assume we had a hotplug event and reset the stats for this CPU. - if (c.cpuStats[i].Idle - n.Idle) >= jumpBackSeconds { - level.Debug(c.logger).Log("msg", jumpBackDebugMessage, "cpu", i, "old_value", c.cpuStats[i].Idle, "new_value", n.Idle) - c.cpuStats[i] = procfs.CPUStat{} + if (cpuStats.Idle - n.Idle) >= jumpBackSeconds { + level.Debug(c.logger).Log("msg", jumpBackDebugMessage, "cpu", i, "old_value", cpuStats.Idle, "new_value", n.Idle) + cpuStats = procfs.CPUStat{} } - if n.Idle >= c.cpuStats[i].Idle { - c.cpuStats[i].Idle = n.Idle + if n.Idle >= cpuStats.Idle { + cpuStats.Idle = n.Idle } else { - level.Debug(c.logger).Log("msg", "CPU Idle counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].Idle, "new_value", n.Idle) + level.Debug(c.logger).Log("msg", "CPU Idle counter jumped backwards", "cpu", i, "old_value", cpuStats.Idle, "new_value", n.Idle) } - if n.User >= c.cpuStats[i].User { - c.cpuStats[i].User = n.User + if n.User >= cpuStats.User { + cpuStats.User = n.User } else { - level.Debug(c.logger).Log("msg", "CPU User counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].User, "new_value", n.User) + level.Debug(c.logger).Log("msg", "CPU User counter jumped backwards", "cpu", i, "old_value", cpuStats.User, "new_value", n.User) } - if n.Nice >= c.cpuStats[i].Nice { - c.cpuStats[i].Nice = n.Nice + if n.Nice >= cpuStats.Nice { + cpuStats.Nice = n.Nice } else { - level.Debug(c.logger).Log("msg", "CPU Nice counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].Nice, "new_value", n.Nice) + level.Debug(c.logger).Log("msg", "CPU Nice counter jumped backwards", "cpu", i, "old_value", cpuStats.Nice, "new_value", n.Nice) } - if n.System >= c.cpuStats[i].System { - c.cpuStats[i].System = n.System + if n.System >= cpuStats.System { + cpuStats.System = n.System } else { - level.Debug(c.logger).Log("msg", "CPU System counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].System, "new_value", n.System) + level.Debug(c.logger).Log("msg", "CPU System counter jumped backwards", "cpu", i, "old_value", cpuStats.System, "new_value", n.System) } - if n.Iowait >= c.cpuStats[i].Iowait { - c.cpuStats[i].Iowait = n.Iowait + if n.Iowait >= cpuStats.Iowait { + cpuStats.Iowait = n.Iowait } else { - level.Debug(c.logger).Log("msg", "CPU Iowait counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].Iowait, "new_value", n.Iowait) + level.Debug(c.logger).Log("msg", "CPU Iowait counter jumped backwards", "cpu", i, "old_value", cpuStats.Iowait, "new_value", n.Iowait) } - if n.IRQ >= c.cpuStats[i].IRQ { - c.cpuStats[i].IRQ = n.IRQ + if n.IRQ >= cpuStats.IRQ { + cpuStats.IRQ = n.IRQ } else { - level.Debug(c.logger).Log("msg", "CPU IRQ counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].IRQ, "new_value", n.IRQ) + level.Debug(c.logger).Log("msg", "CPU IRQ counter jumped backwards", "cpu", i, "old_value", cpuStats.IRQ, "new_value", n.IRQ) } - if n.SoftIRQ >= c.cpuStats[i].SoftIRQ { - c.cpuStats[i].SoftIRQ = n.SoftIRQ + if n.SoftIRQ >= cpuStats.SoftIRQ { + cpuStats.SoftIRQ = n.SoftIRQ } else { - level.Debug(c.logger).Log("msg", "CPU SoftIRQ counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].SoftIRQ, "new_value", n.SoftIRQ) + level.Debug(c.logger).Log("msg", "CPU SoftIRQ counter jumped backwards", "cpu", i, "old_value", cpuStats.SoftIRQ, "new_value", n.SoftIRQ) } - if n.Steal >= c.cpuStats[i].Steal { - c.cpuStats[i].Steal = n.Steal + if n.Steal >= cpuStats.Steal { + cpuStats.Steal = n.Steal } else { - level.Debug(c.logger).Log("msg", "CPU Steal counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].Steal, "new_value", n.Steal) + level.Debug(c.logger).Log("msg", "CPU Steal counter jumped backwards", "cpu", i, "old_value", cpuStats.Steal, "new_value", n.Steal) } - if n.Guest >= c.cpuStats[i].Guest { - c.cpuStats[i].Guest = n.Guest + if n.Guest >= cpuStats.Guest { + cpuStats.Guest = n.Guest } else { - level.Debug(c.logger).Log("msg", "CPU Guest counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].Guest, "new_value", n.Guest) + level.Debug(c.logger).Log("msg", "CPU Guest counter jumped backwards", "cpu", i, "old_value", cpuStats.Guest, "new_value", n.Guest) } - if n.GuestNice >= c.cpuStats[i].GuestNice { - c.cpuStats[i].GuestNice = n.GuestNice + if n.GuestNice >= cpuStats.GuestNice { + cpuStats.GuestNice = n.GuestNice } else { - level.Debug(c.logger).Log("msg", "CPU GuestNice counter jumped backwards", "cpu", i, "old_value", c.cpuStats[i].GuestNice, "new_value", n.GuestNice) + level.Debug(c.logger).Log("msg", "CPU GuestNice counter jumped backwards", "cpu", i, "old_value", cpuStats.GuestNice, "new_value", n.GuestNice) } + + c.cpuStats[i] = cpuStats + } + + // Remove offline CPUs. + if len(newStats) != len(c.cpuStats) { + onlineCPUIds := maps.Keys(newStats) + maps.DeleteFunc(c.cpuStats, func(key int64, item procfs.CPUStat) bool { + return !slices.Contains(onlineCPUIds, key) + }) } } diff --git a/collector/cpu_linux_test.go b/collector/cpu_linux_test.go index 93b493b2e9..b148ffcd93 100644 --- a/collector/cpu_linux_test.go +++ b/collector/cpu_linux_test.go @@ -24,9 +24,16 @@ import ( "github.com/prometheus/procfs" ) -func makeTestCPUCollector(s []procfs.CPUStat) *cpuCollector { - dup := make([]procfs.CPUStat, len(s)) - copy(dup, s) +func copyStats(d, s map[int64]procfs.CPUStat) { + for k := range s { + v := s[k] + d[k] = v + } +} + +func makeTestCPUCollector(s map[int64]procfs.CPUStat) *cpuCollector { + dup := make(map[int64]procfs.CPUStat, len(s)) + copyStats(dup, s) return &cpuCollector{ logger: log.NewNopLogger(), cpuStats: dup, @@ -34,32 +41,34 @@ func makeTestCPUCollector(s []procfs.CPUStat) *cpuCollector { } func TestCPU(t *testing.T) { - firstCPUStat := []procfs.CPUStat{{ - User: 100.0, - Nice: 100.0, - System: 100.0, - Idle: 100.0, - Iowait: 100.0, - IRQ: 100.0, - SoftIRQ: 100.0, - Steal: 100.0, - Guest: 100.0, - GuestNice: 100.0, - }} + firstCPUStat := map[int64]procfs.CPUStat{ + 0: { + User: 100.0, + Nice: 100.0, + System: 100.0, + Idle: 100.0, + Iowait: 100.0, + IRQ: 100.0, + SoftIRQ: 100.0, + Steal: 100.0, + Guest: 100.0, + GuestNice: 100.0, + }} c := makeTestCPUCollector(firstCPUStat) - want := []procfs.CPUStat{{ - User: 101.0, - Nice: 101.0, - System: 101.0, - Idle: 101.0, - Iowait: 101.0, - IRQ: 101.0, - SoftIRQ: 101.0, - Steal: 101.0, - Guest: 101.0, - GuestNice: 101.0, - }} + want := map[int64]procfs.CPUStat{ + 0: { + User: 101.0, + Nice: 101.0, + System: 101.0, + Idle: 101.0, + Iowait: 101.0, + IRQ: 101.0, + SoftIRQ: 101.0, + Steal: 101.0, + Guest: 101.0, + GuestNice: 101.0, + }} c.updateCPUStats(want) got := c.cpuStats if !reflect.DeepEqual(want, got) { @@ -67,18 +76,19 @@ func TestCPU(t *testing.T) { } c = makeTestCPUCollector(firstCPUStat) - jumpBack := []procfs.CPUStat{{ - User: 99.9, - Nice: 99.9, - System: 99.9, - Idle: 99.9, - Iowait: 99.9, - IRQ: 99.9, - SoftIRQ: 99.9, - Steal: 99.9, - Guest: 99.9, - GuestNice: 99.9, - }} + jumpBack := map[int64]procfs.CPUStat{ + 0: { + User: 99.9, + Nice: 99.9, + System: 99.9, + Idle: 99.9, + Iowait: 99.9, + IRQ: 99.9, + SoftIRQ: 99.9, + Steal: 99.9, + Guest: 99.9, + GuestNice: 99.9, + }} c.updateCPUStats(jumpBack) got = c.cpuStats if reflect.DeepEqual(jumpBack, got) { @@ -86,21 +96,107 @@ func TestCPU(t *testing.T) { } c = makeTestCPUCollector(firstCPUStat) - resetIdle := []procfs.CPUStat{{ - User: 102.0, - Nice: 102.0, - System: 102.0, - Idle: 1.0, - Iowait: 102.0, - IRQ: 102.0, - SoftIRQ: 102.0, - Steal: 102.0, - Guest: 102.0, - GuestNice: 102.0, - }} + resetIdle := map[int64]procfs.CPUStat{ + 0: { + User: 102.0, + Nice: 102.0, + System: 102.0, + Idle: 1.0, + Iowait: 102.0, + IRQ: 102.0, + SoftIRQ: 102.0, + Steal: 102.0, + Guest: 102.0, + GuestNice: 102.0, + }} c.updateCPUStats(resetIdle) got = c.cpuStats if !reflect.DeepEqual(resetIdle, got) { t.Fatalf("should have %v CPU Stat: got %v", resetIdle, got) } } + +func TestCPUOffline(t *testing.T) { + // CPU 1 goes offline. + firstCPUStat := map[int64]procfs.CPUStat{ + 0: { + User: 100.0, + Nice: 100.0, + System: 100.0, + Idle: 100.0, + Iowait: 100.0, + IRQ: 100.0, + SoftIRQ: 100.0, + Steal: 100.0, + Guest: 100.0, + GuestNice: 100.0, + }, + 1: { + User: 101.0, + Nice: 101.0, + System: 101.0, + Idle: 101.0, + Iowait: 101.0, + IRQ: 101.0, + SoftIRQ: 101.0, + Steal: 101.0, + Guest: 101.0, + GuestNice: 101.0, + }, + } + + c := makeTestCPUCollector(firstCPUStat) + want := map[int64]procfs.CPUStat{ + 0: { + User: 100.0, + Nice: 100.0, + System: 100.0, + Idle: 100.0, + Iowait: 100.0, + IRQ: 100.0, + SoftIRQ: 100.0, + Steal: 100.0, + Guest: 100.0, + GuestNice: 100.0, + }, + } + c.updateCPUStats(want) + got := c.cpuStats + if !reflect.DeepEqual(want, got) { + t.Fatalf("should have %v CPU Stat: got %v", want, got) + } + + // CPU 1 comes back online. + want = map[int64]procfs.CPUStat{ + 0: { + User: 100.0, + Nice: 100.0, + System: 100.0, + Idle: 100.0, + Iowait: 100.0, + IRQ: 100.0, + SoftIRQ: 100.0, + Steal: 100.0, + Guest: 100.0, + GuestNice: 100.0, + }, + 1: { + User: 101.0, + Nice: 101.0, + System: 101.0, + Idle: 101.0, + Iowait: 101.0, + IRQ: 101.0, + SoftIRQ: 101.0, + Steal: 101.0, + Guest: 101.0, + GuestNice: 101.0, + }, + } + c.updateCPUStats(want) + got = c.cpuStats + if !reflect.DeepEqual(want, got) { + t.Fatalf("should have %v CPU Stat: got %v", want, got) + } + +} diff --git a/collector/cpu_netbsd.go b/collector/cpu_netbsd.go new file mode 100644 index 0000000000..7fc95c8081 --- /dev/null +++ b/collector/cpu_netbsd.go @@ -0,0 +1,277 @@ +// Copyright 2023 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 !nocpu +// +build !nocpu + +package collector + +import ( + "errors" + "math" + "regexp" + "sort" + "strconv" + "strings" + "unsafe" + + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/unix" + + "howett.net/plist" +) + +type clockinfo struct { + hz int32 // clock frequency + tick int32 // micro-seconds per hz tick + spare int32 + stathz int32 // statistics clock frequency + profhz int32 // profiling clock frequency +} + +type cputime struct { + user float64 + nice float64 + sys float64 + intr float64 + idle float64 +} + +type plistref struct { + pref_plist unsafe.Pointer + pref_len uint64 +} + +type sysmonValues struct { + CurValue int `plist:"cur-value"` + Description string `plist:"description"` + State string `plist:"state"` + Type string `plist:"type"` +} + +type sysmonProperty []sysmonValues + +type sysmonProperties map[string]sysmonProperty + +func readBytes(ptr unsafe.Pointer, length uint64) []byte { + buf := make([]byte, length-1) + var i uint64 + for ; i < length-1; i++ { + buf[i] = *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(i))) + } + return buf +} + +func ioctl(fd int, nr int64, typ byte, size uintptr, retptr unsafe.Pointer) error { + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + // Some magicks derived from sys/ioccom.h. + uintptr((0x40000000|0x80000000)| + ((int64(size)&(1<<13-1))<<16)| + (int64(typ)<<8)| + nr, + ), + uintptr(retptr), + ) + if errno != 0 { + return errno + } + return nil +} + +func readSysmonProperties() (sysmonProperties, error) { + fd, err := unix.Open(rootfsFilePath("/dev/sysmon"), unix.O_RDONLY, 0777) + if err != nil { + return nil, err + } + defer unix.Close(fd) + + var retptr plistref + + if err = ioctl(fd, 0, 'E', unsafe.Sizeof(retptr), unsafe.Pointer(&retptr)); err != nil { + return nil, err + } + + bytes := readBytes(retptr.pref_plist, retptr.pref_len) + + var props sysmonProperties + if _, err = plist.Unmarshal(bytes, &props); err != nil { + return nil, err + } + return props, nil +} + +func sortFilterSysmonProperties(props sysmonProperties, prefix string) []string { + var keys []string + for key := range props { + if !strings.HasPrefix(key, prefix) { + continue + } + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +func convertTemperatures(prop sysmonProperty, res map[int]float64) error { + + for _, val := range prop { + if val.State == "invalid" || val.State == "unknown" || val.State == "" { + continue + } + + re := regexp.MustCompile("^cpu([0-9]+) temperature$") + core := re.FindStringSubmatch(val.Description)[1] + ncore, _ := strconv.Atoi(core) + temperature := ((float64(uint64(val.CurValue))) / 1000000) - 273.15 + res[ncore] = temperature + } + return nil +} + +func getCPUTemperatures() (map[int]float64, error) { + + res := make(map[int]float64) + + // Read all properties + props, err := readSysmonProperties() + if err != nil { + return res, err + } + + keys := sortFilterSysmonProperties(props, "coretemp") + for idx, _ := range keys { + convertTemperatures(props[keys[idx]], res) + } + + return res, nil +} + +func getCPUTimes() ([]cputime, error) { + const states = 5 + + clockb, err := unix.SysctlRaw("kern.clockrate") + if err != nil { + return nil, err + } + clock := *(*clockinfo)(unsafe.Pointer(&clockb[0])) + + var cpufreq float64 + if clock.stathz > 0 { + cpufreq = float64(clock.stathz) + } else { + cpufreq = float64(clock.hz) + } + + ncpusb, err := unix.SysctlRaw("hw.ncpu") + if err != nil { + return nil, err + } + ncpus := *(*int)(unsafe.Pointer(&ncpusb[0])) + + if ncpus < 1 { + return nil, errors.New("Invalid cpu number") + } + + var times []float64 + for ncpu := 0; ncpu < ncpus; ncpu++ { + cpb, err := unix.SysctlRaw("kern.cp_time", ncpu) + if err != nil { + return nil, err + } + for len(cpb) >= int(unsafe.Sizeof(int(0))) { + t := *(*int)(unsafe.Pointer(&cpb[0])) + times = append(times, float64(t)/cpufreq) + cpb = cpb[unsafe.Sizeof(int(0)):] + } + } + + cpus := make([]cputime, len(times)/states) + for i := 0; i < len(times); i += states { + cpu := &cpus[i/states] + cpu.user = times[i] + cpu.nice = times[i+1] + cpu.sys = times[i+2] + cpu.intr = times[i+3] + cpu.idle = times[i+4] + } + return cpus, nil +} + +type statCollector struct { + cpu typedDesc + temp typedDesc + logger log.Logger +} + +func init() { + registerCollector("cpu", defaultEnabled, NewStatCollector) +} + +// NewStatCollector returns a new Collector exposing CPU stats. +func NewStatCollector(logger log.Logger) (Collector, error) { + return &statCollector{ + cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue}, + temp: typedDesc{prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "temperature_celsius"), + "CPU temperature", + []string{"cpu"}, nil, + ), prometheus.GaugeValue}, + logger: logger, + }, nil +} + +// Expose CPU stats using sysctl. +func (c *statCollector) Update(ch chan<- prometheus.Metric) error { + // We want time spent per-cpu per CPUSTATE. + // CPUSTATES (number of CPUSTATES) is defined as 5U. + // Order: CP_USER | CP_NICE | CP_SYS | CP_IDLE | CP_INTR + // sysctl kern.cp_time.x provides CPUSTATES long integers: + // (space-separated list of the above variables, where + // x stands for the number of the CPU core) + // + // Each value is a counter incremented at frequency + // kern.clockrate.(stathz | hz) + // + // Look into sys/kern/kern_clock.c for details. + + cpuTimes, err := getCPUTimes() + if err != nil { + return err + } + + cpuTemperatures, err := getCPUTemperatures() + if err != nil { + return err + } + + for cpu, t := range cpuTimes { + lcpu := strconv.Itoa(cpu) + ch <- c.cpu.mustNewConstMetric(float64(t.user), lcpu, "user") + ch <- c.cpu.mustNewConstMetric(float64(t.nice), lcpu, "nice") + ch <- c.cpu.mustNewConstMetric(float64(t.sys), lcpu, "system") + ch <- c.cpu.mustNewConstMetric(float64(t.intr), lcpu, "interrupt") + ch <- c.cpu.mustNewConstMetric(float64(t.idle), lcpu, "idle") + + if temp, ok := cpuTemperatures[cpu]; ok { + ch <- c.temp.mustNewConstMetric(temp, lcpu) + } else { + level.Debug(c.logger).Log("msg", "no temperature information for CPU", "cpu", cpu) + ch <- c.temp.mustNewConstMetric(math.NaN(), lcpu) + } + } + return err +} diff --git a/collector/cpu_netbsd_test.go b/collector/cpu_netbsd_test.go new file mode 100644 index 0000000000..08498d52bf --- /dev/null +++ b/collector/cpu_netbsd_test.go @@ -0,0 +1,44 @@ +// Copyright 2023 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 !nocpu +// +build !nocpu + +package collector + +import ( + "runtime" + "testing" +) + +func TestCPUTimes(t *testing.T) { + times, err := getCPUTimes() + if err != nil { + t.Fatalf("getCPUTimes returned error: %v", err) + } + + if len(times) == 0 { + t.Fatalf("no CPU times found") + } + + if got, want := len(times), runtime.NumCPU(); got != want { + t.Fatalf("unexpected # of CPU times; got %d want %d", got, want) + } +} + +func TestCPUTemperatures(t *testing.T) { + _, err := getCPUTemperatures() + if err != nil { + t.Fatalf("getCPUTemperatures returned error: %v", err) + } +} diff --git a/collector/cpu_openbsd.go b/collector/cpu_openbsd.go index f025c08f8f..8715ff9885 100644 --- a/collector/cpu_openbsd.go +++ b/collector/cpu_openbsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build openbsd && !amd64 && !nocpu -// +build openbsd,!amd64,!nocpu +//go:build !nocpu +// +build !nocpu package collector @@ -25,11 +25,23 @@ import ( "golang.org/x/sys/unix" ) -/* -#include -#include -*/ -import "C" +const ( + CP_USER = iota + CP_NICE + CP_SYS + CP_SPIN + CP_INTR + CP_IDLE + CPUSTATES +) +const ( + CP_USER_O63 = iota + CP_NICE_O63 + CP_SYS_O63 + CP_INTR_O63 + CP_IDLE_O63 + CPUSTATES_O63 +) type cpuCollector struct { cpu typedDesc @@ -52,32 +64,41 @@ func (c *cpuCollector) Update(ch chan<- prometheus.Metric) (err error) { if err != nil { return err } - clock := *(*C.struct_clockinfo)(unsafe.Pointer(&clockb[0])) - hz := float64(clock.stathz) + clock := *(*unix.Clockinfo)(unsafe.Pointer(&clockb[0])) + hz := float64(clock.Stathz) ncpus, err := unix.SysctlUint32("hw.ncpu") if err != nil { return err } - var cpTime [][C.CPUSTATES]C.int64_t + var cpTime [][CPUSTATES]uint64 for i := 0; i < int(ncpus); i++ { cpb, err := unix.SysctlRaw("kern.cp_time2", i) if err != nil && err != unix.ENODEV { return err } if err != unix.ENODEV { - cpTime = append(cpTime, *(*[C.CPUSTATES]C.int64_t)(unsafe.Pointer(&cpb[0]))) + var times [CPUSTATES]uint64 + for n := 0; n < len(cpb); n += 8 { + times[n/8] = *(*uint64)(unsafe.Pointer(&cpb[n])) + } + if len(cpb)/8 == CPUSTATES_O63 { + copy(times[CP_INTR:], times[CP_INTR_O63:]) + times[CP_SPIN] = 0 + } + cpTime = append(cpTime, times) } } for cpu, time := range cpTime { lcpu := strconv.Itoa(cpu) - ch <- c.cpu.mustNewConstMetric(float64(time[C.CP_USER])/hz, lcpu, "user") - ch <- c.cpu.mustNewConstMetric(float64(time[C.CP_NICE])/hz, lcpu, "nice") - ch <- c.cpu.mustNewConstMetric(float64(time[C.CP_SYS])/hz, lcpu, "system") - ch <- c.cpu.mustNewConstMetric(float64(time[C.CP_INTR])/hz, lcpu, "interrupt") - ch <- c.cpu.mustNewConstMetric(float64(time[C.CP_IDLE])/hz, lcpu, "idle") + ch <- c.cpu.mustNewConstMetric(float64(time[CP_USER])/hz, lcpu, "user") + ch <- c.cpu.mustNewConstMetric(float64(time[CP_NICE])/hz, lcpu, "nice") + ch <- c.cpu.mustNewConstMetric(float64(time[CP_SYS])/hz, lcpu, "system") + ch <- c.cpu.mustNewConstMetric(float64(time[CP_SPIN])/hz, lcpu, "spin") + ch <- c.cpu.mustNewConstMetric(float64(time[CP_INTR])/hz, lcpu, "interrupt") + ch <- c.cpu.mustNewConstMetric(float64(time[CP_IDLE])/hz, lcpu, "idle") } return err } diff --git a/collector/cpu_openbsd_amd64.go b/collector/cpu_openbsd_amd64.go deleted file mode 100644 index b07d2ca702..0000000000 --- a/collector/cpu_openbsd_amd64.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2020 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 !nocpu -// +build !nocpu - -package collector - -import ( - "strconv" - "unsafe" - - "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" - "golang.org/x/sys/unix" -) - -type clockinfo struct { - hz int32 - tick int32 - tickadj int32 - stathz int32 - profhz int32 -} - -const ( - CP_USER = iota - CP_NICE - CP_SYS - CP_SPIN - CP_INTR - CP_IDLE - CPUSTATES -) - -type cpuCollector struct { - cpu typedDesc - logger log.Logger -} - -func init() { - registerCollector("cpu", defaultEnabled, NewCPUCollector) -} - -func NewCPUCollector(logger log.Logger) (Collector, error) { - return &cpuCollector{ - cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue}, - logger: logger, - }, nil -} - -func (c *cpuCollector) Update(ch chan<- prometheus.Metric) (err error) { - clockb, err := unix.SysctlRaw("kern.clockrate") - if err != nil { - return err - } - clock := *(*clockinfo)(unsafe.Pointer(&clockb[0])) - hz := float64(clock.stathz) - - ncpus, err := unix.SysctlUint32("hw.ncpu") - if err != nil { - return err - } - - var cpTime [][CPUSTATES]int64 - for i := 0; i < int(ncpus); i++ { - cpb, err := unix.SysctlRaw("kern.cp_time2", i) - if err != nil && err != unix.ENODEV { - return err - } - if err != unix.ENODEV { - cpTime = append(cpTime, *(*[CPUSTATES]int64)(unsafe.Pointer(&cpb[0]))) - } - } - - for cpu, time := range cpTime { - lcpu := strconv.Itoa(cpu) - ch <- c.cpu.mustNewConstMetric(float64(time[CP_USER])/hz, lcpu, "user") - ch <- c.cpu.mustNewConstMetric(float64(time[CP_NICE])/hz, lcpu, "nice") - ch <- c.cpu.mustNewConstMetric(float64(time[CP_SYS])/hz, lcpu, "system") - ch <- c.cpu.mustNewConstMetric(float64(time[CP_SPIN])/hz, lcpu, "spin") - ch <- c.cpu.mustNewConstMetric(float64(time[CP_INTR])/hz, lcpu, "interrupt") - ch <- c.cpu.mustNewConstMetric(float64(time[CP_IDLE])/hz, lcpu, "idle") - } - return err -} diff --git a/collector/cpu_solaris.go b/collector/cpu_solaris.go index c28b4d6dfc..32466a1e64 100644 --- a/collector/cpu_solaris.go +++ b/collector/cpu_solaris.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build solaris && !nocpu -// +build solaris,!nocpu +//go:build !nocpu +// +build !nocpu package collector diff --git a/collector/cpu_vulnerabilities_linux.go b/collector/cpu_vulnerabilities_linux.go new file mode 100644 index 0000000000..69a2c587e3 --- /dev/null +++ b/collector/cpu_vulnerabilities_linux.go @@ -0,0 +1,69 @@ +// Copyright 2023 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. + +package collector + +import ( + "fmt" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs/sysfs" +) + +const ( + cpuVulerabilitiesCollector = "cpu_vulnerabilities" +) + +var ( + vulnerabilityDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuVulerabilitiesCollector, "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, + ) +) + +type cpuVulnerabilitiesCollector struct{} + +func init() { + registerCollector(cpuVulerabilitiesCollector, defaultDisabled, NewVulnerabilitySysfsCollector) +} + +func NewVulnerabilitySysfsCollector(logger log.Logger) (Collector, error) { + return &cpuVulnerabilitiesCollector{}, nil +} + +func (v *cpuVulnerabilitiesCollector) Update(ch chan<- prometheus.Metric) error { + fs, err := sysfs.NewFS(*sysPath) + if err != nil { + return fmt.Errorf("failed to open sysfs: %w", err) + } + + vulnerabilities, err := fs.CPUVulnerabilities() + if err != nil { + return fmt.Errorf("failed to get vulnerabilities: %w", err) + } + + for _, vulnerability := range vulnerabilities { + ch <- prometheus.MustNewConstMetric( + vulnerabilityDesc, + prometheus.GaugeValue, + 1.0, + vulnerability.CodeName, + sysfs.VulnerabilityHumanEncoding[vulnerability.State], + vulnerability.Mitigation, + ) + } + return nil +} diff --git a/collector/cpufreq_common.go b/collector/cpufreq_common.go new file mode 100644 index 0000000000..e1eda58947 --- /dev/null +++ b/collector/cpufreq_common.go @@ -0,0 +1,59 @@ +// Copyright 2023 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 !nocpu +// +build !nocpu + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +var ( + cpuFreqHertzDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"), + "Current CPU thread frequency in hertz.", + []string{"cpu"}, nil, + ) + cpuFreqMinDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_min_hertz"), + "Minimum CPU thread frequency in hertz.", + []string{"cpu"}, nil, + ) + cpuFreqMaxDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_max_hertz"), + "Maximum CPU thread frequency in hertz.", + []string{"cpu"}, nil, + ) + cpuFreqScalingFreqDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "scaling_frequency_hertz"), + "Current scaled CPU thread frequency in hertz.", + []string{"cpu"}, nil, + ) + cpuFreqScalingFreqMinDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "scaling_frequency_min_hertz"), + "Minimum scaled CPU thread frequency in hertz.", + []string{"cpu"}, nil, + ) + cpuFreqScalingFreqMaxDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "scaling_frequency_max_hertz"), + "Maximum scaled CPU thread frequency in hertz.", + []string{"cpu"}, nil, + ) + cpuFreqScalingGovernorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "scaling_governor"), + "Current enabled CPU frequency governor.", + []string{"cpu", "governor"}, nil, + ) +) diff --git a/collector/cpufreq_linux.go b/collector/cpufreq_linux.go index ce431cc06e..3372be1ab6 100644 --- a/collector/cpufreq_linux.go +++ b/collector/cpufreq_linux.go @@ -18,21 +18,15 @@ package collector import ( "fmt" - "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/sysfs" + "strings" ) type cpuFreqCollector struct { - fs sysfs.FS - cpuFreq *prometheus.Desc - cpuFreqMin *prometheus.Desc - cpuFreqMax *prometheus.Desc - scalingFreq *prometheus.Desc - scalingFreqMin *prometheus.Desc - scalingFreqMax *prometheus.Desc - logger log.Logger + fs sysfs.FS + logger log.Logger } func init() { @@ -47,37 +41,7 @@ func NewCPUFreqCollector(logger log.Logger) (Collector, error) { } return &cpuFreqCollector{ - fs: fs, - cpuFreq: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"), - "Current cpu thread frequency in hertz.", - []string{"cpu"}, nil, - ), - cpuFreqMin: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_min_hertz"), - "Minimum cpu thread frequency in hertz.", - []string{"cpu"}, nil, - ), - cpuFreqMax: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_max_hertz"), - "Maximum cpu thread frequency in hertz.", - []string{"cpu"}, nil, - ), - scalingFreq: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "scaling_frequency_hertz"), - "Current scaled CPU thread frequency in hertz.", - []string{"cpu"}, nil, - ), - scalingFreqMin: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "scaling_frequency_min_hertz"), - "Minimum scaled CPU thread frequency in hertz.", - []string{"cpu"}, nil, - ), - scalingFreqMax: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "scaling_frequency_max_hertz"), - "Maximum scaled CPU thread frequency in hertz.", - []string{"cpu"}, nil, - ), + fs: fs, logger: logger, }, nil } @@ -94,7 +58,7 @@ func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { for _, stats := range cpuFreqs { if stats.CpuinfoCurrentFrequency != nil { ch <- prometheus.MustNewConstMetric( - c.cpuFreq, + cpuFreqHertzDesc, prometheus.GaugeValue, float64(*stats.CpuinfoCurrentFrequency)*1000.0, stats.Name, @@ -102,7 +66,7 @@ func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { } if stats.CpuinfoMinimumFrequency != nil { ch <- prometheus.MustNewConstMetric( - c.cpuFreqMin, + cpuFreqMinDesc, prometheus.GaugeValue, float64(*stats.CpuinfoMinimumFrequency)*1000.0, stats.Name, @@ -110,7 +74,7 @@ func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { } if stats.CpuinfoMaximumFrequency != nil { ch <- prometheus.MustNewConstMetric( - c.cpuFreqMax, + cpuFreqMaxDesc, prometheus.GaugeValue, float64(*stats.CpuinfoMaximumFrequency)*1000.0, stats.Name, @@ -118,7 +82,7 @@ func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { } if stats.ScalingCurrentFrequency != nil { ch <- prometheus.MustNewConstMetric( - c.scalingFreq, + cpuFreqScalingFreqDesc, prometheus.GaugeValue, float64(*stats.ScalingCurrentFrequency)*1000.0, stats.Name, @@ -126,7 +90,7 @@ func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { } if stats.ScalingMinimumFrequency != nil { ch <- prometheus.MustNewConstMetric( - c.scalingFreqMin, + cpuFreqScalingFreqMinDesc, prometheus.GaugeValue, float64(*stats.ScalingMinimumFrequency)*1000.0, stats.Name, @@ -134,12 +98,28 @@ func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { } if stats.ScalingMaximumFrequency != nil { ch <- prometheus.MustNewConstMetric( - c.scalingFreqMax, + cpuFreqScalingFreqMaxDesc, prometheus.GaugeValue, float64(*stats.ScalingMaximumFrequency)*1000.0, stats.Name, ) } + if stats.Governor != "" { + availableGovernors := strings.Split(stats.AvailableGovernors, " ") + for _, g := range availableGovernors { + state := 0 + if g == stats.Governor { + state = 1 + } + ch <- prometheus.MustNewConstMetric( + cpuFreqScalingGovernorDesc, + prometheus.GaugeValue, + float64(state), + stats.Name, + g, + ) + } + } } return nil } diff --git a/collector/cpufreq_solaris.go b/collector/cpufreq_solaris.go index 10883ce404..c3fb9ee687 100644 --- a/collector/cpufreq_solaris.go +++ b/collector/cpufreq_solaris.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build solaris && !nocpu -// +build solaris,!nocpu +//go:build !nocpu +// +build !nocpu package collector @@ -29,9 +29,7 @@ import ( import "C" type cpuFreqCollector struct { - cpuFreq *prometheus.Desc - cpuFreqMax *prometheus.Desc - logger log.Logger + logger log.Logger } func init() { @@ -40,16 +38,6 @@ func init() { func NewCpuFreqCollector(logger log.Logger) (Collector, error) { return &cpuFreqCollector{ - cpuFreq: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"), - "Current CPU thread frequency in hertz.", - []string{"cpu"}, nil, - ), - cpuFreqMax: prometheus.NewDesc( - prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_max_hertz"), - "Maximum CPU thread frequency in hertz.", - []string{"cpu"}, nil, - ), logger: logger, }, nil } @@ -81,14 +69,14 @@ func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { lcpu := strconv.Itoa(cpu) ch <- prometheus.MustNewConstMetric( - c.cpuFreq, + cpuFreqHertzDesc, prometheus.GaugeValue, float64(cpuFreqV.UintVal), lcpu, ) // Multiply by 1e+6 to convert MHz to Hz. ch <- prometheus.MustNewConstMetric( - c.cpuFreqMax, + cpuFreqMaxDesc, prometheus.GaugeValue, float64(cpuFreqMaxV.IntVal)*1e+6, lcpu, diff --git a/collector/netdev_filter.go b/collector/device_filter.go similarity index 76% rename from collector/netdev_filter.go rename to collector/device_filter.go index e809c499e3..d8a38a2970 100644 --- a/collector/netdev_filter.go +++ b/collector/device_filter.go @@ -17,12 +17,12 @@ import ( "regexp" ) -type netDevFilter struct { +type deviceFilter struct { ignorePattern *regexp.Regexp acceptPattern *regexp.Regexp } -func newNetDevFilter(ignoredPattern, acceptPattern string) (f netDevFilter) { +func newDeviceFilter(ignoredPattern, acceptPattern string) (f deviceFilter) { if ignoredPattern != "" { f.ignorePattern = regexp.MustCompile(ignoredPattern) } @@ -34,8 +34,8 @@ func newNetDevFilter(ignoredPattern, acceptPattern string) (f netDevFilter) { return } -// ignores returns whether the device should be ignored -func (f *netDevFilter) ignored(name string) bool { - return ((f.ignorePattern != nil && f.ignorePattern.MatchString(name)) || - (f.acceptPattern != nil && !f.acceptPattern.MatchString(name))) +// ignored returns whether the device should be ignored +func (f *deviceFilter) ignored(name string) bool { + return (f.ignorePattern != nil && f.ignorePattern.MatchString(name)) || + (f.acceptPattern != nil && !f.acceptPattern.MatchString(name)) } diff --git a/collector/netdev_filter_test.go b/collector/device_filter_test.go similarity index 92% rename from collector/netdev_filter_test.go rename to collector/device_filter_test.go index 13cebbc68a..7332f1cdb4 100644 --- a/collector/netdev_filter_test.go +++ b/collector/device_filter_test.go @@ -17,7 +17,7 @@ import ( "testing" ) -func TestNetDevFilter(t *testing.T) { +func TestDeviceFilter(t *testing.T) { tests := []struct { ignore string accept string @@ -33,7 +33,7 @@ func TestNetDevFilter(t *testing.T) { } for _, test := range tests { - filter := newNetDevFilter(test.ignore, test.accept) + filter := newDeviceFilter(test.ignore, test.accept) result := filter.ignored(test.name) if result != test.expectedResult { diff --git a/collector/diskstats_common.go b/collector/diskstats_common.go index 0f6bbe4694..2ab84438e7 100644 --- a/collector/diskstats_common.go +++ b/collector/diskstats_common.go @@ -18,6 +18,11 @@ package collector import ( + "errors" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" ) @@ -28,6 +33,21 @@ const ( var ( diskLabelNames = []string{"device"} + diskstatsDeviceExcludeSet bool + diskstatsDeviceExclude = kingpin.Flag( + "collector.diskstats.device-exclude", + "Regexp of diskstats devices to exclude (mutually exclusive to device-include).", + ).Default(diskstatsDefaultIgnoredDevices).PreAction(func(c *kingpin.ParseContext) error { + diskstatsDeviceExcludeSet = true + return nil + }).String() + oldDiskstatsDeviceExclude = kingpin.Flag( + "collector.diskstats.ignored-devices", + "DEPRECATED: Use collector.diskstats.device-exclude", + ).Hidden().String() + + diskstatsDeviceInclude = kingpin.Flag("collector.diskstats.device-include", "Regexp of diskstats devices to include (mutually exclusive to device-exclude).").String() + readsCompletedDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, diskSubsystem, "reads_completed_total"), "The total number of reads completed successfully.", @@ -72,3 +92,28 @@ var ( nil, ) ) + +func newDiskstatsDeviceFilter(logger log.Logger) (deviceFilter, error) { + if *oldDiskstatsDeviceExclude != "" { + if !diskstatsDeviceExcludeSet { + level.Warn(logger).Log("msg", "--collector.diskstats.ignored-devices is DEPRECATED and will be removed in 2.0.0, use --collector.diskstats.device-exclude") + *diskstatsDeviceExclude = *oldDiskstatsDeviceExclude + } else { + return deviceFilter{}, errors.New("--collector.diskstats.ignored-devices and --collector.diskstats.device-exclude are mutually exclusive") + } + } + + if *diskstatsDeviceExclude != "" && *diskstatsDeviceInclude != "" { + return deviceFilter{}, errors.New("device-exclude & device-include are mutually exclusive") + } + + if *diskstatsDeviceExclude != "" { + level.Info(logger).Log("msg", "Parsed flag --collector.diskstats.device-exclude", "flag", *diskstatsDeviceExclude) + } + + if *diskstatsDeviceInclude != "" { + level.Info(logger).Log("msg", "Parsed Flag --collector.diskstats.device-include", "flag", *diskstatsDeviceInclude) + } + + return newDeviceFilter(*diskstatsDeviceExclude, *diskstatsDeviceInclude), nil +} diff --git a/collector/diskstats_darwin.go b/collector/diskstats_darwin.go index 350c44f1cc..b5f6c53844 100644 --- a/collector/diskstats_darwin.go +++ b/collector/diskstats_darwin.go @@ -24,14 +24,18 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +const diskstatsDefaultIgnoredDevices = "" + type typedDescFunc struct { typedDesc value func(stat *iostat.DriveStats) float64 } type diskstatsCollector struct { - descs []typedDescFunc - logger log.Logger + descs []typedDescFunc + + deviceFilter deviceFilter + logger log.Logger } func init() { @@ -42,6 +46,11 @@ func init() { func NewDiskstatsCollector(logger log.Logger) (Collector, error) { var diskLabelNames = []string{"device"} + deviceFilter, err := newDiskstatsDeviceFilter(logger) + if err != nil { + return nil, fmt.Errorf("failed to parse device filter flags: %w", err) + } + return &diskstatsCollector{ descs: []typedDescFunc{ { @@ -183,7 +192,9 @@ func NewDiskstatsCollector(logger log.Logger) (Collector, error) { }, }, }, - logger: logger, + + deviceFilter: deviceFilter, + logger: logger, }, nil } @@ -194,6 +205,9 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) error { } for _, stats := range diskStats { + if c.deviceFilter.ignored(stats.Name) { + continue + } for _, desc := range c.descs { v := desc.value(stats) ch <- desc.mustNewConstMetric(v, stats.Name) diff --git a/collector/diskstats_linux.go b/collector/diskstats_linux.go index b79d6bd398..ed5d044a61 100644 --- a/collector/diskstats_linux.go +++ b/collector/diskstats_linux.go @@ -17,22 +17,53 @@ package collector import ( + "bufio" "fmt" - "regexp" + "os" + "strconv" + "strings" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/blockdevice" - "gopkg.in/alecthomas/kingpin.v2" ) const ( secondsPerTick = 1.0 / 1000.0 -) -var ( - ignoredDevices = kingpin.Flag("collector.diskstats.ignored-devices", "Regexp of devices to ignore for diskstats.").Default("^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$").String() + // Read sectors and write sectors are the "standard UNIX 512-byte sectors, not any device- or filesystem-specific block size." + // See also https://www.kernel.org/doc/Documentation/block/stat.txt + unixSectorSize = 512.0 + + diskstatsDefaultIgnoredDevices = "^(z?ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$" + + // See udevadm(8). + udevDevicePropertyPrefix = "E:" + + // Udev device properties. + udevDMLVLayer = "DM_LV_LAYER" + udevDMLVName = "DM_LV_NAME" + udevDMName = "DM_NAME" + udevDMUUID = "DM_UUID" + udevDMVGName = "DM_VG_NAME" + udevIDATA = "ID_ATA" + udevIDATARotationRateRPM = "ID_ATA_ROTATION_RATE_RPM" + udevIDATASATA = "ID_ATA_SATA" + udevIDATASATASignalRateGen1 = "ID_ATA_SATA_SIGNAL_RATE_GEN1" + udevIDATASATASignalRateGen2 = "ID_ATA_SATA_SIGNAL_RATE_GEN2" + udevIDATAWriteCache = "ID_ATA_WRITE_CACHE" + udevIDATAWriteCacheEnabled = "ID_ATA_WRITE_CACHE_ENABLED" + udevIDFSType = "ID_FS_TYPE" + udevIDFSUsage = "ID_FS_USAGE" + udevIDFSUUID = "ID_FS_UUID" + udevIDFSVersion = "ID_FS_VERSION" + udevIDModel = "ID_MODEL" + udevIDPath = "ID_PATH" + udevIDRevision = "ID_REVISION" + udevIDSerialShort = "ID_SERIAL_SHORT" + udevIDWWN = "ID_WWN" + udevSCSIIdentSerial = "SCSI_IDENT_SERIAL" ) type typedFactorDesc struct { @@ -40,16 +71,22 @@ type typedFactorDesc struct { valueType prometheus.ValueType } +type udevInfo map[string]string + func (d *typedFactorDesc) mustNewConstMetric(value float64, labels ...string) prometheus.Metric { return prometheus.MustNewConstMetric(d.desc, d.valueType, value, labels...) } type diskstatsCollector struct { - ignoredDevicesPattern *regexp.Regexp - fs blockdevice.FS - infoDesc typedFactorDesc - descs []typedFactorDesc - logger log.Logger + deviceFilter deviceFilter + fs blockdevice.FS + infoDesc typedFactorDesc + descs []typedFactorDesc + filesystemInfoDesc typedFactorDesc + deviceMapperInfoDesc typedFactorDesc + ataDescs map[string]typedFactorDesc + logger log.Logger + getUdevDeviceProperties func(uint32, uint32) (udevInfo, error) } func init() { @@ -65,13 +102,18 @@ func NewDiskstatsCollector(logger log.Logger) (Collector, error) { return nil, fmt.Errorf("failed to open sysfs: %w", err) } - return &diskstatsCollector{ - ignoredDevicesPattern: regexp.MustCompile(*ignoredDevices), - fs: fs, + deviceFilter, err := newDiskstatsDeviceFilter(logger) + if err != nil { + return nil, fmt.Errorf("failed to parse device filter flags: %w", err) + } + + collector := diskstatsCollector{ + deviceFilter: deviceFilter, + fs: fs, infoDesc: typedFactorDesc{ desc: prometheus.NewDesc(prometheus.BuildFQName(namespace, diskSubsystem, "info"), "Info of /sys/block/.", - []string{"device", "major", "minor"}, + []string{"device", "major", "minor", "path", "wwn", "model", "serial", "revision"}, nil, ), valueType: prometheus.GaugeValue, }, @@ -178,8 +220,54 @@ func NewDiskstatsCollector(logger log.Logger) (Collector, error) { ), valueType: prometheus.CounterValue, }, }, + filesystemInfoDesc: typedFactorDesc{ + desc: prometheus.NewDesc(prometheus.BuildFQName(namespace, diskSubsystem, "filesystem_info"), + "Info about disk filesystem.", + []string{"device", "type", "usage", "uuid", "version"}, + nil, + ), valueType: prometheus.GaugeValue, + }, + deviceMapperInfoDesc: typedFactorDesc{ + desc: prometheus.NewDesc(prometheus.BuildFQName(namespace, diskSubsystem, "device_mapper_info"), + "Info about disk device mapper.", + []string{"device", "name", "uuid", "vg_name", "lv_name", "lv_layer"}, + nil, + ), valueType: prometheus.GaugeValue, + }, + ataDescs: map[string]typedFactorDesc{ + udevIDATAWriteCache: { + desc: prometheus.NewDesc(prometheus.BuildFQName(namespace, diskSubsystem, "ata_write_cache"), + "ATA disk has a write cache.", + []string{"device"}, + nil, + ), valueType: prometheus.GaugeValue, + }, + udevIDATAWriteCacheEnabled: { + desc: prometheus.NewDesc(prometheus.BuildFQName(namespace, diskSubsystem, "ata_write_cache_enabled"), + "ATA disk has its write cache enabled.", + []string{"device"}, + nil, + ), valueType: prometheus.GaugeValue, + }, + udevIDATARotationRateRPM: { + desc: prometheus.NewDesc(prometheus.BuildFQName(namespace, diskSubsystem, "ata_rotation_rate_rpm"), + "ATA disk rotation rate in RPMs (0 for SSDs).", + []string{"device"}, + nil, + ), valueType: prometheus.GaugeValue, + }, + }, logger: logger, - }, nil + } + + // Only enable getting device properties from udev if the directory is readable. + if stat, err := os.Stat(*udevDataPath); err != nil || !stat.IsDir() { + level.Error(logger).Log("msg", "Failed to open directory, disabling udev device properties", "path", *udevDataPath) + } else { + collector.getUdevDeviceProperties = getUdevDeviceProperties + } + + return &collector, nil } func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) error { @@ -190,31 +278,43 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) error { for _, stats := range diskStats { dev := stats.DeviceName - if c.ignoredDevicesPattern.MatchString(dev) { - level.Debug(c.logger).Log("msg", "Ignoring device", "device", dev, "pattern", c.ignoredDevicesPattern) + if c.deviceFilter.ignored(dev) { continue } - diskSectorSize := 512.0 - blockQueue, err := c.fs.SysBlockDeviceQueueStats(dev) + info, err := getUdevDeviceProperties(stats.MajorNumber, stats.MinorNumber) if err != nil { - level.Debug(c.logger).Log("msg", "Error getting queue stats", "device", dev, "err", err) - } else { - diskSectorSize = float64(blockQueue.LogicalBlockSize) + level.Debug(c.logger).Log("msg", "Failed to parse udev info", "err", err) } - ch <- c.infoDesc.mustNewConstMetric(1.0, dev, fmt.Sprint(stats.MajorNumber), fmt.Sprint(stats.MinorNumber)) + // This is usually the serial printed on the disk label. + serial := info[udevSCSIIdentSerial] + + // If it's undefined, fallback to ID_SERIAL_SHORT instead. + if serial == "" { + serial = info[udevIDSerialShort] + } + + ch <- c.infoDesc.mustNewConstMetric(1.0, dev, + fmt.Sprint(stats.MajorNumber), + fmt.Sprint(stats.MinorNumber), + info[udevIDPath], + info[udevIDWWN], + info[udevIDModel], + serial, + info[udevIDRevision], + ) statCount := stats.IoStatsCount - 3 // Total diskstats record count, less MajorNumber, MinorNumber and DeviceName for i, val := range []float64{ float64(stats.ReadIOs), float64(stats.ReadMerges), - float64(stats.ReadSectors) * diskSectorSize, + float64(stats.ReadSectors) * unixSectorSize, float64(stats.ReadTicks) * secondsPerTick, float64(stats.WriteIOs), float64(stats.WriteMerges), - float64(stats.WriteSectors) * diskSectorSize, + float64(stats.WriteSectors) * unixSectorSize, float64(stats.WriteTicks) * secondsPerTick, float64(stats.IOsInProgress), float64(stats.IOsTotalTicks) * secondsPerTick, @@ -231,6 +331,77 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) error { } ch <- c.descs[i].mustNewConstMetric(val, dev) } + + if fsType := info[udevIDFSType]; fsType != "" { + ch <- c.filesystemInfoDesc.mustNewConstMetric(1.0, dev, + fsType, + info[udevIDFSUsage], + info[udevIDFSUUID], + info[udevIDFSVersion], + ) + } + + if name := info[udevDMName]; name != "" { + ch <- c.deviceMapperInfoDesc.mustNewConstMetric(1.0, dev, + name, + info[udevDMUUID], + info[udevDMVGName], + info[udevDMLVName], + info[udevDMLVLayer], + ) + } + + if ata := info[udevIDATA]; ata != "" { + for attr, desc := range c.ataDescs { + str, ok := info[attr] + if !ok { + level.Debug(c.logger).Log("msg", "Udev attribute does not exist", "attribute", attr) + continue + } + + if value, err := strconv.ParseFloat(str, 64); err == nil { + ch <- desc.mustNewConstMetric(value, dev) + } else { + level.Error(c.logger).Log("msg", "Failed to parse ATA value", "err", err) + } + } + } } return nil } + +func getUdevDeviceProperties(major, minor uint32) (udevInfo, error) { + filename := udevDataFilePath(fmt.Sprintf("b%d:%d", major, minor)) + + data, err := os.Open(filename) + if err != nil { + return nil, err + } + defer data.Close() + + info := make(udevInfo) + + scanner := bufio.NewScanner(data) + for scanner.Scan() { + line := scanner.Text() + + // We're only interested in device properties. + if !strings.HasPrefix(line, udevDevicePropertyPrefix) { + continue + } + + line = strings.TrimPrefix(line, udevDevicePropertyPrefix) + + /* TODO: After we drop support for Go 1.17, the condition below can be simplified to: + + if name, value, found := strings.Cut(line, "="); found { + info[name] = value + } + */ + if fields := strings.SplitN(line, "=", 2); len(fields) == 2 { + info[fields[0]] = fields[1] + } + } + + return info, nil +} diff --git a/collector/diskstats_linux_test.go b/collector/diskstats_linux_test.go index 0e8dc84ff2..8e969c3e3a 100644 --- a/collector/diskstats_linux_test.go +++ b/collector/diskstats_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nodiskstats +// +build !nodiskstats + package collector import ( @@ -49,8 +52,32 @@ func NewTestDiskStatsCollector(logger log.Logger) (prometheus.Collector, error) func TestDiskStats(t *testing.T) { *sysPath = "fixtures/sys" *procPath = "fixtures/proc" - *ignoredDevices = "^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$" - testcase := `# HELP node_disk_discard_time_seconds_total This is the total number of seconds spent by all discards. + *udevDataPath = "fixtures/udev/data" + *diskstatsDeviceExclude = "^(z?ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$" + testcase := `# HELP node_disk_ata_rotation_rate_rpm ATA disk rotation rate in RPMs (0 for SSDs). +# TYPE node_disk_ata_rotation_rate_rpm gauge +node_disk_ata_rotation_rate_rpm{device="sda"} 7200 +node_disk_ata_rotation_rate_rpm{device="sdb"} 0 +node_disk_ata_rotation_rate_rpm{device="sdc"} 0 +# HELP node_disk_ata_write_cache ATA disk has a write cache. +# TYPE node_disk_ata_write_cache gauge +node_disk_ata_write_cache{device="sda"} 1 +node_disk_ata_write_cache{device="sdb"} 1 +node_disk_ata_write_cache{device="sdc"} 1 +# HELP node_disk_ata_write_cache_enabled ATA disk has its write cache enabled. +# TYPE node_disk_ata_write_cache_enabled gauge +node_disk_ata_write_cache_enabled{device="sda"} 0 +node_disk_ata_write_cache_enabled{device="sdb"} 1 +node_disk_ata_write_cache_enabled{device="sdc"} 0 +# HELP node_disk_device_mapper_info Info about disk device mapper. +# TYPE node_disk_device_mapper_info gauge +node_disk_device_mapper_info{device="dm-0",lv_layer="",lv_name="",name="nvme0n1_crypt",uuid="CRYPT-LUKS2-jolaulot80fy9zsiobkxyxo7y2dqeho2-nvme0n1_crypt",vg_name=""} 1 +node_disk_device_mapper_info{device="dm-1",lv_layer="",lv_name="swap_1",name="system-swap_1",uuid="LVM-wbGqQEBL9SxrW2DLntJwgg8fAv946hw3Tvjqh0v31fWgxEtD4BoHO0lROWFUY65T",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-2",lv_layer="",lv_name="root",name="system-root",uuid="LVM-NWEDo8q5ABDyJuC3F8veKNyWfYmeIBfFMS4MF3HakzUhkk7ekDm6fJTHkl2fYHe7",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-3",lv_layer="",lv_name="var",name="system-var",uuid="LVM-hrxHo0rlZ6U95ku5841Lpd17bS1Z7V7lrtEE60DVgE6YEOCdS9gcDGyonWim4hGP",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-4",lv_layer="",lv_name="tmp",name="system-tmp",uuid="LVM-XTNGOHjPWLHcxmJmVu5cWTXEtuzqDeBkdEHAZW5q9LxWQ2d4mb5CchUQzUPJpl8H",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-5",lv_layer="",lv_name="home",name="system-home",uuid="LVM-MtoJaWTpjWRXlUnNFlpxZauTEuYlMvGFutigEzCCrfj8CNh6jCRi5LQJXZCpLjPf",vg_name="system"} 1 +# HELP node_disk_discard_time_seconds_total This is the total number of seconds spent by all discards. # TYPE node_disk_discard_time_seconds_total counter node_disk_discard_time_seconds_total{device="sdb"} 11.13 node_disk_discard_time_seconds_total{device="sdc"} 11.13 @@ -66,6 +93,18 @@ node_disk_discards_completed_total{device="sdc"} 18851 # TYPE node_disk_discards_merged_total counter node_disk_discards_merged_total{device="sdb"} 0 node_disk_discards_merged_total{device="sdc"} 0 +# HELP node_disk_filesystem_info Info about disk filesystem. +# TYPE node_disk_filesystem_info gauge +node_disk_filesystem_info{device="dm-0",type="LVM2_member",usage="raid",uuid="c3C3uW-gD96-Yw69-c1CJ-5MwT-6ysM-mST0vB",version="LVM2 001"} 1 +node_disk_filesystem_info{device="dm-1",type="swap",usage="other",uuid="5272bb60-04b5-49cd-b730-be57c7604450",version="1"} 1 +node_disk_filesystem_info{device="dm-2",type="ext4",usage="filesystem",uuid="3deafd0d-faff-4695-8d15-51061ae1f51b",version="1.0"} 1 +node_disk_filesystem_info{device="dm-3",type="ext4",usage="filesystem",uuid="5c772222-f7d4-4c8e-87e8-e97df6b7a45e",version="1.0"} 1 +node_disk_filesystem_info{device="dm-4",type="ext4",usage="filesystem",uuid="a9479d44-60e1-4015-a1e5-bb065e6dd11b",version="1.0"} 1 +node_disk_filesystem_info{device="dm-5",type="ext4",usage="filesystem",uuid="b05b726a-c718-4c4d-8641-7c73a7696d83",version="1.0"} 1 +node_disk_filesystem_info{device="mmcblk0p1",type="vfat",usage="filesystem",uuid="6284-658D",version="FAT32"} 1 +node_disk_filesystem_info{device="mmcblk0p2",type="ext4",usage="filesystem",uuid="83324ce8-a6f3-4e35-ad64-dbb3d6b87a32",version="1.0"} 1 +node_disk_filesystem_info{device="sda",type="LVM2_member",usage="raid",uuid="cVVv6j-HSA2-IY33-1Jmj-dO2H-YL7w-b4Oxqw",version="LVM2 001"} 1 +node_disk_filesystem_info{device="sdc",type="LVM2_member",usage="raid",uuid="QFy9W7-Brj3-hQ6v-AF8i-3Zqg-n3Vs-kGY4vb",version="LVM2 001"} 1 # HELP node_disk_flush_requests_time_seconds_total This is the total number of seconds spent by all flush requests. # TYPE node_disk_flush_requests_time_seconds_total counter node_disk_flush_requests_time_seconds_total{device="sdc"} 1.944 @@ -74,21 +113,21 @@ node_disk_flush_requests_time_seconds_total{device="sdc"} 1.944 node_disk_flush_requests_total{device="sdc"} 1555 # HELP node_disk_info Info of /sys/block/. # TYPE node_disk_info gauge -node_disk_info{device="dm-0",major="252",minor="0"} 1 -node_disk_info{device="dm-1",major="252",minor="1"} 1 -node_disk_info{device="dm-2",major="252",minor="2"} 1 -node_disk_info{device="dm-3",major="252",minor="3"} 1 -node_disk_info{device="dm-4",major="252",minor="4"} 1 -node_disk_info{device="dm-5",major="252",minor="5"} 1 -node_disk_info{device="mmcblk0",major="179",minor="0"} 1 -node_disk_info{device="mmcblk0p1",major="179",minor="1"} 1 -node_disk_info{device="mmcblk0p2",major="179",minor="2"} 1 -node_disk_info{device="nvme0n1",major="259",minor="0"} 1 -node_disk_info{device="sda",major="8",minor="0"} 1 -node_disk_info{device="sdb",major="8",minor="0"} 1 -node_disk_info{device="sdc",major="8",minor="0"} 1 -node_disk_info{device="sr0",major="11",minor="0"} 1 -node_disk_info{device="vda",major="254",minor="0"} 1 +node_disk_info{device="dm-0",major="252",minor="0",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-1",major="252",minor="1",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-2",major="252",minor="2",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-3",major="252",minor="3",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-4",major="252",minor="4",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-5",major="252",minor="5",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0",major="179",minor="0",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0p1",major="179",minor="1",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0p2",major="179",minor="2",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="nvme0n1",major="259",minor="0",model="SAMSUNG EHFTF55LURSY-000Y9",path="pci-0000:02:00.0-nvme-1",revision="4NBTUY95",serial="S252B6CU1HG3M1",wwn="eui.p3vbbiejx5aae2r3"} 1 +node_disk_info{device="sda",major="8",minor="0",model="TOSHIBA_KSDB4U86",path="pci-0000:3b:00.0-sas-phy7-lun-0",revision="0102",serial="2160A0D5FVGG",wwn="0x7c72382b8de36a64"} 1 +node_disk_info{device="sdb",major="8",minor="16",model="SuperMicro_SSD",path="pci-0000:00:1f.2-ata-1",revision="0R",serial="SMC0E1B87ABBB16BD84E",wwn="0xe1b87abbb16bd84e"} 1 +node_disk_info{device="sdc",major="8",minor="32",model="INTEL_SSDS9X9SI0",path="pci-0000:00:1f.2-ata-4",revision="0100",serial="3EWB5Y25CWQWA7EH1U",wwn="0x58907ddc573a5de"} 1 +node_disk_info{device="sr0",major="11",minor="0",model="Virtual_CDROM0",path="pci-0000:00:14.0-usb-0:1.1:1.0-scsi-0:0:0:0",revision="1.00",serial="AAAABBBBCCCC1",wwn=""} 1 +node_disk_info{device="vda",major="254",minor="0",model="",path="pci-0000:00:06.0",revision="",serial="",wwn=""} 1 # HELP node_disk_io_now The number of I/Os currently in progress. # TYPE node_disk_io_now gauge node_disk_io_now{device="dm-0"} 0 diff --git a/collector/diskstats_openbsd.go b/collector/diskstats_openbsd.go index dd4f0b037c..2a69042aac 100644 --- a/collector/diskstats_openbsd.go +++ b/collector/diskstats_openbsd.go @@ -11,12 +11,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build openbsd && !amd64 && !nodiskstats -// +build openbsd,!amd64,!nodiskstats +//go:build !nodiskstats && !amd64 +// +build !nodiskstats,!amd64 package collector import ( + "fmt" "unsafe" "github.com/go-kit/log" @@ -30,13 +31,17 @@ import ( */ import "C" +const diskstatsDefaultIgnoredDevices = "" + type diskstatsCollector struct { rxfer typedDesc rbytes typedDesc wxfer typedDesc wbytes typedDesc time typedDesc - logger log.Logger + + deviceFilter deviceFilter + logger log.Logger } func init() { @@ -45,13 +50,20 @@ func init() { // NewDiskstatsCollector returns a new Collector exposing disk device stats. func NewDiskstatsCollector(logger log.Logger) (Collector, error) { + deviceFilter, err := newDiskstatsDeviceFilter(logger) + if err != nil { + return nil, fmt.Errorf("failed to parse device filter flags: %w", err) + } + return &diskstatsCollector{ rxfer: typedDesc{readsCompletedDesc, prometheus.CounterValue}, rbytes: typedDesc{readBytesDesc, prometheus.CounterValue}, wxfer: typedDesc{writesCompletedDesc, prometheus.CounterValue}, wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue}, time: typedDesc{ioTimeSecondsDesc, prometheus.CounterValue}, - logger: logger, + + deviceFilter: deviceFilter, + logger: logger, }, nil } @@ -66,6 +78,9 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) (err error) { for i := 0; i < ndisks; i++ { diskname := C.GoString(&diskstats[i].ds_name[0]) + if c.deviceFilter.ignored(diskname) { + continue + } ch <- c.rxfer.mustNewConstMetric(float64(diskstats[i].ds_rxfer), diskname) ch <- c.rbytes.mustNewConstMetric(float64(diskstats[i].ds_rbytes), diskname) diff --git a/collector/diskstats_openbsd_amd64.go b/collector/diskstats_openbsd_amd64.go index 41265e233b..a39cabb538 100644 --- a/collector/diskstats_openbsd_amd64.go +++ b/collector/diskstats_openbsd_amd64.go @@ -17,6 +17,7 @@ package collector import ( + "fmt" "unsafe" "github.com/go-kit/log" @@ -26,6 +27,8 @@ import ( const ( DS_DISKNAMELEN = 16 + + diskstatsDefaultIgnoredDevices = "" ) type DiskStats struct { @@ -47,7 +50,9 @@ type diskstatsCollector struct { wxfer typedDesc wbytes typedDesc time typedDesc - logger log.Logger + + deviceFilter deviceFilter + logger log.Logger } func init() { @@ -56,13 +61,20 @@ func init() { // NewDiskstatsCollector returns a new Collector exposing disk device stats. func NewDiskstatsCollector(logger log.Logger) (Collector, error) { + deviceFilter, err := newDiskstatsDeviceFilter(logger) + if err != nil { + return nil, fmt.Errorf("failed to parse device filter flags: %w", err) + } + return &diskstatsCollector{ rxfer: typedDesc{readsCompletedDesc, prometheus.CounterValue}, rbytes: typedDesc{readBytesDesc, prometheus.CounterValue}, wxfer: typedDesc{writesCompletedDesc, prometheus.CounterValue}, wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue}, time: typedDesc{ioTimeSecondsDesc, prometheus.CounterValue}, - logger: logger, + + deviceFilter: deviceFilter, + logger: logger, }, nil } @@ -78,6 +90,9 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) (err error) { for i := 0; i < ndisks; i++ { dn := *(*[DS_DISKNAMELEN]int8)(unsafe.Pointer(&diskstats[i].Name[0])) diskname := int8ToString(dn[:]) + if c.deviceFilter.ignored(diskname) { + continue + } ch <- c.rxfer.mustNewConstMetric(float64(diskstats[i].Rxfer), diskname) ch <- c.rbytes.mustNewConstMetric(float64(diskstats[i].Rbytes), diskname) diff --git a/collector/dmi.go b/collector/dmi.go index 3cc2a8a517..794755076a 100644 --- a/collector/dmi.go +++ b/collector/dmi.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "os" + "strings" "github.com/go-kit/log" "github.com/go-kit/log/level" @@ -78,7 +79,7 @@ func NewDMICollector(logger log.Logger) (Collector, error) { } { if value != nil { labels = append(labels, label) - values = append(values, *value) + values = append(values, strings.ToValidUTF8(*value, "�")) } } diff --git a/collector/drm_linux.go b/collector/drm_linux.go index 21a0314e38..11b8c6283b 100644 --- a/collector/drm_linux.go +++ b/collector/drm_linux.go @@ -99,11 +99,7 @@ func NewDrmCollector(logger log.Logger) (Collector, error) { } func (c *drmCollector) Update(ch chan<- prometheus.Metric) error { - if err := c.updateAMDCards(ch); err != nil { - return err - } - - return nil + return c.updateAMDCards(ch) } func (c *drmCollector) updateAMDCards(ch chan<- prometheus.Metric) error { diff --git a/collector/ethtool_linux.go b/collector/ethtool_linux.go index 233cbd8fe1..0111701bbe 100644 --- a/collector/ethtool_linux.go +++ b/collector/ethtool_linux.go @@ -27,15 +27,16 @@ import ( "regexp" "sort" "strings" + "sync" "syscall" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/sysfs" "github.com/safchain/ethtool" "golang.org/x/sys/unix" - "gopkg.in/alecthomas/kingpin.v2" ) var ( @@ -73,8 +74,9 @@ func (e *ethtoolLibrary) LinkInfo(intf string) (ethtool.EthtoolCmd, error) { type ethtoolCollector struct { fs sysfs.FS entries map[string]*prometheus.Desc + entriesMutex sync.Mutex ethtool Ethtool - deviceFilter netDevFilter + deviceFilter deviceFilter infoDesc *prometheus.Desc metricsPattern *regexp.Regexp logger log.Logger @@ -98,7 +100,7 @@ func makeEthtoolCollector(logger log.Logger) (*ethtoolCollector, error) { return ðtoolCollector{ fs: fs, ethtool: ðtoolLibrary{e}, - deviceFilter: newNetDevFilter(*ethtoolDeviceExclude, *ethtoolDeviceInclude), + deviceFilter: newDeviceFilter(*ethtoolDeviceExclude, *ethtoolDeviceInclude), metricsPattern: regexp.MustCompile(*ethtoolIncludedMetrics), logger: logger, entries: map[string]*prometheus.Desc{ @@ -233,9 +235,9 @@ func (c *ethtoolCollector) updatePortCapabilities(ch chan<- prometheus.Metric, p if linkModes&(1< 0 { continue } ch <- prometheus.MustNewConstMetric( c.sizeDesc, prometheus.GaugeValue, - s.size, s.labels.device, s.labels.mountPoint, s.labels.fsType, + s.size, s.labels.device, s.labels.mountPoint, s.labels.fsType, s.labels.deviceError, ) ch <- prometheus.MustNewConstMetric( c.freeDesc, prometheus.GaugeValue, - s.free, s.labels.device, s.labels.mountPoint, s.labels.fsType, + s.free, s.labels.device, s.labels.mountPoint, s.labels.fsType, s.labels.deviceError, ) ch <- prometheus.MustNewConstMetric( c.availDesc, prometheus.GaugeValue, - s.avail, s.labels.device, s.labels.mountPoint, s.labels.fsType, + s.avail, s.labels.device, s.labels.mountPoint, s.labels.fsType, s.labels.deviceError, ) ch <- prometheus.MustNewConstMetric( c.filesDesc, prometheus.GaugeValue, - s.files, s.labels.device, s.labels.mountPoint, s.labels.fsType, + s.files, s.labels.device, s.labels.mountPoint, s.labels.fsType, s.labels.deviceError, ) ch <- prometheus.MustNewConstMetric( c.filesFreeDesc, prometheus.GaugeValue, - s.filesFree, s.labels.device, s.labels.mountPoint, s.labels.fsType, - ) - ch <- prometheus.MustNewConstMetric( - c.roDesc, prometheus.GaugeValue, - s.ro, s.labels.device, s.labels.mountPoint, s.labels.fsType, + s.filesFree, s.labels.device, s.labels.mountPoint, s.labels.fsType, s.labels.deviceError, ) } return nil diff --git a/collector/filesystem_freebsd.go b/collector/filesystem_freebsd.go index 768eb797b0..f05702d14f 100644 --- a/collector/filesystem_freebsd.go +++ b/collector/filesystem_freebsd.go @@ -24,38 +24,41 @@ import ( const ( defMountPointsExcluded = "^/(dev)($|/)" defFSTypesExcluded = "^devfs$" - readOnly = 0x1 // MNT_RDONLY - noWait = 0x2 // MNT_NOWAIT ) // Expose filesystem fullness. func (c *filesystemCollector) GetStats() ([]filesystemStats, error) { - n, err := unix.Getfsstat(nil, noWait) + n, err := unix.Getfsstat(nil, unix.MNT_NOWAIT) if err != nil { return nil, err } buf := make([]unix.Statfs_t, n) - _, err = unix.Getfsstat(buf, noWait) + _, err = unix.Getfsstat(buf, unix.MNT_NOWAIT) if err != nil { return nil, err } stats := []filesystemStats{} for _, fs := range buf { - mountpoint := bytesToString(fs.Mntonname[:]) + mountpoint := unix.ByteSliceToString(fs.Mntonname[:]) if c.excludedMountPointsPattern.MatchString(mountpoint) { level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint) continue } - device := bytesToString(fs.Mntfromname[:]) - fstype := bytesToString(fs.Fstypename[:]) + device := unix.ByteSliceToString(fs.Mntfromname[:]) + fstype := unix.ByteSliceToString(fs.Fstypename[:]) if c.excludedFSTypesPattern.MatchString(fstype) { level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype) continue } + if (fs.Flags & unix.MNT_IGNORE) != 0 { + level.Debug(c.logger).Log("msg", "Ignoring mount flagged as ignore", "mountpoint", mountpoint) + continue + } + var ro float64 - if (fs.Flags & readOnly) != 0 { + if (fs.Flags & unix.MNT_RDONLY) != 0 { ro = 1 } diff --git a/collector/filesystem_linux.go b/collector/filesystem_linux.go index a5c6bf3192..1d0c8493b9 100644 --- a/collector/filesystem_linux.go +++ b/collector/filesystem_linux.go @@ -26,20 +26,23 @@ import ( "sync" "time" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "golang.org/x/sys/unix" - "gopkg.in/alecthomas/kingpin.v2" ) const ( - defMountPointsExcluded = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)" + defMountPointsExcluded = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+|var/lib/containers/storage/.+)($|/)" defFSTypesExcluded = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$" ) var mountTimeout = kingpin.Flag("collector.filesystem.mount-timeout", "how long to wait for a mount to respond before marking it as stale"). Hidden().Default("5s").Duration() +var statWorkerCount = kingpin.Flag("collector.filesystem.stat-workers", + "how many stat calls to process simultaneously"). + Hidden().Default("4").Int() var stuckMounts = make(map[string]struct{}) var stuckMountsMtx = &sync.Mutex{} @@ -50,72 +53,105 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) { return nil, err } stats := []filesystemStats{} - for _, labels := range mps { - if c.excludedMountPointsPattern.MatchString(labels.mountPoint) { - level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", labels.mountPoint) - continue - } - if c.excludedFSTypesPattern.MatchString(labels.fsType) { - level.Debug(c.logger).Log("msg", "Ignoring fs", "type", labels.fsType) - continue - } - stuckMountsMtx.Lock() - if _, ok := stuckMounts[labels.mountPoint]; ok { - stats = append(stats, filesystemStats{ - labels: labels, - deviceError: 1, - }) - level.Debug(c.logger).Log("msg", "Mount point is in an unresponsive state", "mountpoint", labels.mountPoint) + labelChan := make(chan filesystemLabels) + statChan := make(chan filesystemStats) + wg := sync.WaitGroup{} + + workerCount := *statWorkerCount + if workerCount < 1 { + workerCount = 1 + } + + for i := 0; i < workerCount; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for labels := range labelChan { + statChan <- c.processStat(labels) + } + }() + } + + go func() { + for _, labels := range mps { + if c.excludedMountPointsPattern.MatchString(labels.mountPoint) { + level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", labels.mountPoint) + continue + } + if c.excludedFSTypesPattern.MatchString(labels.fsType) { + level.Debug(c.logger).Log("msg", "Ignoring fs", "type", labels.fsType) + continue + } + + stuckMountsMtx.Lock() + if _, ok := stuckMounts[labels.mountPoint]; ok { + labels.deviceError = "mountpoint timeout" + stats = append(stats, filesystemStats{ + labels: labels, + deviceError: 1, + }) + level.Debug(c.logger).Log("msg", "Mount point is in an unresponsive state", "mountpoint", labels.mountPoint) + stuckMountsMtx.Unlock() + continue + } + stuckMountsMtx.Unlock() - continue + labelChan <- labels } - stuckMountsMtx.Unlock() + close(labelChan) + wg.Wait() + close(statChan) + }() - // The success channel is used do tell the "watcher" that the stat - // finished successfully. The channel is closed on success. - success := make(chan struct{}) - go stuckMountWatcher(labels.mountPoint, success, c.logger) + for stat := range statChan { + stats = append(stats, stat) + } + return stats, nil +} - buf := new(unix.Statfs_t) - err = unix.Statfs(rootfsFilePath(labels.mountPoint), buf) - stuckMountsMtx.Lock() - close(success) - // If the mount has been marked as stuck, unmark it and log it's recovery. - if _, ok := stuckMounts[labels.mountPoint]; ok { - level.Debug(c.logger).Log("msg", "Mount point has recovered, monitoring will resume", "mountpoint", labels.mountPoint) - delete(stuckMounts, labels.mountPoint) +func (c *filesystemCollector) processStat(labels filesystemLabels) filesystemStats { + var ro float64 + for _, option := range strings.Split(labels.options, ",") { + if option == "ro" { + ro = 1 + break } - stuckMountsMtx.Unlock() + } - if err != nil { - stats = append(stats, filesystemStats{ - labels: labels, - deviceError: 1, - }) + success := make(chan struct{}) + go stuckMountWatcher(labels.mountPoint, success, c.logger) - level.Debug(c.logger).Log("msg", "Error on statfs() system call", "rootfs", rootfsFilePath(labels.mountPoint), "err", err) - continue - } + buf := new(unix.Statfs_t) + err := unix.Statfs(rootfsFilePath(labels.mountPoint), buf) + stuckMountsMtx.Lock() + close(success) - var ro float64 - for _, option := range strings.Split(labels.options, ",") { - if option == "ro" { - ro = 1 - break - } + // If the mount has been marked as stuck, unmark it and log it's recovery. + if _, ok := stuckMounts[labels.mountPoint]; ok { + level.Debug(c.logger).Log("msg", "Mount point has recovered, monitoring will resume", "mountpoint", labels.mountPoint) + delete(stuckMounts, labels.mountPoint) + } + stuckMountsMtx.Unlock() + + if err != nil { + labels.deviceError = err.Error() + level.Debug(c.logger).Log("msg", "Error on statfs() system call", "rootfs", rootfsFilePath(labels.mountPoint), "err", err) + return filesystemStats{ + labels: labels, + deviceError: 1, + ro: ro, } + } - stats = append(stats, filesystemStats{ - labels: labels, - size: float64(buf.Blocks) * float64(buf.Bsize), - free: float64(buf.Bfree) * float64(buf.Bsize), - avail: float64(buf.Bavail) * float64(buf.Bsize), - files: float64(buf.Files), - filesFree: float64(buf.Ffree), - ro: ro, - }) + return filesystemStats{ + labels: labels, + size: float64(buf.Blocks) * float64(buf.Bsize), + free: float64(buf.Bfree) * float64(buf.Bsize), + avail: float64(buf.Bavail) * float64(buf.Bsize), + files: float64(buf.Files), + filesFree: float64(buf.Ffree), + ro: ro, } - return stats, nil } // stuckMountWatcher listens on the given success channel and if the channel closes @@ -173,10 +209,11 @@ func parseFilesystemLabels(r io.Reader) ([]filesystemLabels, error) { parts[1] = strings.Replace(parts[1], "\\011", "\t", -1) filesystems = append(filesystems, filesystemLabels{ - device: parts[0], - mountPoint: rootfsStripPrefix(parts[1]), - fsType: parts[2], - options: parts[3], + device: parts[0], + mountPoint: rootfsStripPrefix(parts[1]), + fsType: parts[2], + options: parts[3], + deviceError: "", }) } diff --git a/collector/filesystem_linux_test.go b/collector/filesystem_linux_test.go index 1d18fd5920..325ffc87b2 100644 --- a/collector/filesystem_linux_test.go +++ b/collector/filesystem_linux_test.go @@ -11,14 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nofilesystem +// +build !nofilesystem + package collector import ( - "github.com/go-kit/log" "strings" "testing" - kingpin "gopkg.in/alecthomas/kingpin.v2" + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" ) func Test_parseFilesystemLabelsError(t *testing.T) { diff --git a/collector/filesystem_openbsd_amd64.go b/collector/filesystem_openbsd.go similarity index 90% rename from collector/filesystem_openbsd_amd64.go rename to collector/filesystem_openbsd.go index 448b3ef36e..1c1e479e1f 100644 --- a/collector/filesystem_openbsd_amd64.go +++ b/collector/filesystem_openbsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build openbsd && !nofilesystem -// +build openbsd,!nofilesystem +//go:build !nofilesystem +// +build !nofilesystem package collector @@ -41,14 +41,14 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) { stats = []filesystemStats{} for _, v := range mnt { - mountpoint := int8ToString(v.F_mntonname[:]) + mountpoint := unix.ByteSliceToString(v.F_mntonname[:]) if c.excludedMountPointsPattern.MatchString(mountpoint) { level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint) continue } - device := int8ToString(v.F_mntfromname[:]) - fstype := int8ToString(v.F_fstypename[:]) + device := unix.ByteSliceToString(v.F_mntfromname[:]) + fstype := unix.ByteSliceToString(v.F_fstypename[:]) if c.excludedFSTypesPattern.MatchString(fstype) { level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype) continue diff --git a/collector/fixtures/e2e-64k-page-output.txt b/collector/fixtures/e2e-64k-page-output.txt index 845a9089b9..5b0ac8db46 100644 --- a/collector/fixtures/e2e-64k-page-output.txt +++ b/collector/fixtures/e2e-64k-page-output.txt @@ -12,8 +12,6 @@ # TYPE go_memstats_buck_hash_sys_bytes gauge # HELP go_memstats_frees_total Total number of frees. # TYPE go_memstats_frees_total counter -# HELP go_memstats_gc_cpu_fraction The fraction of this program's available CPU time used by the GC since the program started. -# TYPE go_memstats_gc_cpu_fraction gauge # HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata. # TYPE go_memstats_gc_sys_bytes gauge # HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use. @@ -99,13 +97,16 @@ node_bcache_cache_misses_total{backing_device="bdev0",uuid="deaddd54-c735-46d5-8 node_bcache_cache_read_races_total{uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 # HELP node_bcache_cache_readaheads_total Count of times readahead occurred. # TYPE node_bcache_cache_readaheads_total counter -node_bcache_cache_readaheads_total{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 +node_bcache_cache_readaheads_total{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 13 # HELP node_bcache_congested Congestion. # TYPE node_bcache_congested gauge node_bcache_congested{uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 # HELP node_bcache_dirty_data_bytes Amount of dirty data for this backing device in the cache. # TYPE node_bcache_dirty_data_bytes gauge node_bcache_dirty_data_bytes{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 +# HELP node_bcache_dirty_target_bytes Current dirty data target threshold for this backing device in bytes. +# TYPE node_bcache_dirty_target_bytes gauge +node_bcache_dirty_target_bytes{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 2.189426688e+10 # HELP node_bcache_io_errors Number of errors that have occurred, decayed by io_error_halflife. # TYPE node_bcache_io_errors gauge node_bcache_io_errors{cache_device="cache0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 @@ -124,6 +125,18 @@ node_bcache_root_usage_percent{uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 # HELP node_bcache_tree_depth Depth of the btree. # TYPE node_bcache_tree_depth gauge node_bcache_tree_depth{uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 +# HELP node_bcache_writeback_change Last writeback rate change step for this backing device. +# TYPE node_bcache_writeback_change gauge +node_bcache_writeback_change{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 329204 +# HELP node_bcache_writeback_rate Current writeback rate for this backing device in bytes. +# TYPE node_bcache_writeback_rate gauge +node_bcache_writeback_rate{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 1.150976e+06 +# HELP node_bcache_writeback_rate_integral_term Current result of integral controller, part of writeback rate +# TYPE node_bcache_writeback_rate_integral_term gauge +node_bcache_writeback_rate_integral_term{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 808960 +# HELP node_bcache_writeback_rate_proportional_term Current result of proportional controller, part of writeback rate +# TYPE node_bcache_writeback_rate_proportional_term gauge +node_bcache_writeback_rate_proportional_term{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 437748 # HELP node_bcache_written_bytes_total Sum of all data that has been written to the cache. # TYPE node_bcache_written_bytes_total counter node_bcache_written_bytes_total{cache_device="cache0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 @@ -140,6 +153,54 @@ node_bonding_slaves{master="int"} 2 # HELP node_boot_time_seconds Node boot time, in unixtime. # TYPE node_boot_time_seconds gauge node_boot_time_seconds 1.418183276e+09 +# HELP node_btrfs_allocation_ratio Data allocation ratio for a layout/data type +# TYPE node_btrfs_allocation_ratio gauge +node_btrfs_allocation_ratio{block_group_type="data",mode="raid0",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 1 +node_btrfs_allocation_ratio{block_group_type="data",mode="raid5",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1.3333333333333333 +node_btrfs_allocation_ratio{block_group_type="metadata",mode="raid1",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 2 +node_btrfs_allocation_ratio{block_group_type="metadata",mode="raid6",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 2 +node_btrfs_allocation_ratio{block_group_type="system",mode="raid1",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 2 +node_btrfs_allocation_ratio{block_group_type="system",mode="raid6",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 2 +# HELP node_btrfs_device_size_bytes Size of a device that is part of the filesystem. +# TYPE node_btrfs_device_size_bytes gauge +node_btrfs_device_size_bytes{device="loop22",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1.073741824e+10 +node_btrfs_device_size_bytes{device="loop23",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1.073741824e+10 +node_btrfs_device_size_bytes{device="loop24",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1.073741824e+10 +node_btrfs_device_size_bytes{device="loop25",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 1.073741824e+10 +node_btrfs_device_size_bytes{device="loop25",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1.073741824e+10 +node_btrfs_device_size_bytes{device="loop26",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 1.073741824e+10 +# HELP node_btrfs_global_rsv_size_bytes Size of global reserve. +# TYPE node_btrfs_global_rsv_size_bytes gauge +node_btrfs_global_rsv_size_bytes{uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 1.6777216e+07 +node_btrfs_global_rsv_size_bytes{uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1.6777216e+07 +# HELP node_btrfs_info Filesystem information +# TYPE node_btrfs_info gauge +node_btrfs_info{label="",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1 +node_btrfs_info{label="fixture",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 1 +# HELP node_btrfs_reserved_bytes Amount of space reserved for a data type +# TYPE node_btrfs_reserved_bytes gauge +node_btrfs_reserved_bytes{block_group_type="data",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 0 +node_btrfs_reserved_bytes{block_group_type="data",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 0 +node_btrfs_reserved_bytes{block_group_type="metadata",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 0 +node_btrfs_reserved_bytes{block_group_type="metadata",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 0 +node_btrfs_reserved_bytes{block_group_type="system",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 0 +node_btrfs_reserved_bytes{block_group_type="system",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 0 +# HELP node_btrfs_size_bytes Amount of space allocated for a layout/data type +# TYPE node_btrfs_size_bytes gauge +node_btrfs_size_bytes{block_group_type="data",mode="raid0",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 2.147483648e+09 +node_btrfs_size_bytes{block_group_type="data",mode="raid5",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 6.44087808e+08 +node_btrfs_size_bytes{block_group_type="metadata",mode="raid1",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 1.073741824e+09 +node_btrfs_size_bytes{block_group_type="metadata",mode="raid6",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 4.29391872e+08 +node_btrfs_size_bytes{block_group_type="system",mode="raid1",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 8.388608e+06 +node_btrfs_size_bytes{block_group_type="system",mode="raid6",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 1.6777216e+07 +# HELP node_btrfs_used_bytes Amount of used space by a layout/data type +# TYPE node_btrfs_used_bytes gauge +node_btrfs_used_bytes{block_group_type="data",mode="raid0",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 8.08189952e+08 +node_btrfs_used_bytes{block_group_type="data",mode="raid5",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 0 +node_btrfs_used_bytes{block_group_type="metadata",mode="raid1",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 933888 +node_btrfs_used_bytes{block_group_type="metadata",mode="raid6",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 114688 +node_btrfs_used_bytes{block_group_type="system",mode="raid1",uuid="0abb23a9-579b-43e6-ad30-227ef47fcb9d"} 16384 +node_btrfs_used_bytes{block_group_type="system",mode="raid6",uuid="7f07c59f-6136-449c-ab87-e1cf2328731b"} 16384 # HELP node_buddyinfo_blocks Count of free blocks according to size. # TYPE node_buddyinfo_blocks gauge node_buddyinfo_blocks{node="0",size="0",zone="DMA"} 1 @@ -175,6 +236,34 @@ node_buddyinfo_blocks{node="0",size="8",zone="Normal"} 0 node_buddyinfo_blocks{node="0",size="9",zone="DMA"} 1 node_buddyinfo_blocks{node="0",size="9",zone="DMA32"} 0 node_buddyinfo_blocks{node="0",size="9",zone="Normal"} 0 +# HELP node_cgroups_cgroups Current cgroup number of the subsystem. +# TYPE node_cgroups_cgroups gauge +node_cgroups_cgroups{subsys_name="blkio"} 170 +node_cgroups_cgroups{subsys_name="cpu"} 172 +node_cgroups_cgroups{subsys_name="cpuacct"} 172 +node_cgroups_cgroups{subsys_name="cpuset"} 47 +node_cgroups_cgroups{subsys_name="devices"} 170 +node_cgroups_cgroups{subsys_name="freezer"} 47 +node_cgroups_cgroups{subsys_name="hugetlb"} 47 +node_cgroups_cgroups{subsys_name="memory"} 234 +node_cgroups_cgroups{subsys_name="net_cls"} 47 +node_cgroups_cgroups{subsys_name="perf_event"} 47 +node_cgroups_cgroups{subsys_name="pids"} 170 +node_cgroups_cgroups{subsys_name="rdma"} 1 +# HELP node_cgroups_enabled Current cgroup number of the subsystem. +# TYPE node_cgroups_enabled gauge +node_cgroups_enabled{subsys_name="blkio"} 1 +node_cgroups_enabled{subsys_name="cpu"} 1 +node_cgroups_enabled{subsys_name="cpuacct"} 1 +node_cgroups_enabled{subsys_name="cpuset"} 1 +node_cgroups_enabled{subsys_name="devices"} 1 +node_cgroups_enabled{subsys_name="freezer"} 1 +node_cgroups_enabled{subsys_name="hugetlb"} 1 +node_cgroups_enabled{subsys_name="memory"} 1 +node_cgroups_enabled{subsys_name="net_cls"} 1 +node_cgroups_enabled{subsys_name="perf_event"} 1 +node_cgroups_enabled{subsys_name="pids"} 1 +node_cgroups_enabled{subsys_name="rdma"} 1 # HELP node_context_switches_total Total number of context switches. # TYPE node_context_switches_total counter node_context_switches_total 3.8014093e+07 @@ -184,24 +273,12 @@ node_cooling_device_cur_state{name="0",type="Processor"} 0 # HELP node_cooling_device_max_state Maximum throttle state of the cooling device # TYPE node_cooling_device_max_state gauge node_cooling_device_max_state{name="0",type="Processor"} 3 -# HELP node_cpu_bug_info The `bugs` field of CPU information from /proc/cpuinfo. -# TYPE node_cpu_bug_info gauge -node_cpu_bug_info{bug="cpu_meltdown"} 1 -node_cpu_bug_info{bug="mds"} 1 -node_cpu_bug_info{bug="spectre_v1"} 1 -node_cpu_bug_info{bug="spectre_v2"} 1 # HELP node_cpu_core_throttles_total Number of times this CPU core has been throttled. # TYPE node_cpu_core_throttles_total counter node_cpu_core_throttles_total{core="0",package="0"} 5 node_cpu_core_throttles_total{core="0",package="1"} 0 node_cpu_core_throttles_total{core="1",package="0"} 0 node_cpu_core_throttles_total{core="1",package="1"} 9 -# HELP node_cpu_flag_info The `flags` field of CPU information from /proc/cpuinfo. -# TYPE node_cpu_flag_info gauge -node_cpu_flag_info{flag="aes"} 1 -node_cpu_flag_info{flag="avx"} 1 -node_cpu_flag_info{flag="avx2"} 1 -node_cpu_flag_info{flag="constant_tsc"} 1 # HELP node_cpu_guest_seconds_total Seconds the CPUs spent in guests (VMs) for each mode. # TYPE node_cpu_guest_seconds_total counter node_cpu_guest_seconds_total{cpu="0",mode="nice"} 0.01 @@ -220,16 +297,13 @@ node_cpu_guest_seconds_total{cpu="6",mode="nice"} 0.07 node_cpu_guest_seconds_total{cpu="6",mode="user"} 0.08 node_cpu_guest_seconds_total{cpu="7",mode="nice"} 0.08 node_cpu_guest_seconds_total{cpu="7",mode="user"} 0.09 -# HELP node_cpu_info CPU information from /proc/cpuinfo. -# TYPE node_cpu_info gauge -node_cpu_info{cachesize="8192 KB",core="0",cpu="0",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 -node_cpu_info{cachesize="8192 KB",core="0",cpu="4",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 -node_cpu_info{cachesize="8192 KB",core="1",cpu="1",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 -node_cpu_info{cachesize="8192 KB",core="1",cpu="5",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 -node_cpu_info{cachesize="8192 KB",core="2",cpu="2",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 -node_cpu_info{cachesize="8192 KB",core="2",cpu="6",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 -node_cpu_info{cachesize="8192 KB",core="3",cpu="3",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 -node_cpu_info{cachesize="8192 KB",core="3",cpu="7",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 +# HELP node_cpu_isolated Whether each core is isolated, information from /sys/devices/system/cpu/isolated. +# TYPE node_cpu_isolated gauge +node_cpu_isolated{cpu="1"} 1 +node_cpu_isolated{cpu="3"} 1 +node_cpu_isolated{cpu="4"} 1 +node_cpu_isolated{cpu="5"} 1 +node_cpu_isolated{cpu="9"} 1 # HELP node_cpu_package_throttles_total Number of times this CPU package has been throttled. # TYPE node_cpu_package_throttles_total counter node_cpu_package_throttles_total{package="0"} 30 @@ -252,6 +326,16 @@ node_cpu_scaling_frequency_min_hertz{cpu="0"} 8e+08 node_cpu_scaling_frequency_min_hertz{cpu="1"} 8e+08 node_cpu_scaling_frequency_min_hertz{cpu="2"} 1e+06 node_cpu_scaling_frequency_min_hertz{cpu="3"} 1e+06 +# HELP node_cpu_scaling_governor Current enabled CPU frequency governor. +# TYPE node_cpu_scaling_governor gauge +node_cpu_scaling_governor{cpu="0",governor="performance"} 0 +node_cpu_scaling_governor{cpu="0",governor="powersave"} 1 +node_cpu_scaling_governor{cpu="1",governor="performance"} 0 +node_cpu_scaling_governor{cpu="1",governor="powersave"} 1 +node_cpu_scaling_governor{cpu="2",governor="performance"} 0 +node_cpu_scaling_governor{cpu="2",governor="powersave"} 1 +node_cpu_scaling_governor{cpu="3",governor="performance"} 0 +node_cpu_scaling_governor{cpu="3",governor="powersave"} 1 # HELP node_cpu_seconds_total Seconds the CPUs spent in each mode. # TYPE node_cpu_seconds_total counter node_cpu_seconds_total{cpu="0",mode="idle"} 10870.69 @@ -318,18 +402,87 @@ node_cpu_seconds_total{cpu="7",mode="softirq"} 0.31 node_cpu_seconds_total{cpu="7",mode="steal"} 0 node_cpu_seconds_total{cpu="7",mode="system"} 101.64 node_cpu_seconds_total{cpu="7",mode="user"} 290.98 +# HELP node_cpu_vulnerabilities_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 +# TYPE node_cpu_vulnerabilities_info gauge +node_cpu_vulnerabilities_info{codename="itlb_multihit",mitigation="",state="not affected"} 1 +node_cpu_vulnerabilities_info{codename="mds",mitigation="",state="vulnerable"} 1 +node_cpu_vulnerabilities_info{codename="retbleed",mitigation="untrained return thunk; SMT enabled with STIBP protection",state="mitigation"} 1 +node_cpu_vulnerabilities_info{codename="spectre_v1",mitigation="usercopy/swapgs barriers and __user pointer sanitization",state="mitigation"} 1 +node_cpu_vulnerabilities_info{codename="spectre_v2",mitigation="Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected",state="mitigation"} 1 +# HELP node_disk_ata_rotation_rate_rpm ATA disk rotation rate in RPMs (0 for SSDs). +# TYPE node_disk_ata_rotation_rate_rpm gauge +node_disk_ata_rotation_rate_rpm{device="sda"} 7200 +node_disk_ata_rotation_rate_rpm{device="sdb"} 0 +node_disk_ata_rotation_rate_rpm{device="sdc"} 0 +# HELP node_disk_ata_write_cache ATA disk has a write cache. +# TYPE node_disk_ata_write_cache gauge +node_disk_ata_write_cache{device="sda"} 1 +node_disk_ata_write_cache{device="sdb"} 1 +node_disk_ata_write_cache{device="sdc"} 1 +# HELP node_disk_ata_write_cache_enabled ATA disk has its write cache enabled. +# TYPE node_disk_ata_write_cache_enabled gauge +node_disk_ata_write_cache_enabled{device="sda"} 0 +node_disk_ata_write_cache_enabled{device="sdb"} 1 +node_disk_ata_write_cache_enabled{device="sdc"} 0 +# HELP node_disk_device_mapper_info Info about disk device mapper. +# TYPE node_disk_device_mapper_info gauge +node_disk_device_mapper_info{device="dm-0",lv_layer="",lv_name="",name="nvme0n1_crypt",uuid="CRYPT-LUKS2-jolaulot80fy9zsiobkxyxo7y2dqeho2-nvme0n1_crypt",vg_name=""} 1 +node_disk_device_mapper_info{device="dm-1",lv_layer="",lv_name="swap_1",name="system-swap_1",uuid="LVM-wbGqQEBL9SxrW2DLntJwgg8fAv946hw3Tvjqh0v31fWgxEtD4BoHO0lROWFUY65T",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-2",lv_layer="",lv_name="root",name="system-root",uuid="LVM-NWEDo8q5ABDyJuC3F8veKNyWfYmeIBfFMS4MF3HakzUhkk7ekDm6fJTHkl2fYHe7",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-3",lv_layer="",lv_name="var",name="system-var",uuid="LVM-hrxHo0rlZ6U95ku5841Lpd17bS1Z7V7lrtEE60DVgE6YEOCdS9gcDGyonWim4hGP",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-4",lv_layer="",lv_name="tmp",name="system-tmp",uuid="LVM-XTNGOHjPWLHcxmJmVu5cWTXEtuzqDeBkdEHAZW5q9LxWQ2d4mb5CchUQzUPJpl8H",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-5",lv_layer="",lv_name="home",name="system-home",uuid="LVM-MtoJaWTpjWRXlUnNFlpxZauTEuYlMvGFutigEzCCrfj8CNh6jCRi5LQJXZCpLjPf",vg_name="system"} 1 # HELP node_disk_discard_time_seconds_total This is the total number of seconds spent by all discards. # TYPE node_disk_discard_time_seconds_total counter node_disk_discard_time_seconds_total{device="sdb"} 11.13 +node_disk_discard_time_seconds_total{device="sdc"} 11.13 # HELP node_disk_discarded_sectors_total The total number of sectors discarded successfully. # TYPE node_disk_discarded_sectors_total counter node_disk_discarded_sectors_total{device="sdb"} 1.925173784e+09 +node_disk_discarded_sectors_total{device="sdc"} 1.25173784e+08 # HELP node_disk_discards_completed_total The total number of discards completed successfully. # TYPE node_disk_discards_completed_total counter node_disk_discards_completed_total{device="sdb"} 68851 +node_disk_discards_completed_total{device="sdc"} 18851 # HELP node_disk_discards_merged_total The total number of discards merged. # TYPE node_disk_discards_merged_total counter node_disk_discards_merged_total{device="sdb"} 0 +node_disk_discards_merged_total{device="sdc"} 0 +# HELP node_disk_filesystem_info Info about disk filesystem. +# TYPE node_disk_filesystem_info gauge +node_disk_filesystem_info{device="dm-0",type="LVM2_member",usage="raid",uuid="c3C3uW-gD96-Yw69-c1CJ-5MwT-6ysM-mST0vB",version="LVM2 001"} 1 +node_disk_filesystem_info{device="dm-1",type="swap",usage="other",uuid="5272bb60-04b5-49cd-b730-be57c7604450",version="1"} 1 +node_disk_filesystem_info{device="dm-2",type="ext4",usage="filesystem",uuid="3deafd0d-faff-4695-8d15-51061ae1f51b",version="1.0"} 1 +node_disk_filesystem_info{device="dm-3",type="ext4",usage="filesystem",uuid="5c772222-f7d4-4c8e-87e8-e97df6b7a45e",version="1.0"} 1 +node_disk_filesystem_info{device="dm-4",type="ext4",usage="filesystem",uuid="a9479d44-60e1-4015-a1e5-bb065e6dd11b",version="1.0"} 1 +node_disk_filesystem_info{device="dm-5",type="ext4",usage="filesystem",uuid="b05b726a-c718-4c4d-8641-7c73a7696d83",version="1.0"} 1 +node_disk_filesystem_info{device="mmcblk0p1",type="vfat",usage="filesystem",uuid="6284-658D",version="FAT32"} 1 +node_disk_filesystem_info{device="mmcblk0p2",type="ext4",usage="filesystem",uuid="83324ce8-a6f3-4e35-ad64-dbb3d6b87a32",version="1.0"} 1 +node_disk_filesystem_info{device="sda",type="LVM2_member",usage="raid",uuid="cVVv6j-HSA2-IY33-1Jmj-dO2H-YL7w-b4Oxqw",version="LVM2 001"} 1 +node_disk_filesystem_info{device="sdc",type="LVM2_member",usage="raid",uuid="QFy9W7-Brj3-hQ6v-AF8i-3Zqg-n3Vs-kGY4vb",version="LVM2 001"} 1 +# HELP node_disk_flush_requests_time_seconds_total This is the total number of seconds spent by all flush requests. +# TYPE node_disk_flush_requests_time_seconds_total counter +node_disk_flush_requests_time_seconds_total{device="sdc"} 1.944 +# HELP node_disk_flush_requests_total The total number of flush requests completed successfully +# TYPE node_disk_flush_requests_total counter +node_disk_flush_requests_total{device="sdc"} 1555 +# HELP node_disk_info Info of /sys/block/. +# TYPE node_disk_info gauge +node_disk_info{device="dm-0",major="252",minor="0",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-1",major="252",minor="1",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-2",major="252",minor="2",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-3",major="252",minor="3",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-4",major="252",minor="4",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-5",major="252",minor="5",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0",major="179",minor="0",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0p1",major="179",minor="1",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0p2",major="179",minor="2",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="nvme0n1",major="259",minor="0",model="SAMSUNG EHFTF55LURSY-000Y9",path="pci-0000:02:00.0-nvme-1",revision="4NBTUY95",serial="S252B6CU1HG3M1",wwn="eui.p3vbbiejx5aae2r3"} 1 +node_disk_info{device="sda",major="8",minor="0",model="TOSHIBA_KSDB4U86",path="pci-0000:3b:00.0-sas-phy7-lun-0",revision="0102",serial="2160A0D5FVGG",wwn="0x7c72382b8de36a64"} 1 +node_disk_info{device="sdb",major="8",minor="16",model="SuperMicro_SSD",path="pci-0000:00:1f.2-ata-1",revision="0R",serial="SMC0E1B87ABBB16BD84E",wwn="0xe1b87abbb16bd84e"} 1 +node_disk_info{device="sdc",major="8",minor="32",model="INTEL_SSDS9X9SI0",path="pci-0000:00:1f.2-ata-4",revision="0100",serial="3EWB5Y25CWQWA7EH1U",wwn="0x58907ddc573a5de"} 1 +node_disk_info{device="sr0",major="11",minor="0",model="Virtual_CDROM0",path="pci-0000:00:14.0-usb-0:1.1:1.0-scsi-0:0:0:0",revision="1.00",serial="AAAABBBBCCCC1",wwn=""} 1 +node_disk_info{device="vda",major="254",minor="0",model="",path="pci-0000:00:06.0",revision="",serial="",wwn=""} 1 # HELP node_disk_io_now The number of I/Os currently in progress. # TYPE node_disk_io_now gauge node_disk_io_now{device="dm-0"} 0 @@ -344,6 +497,7 @@ node_disk_io_now{device="mmcblk0p2"} 0 node_disk_io_now{device="nvme0n1"} 0 node_disk_io_now{device="sda"} 0 node_disk_io_now{device="sdb"} 0 +node_disk_io_now{device="sdc"} 0 node_disk_io_now{device="sr0"} 0 node_disk_io_now{device="vda"} 0 # HELP node_disk_io_time_seconds_total Total seconds spent doing I/Os. @@ -360,6 +514,7 @@ node_disk_io_time_seconds_total{device="mmcblk0p2"} 0.068 node_disk_io_time_seconds_total{device="nvme0n1"} 222.766 node_disk_io_time_seconds_total{device="sda"} 9653.880000000001 node_disk_io_time_seconds_total{device="sdb"} 60.730000000000004 +node_disk_io_time_seconds_total{device="sdc"} 10.73 node_disk_io_time_seconds_total{device="sr0"} 0 node_disk_io_time_seconds_total{device="vda"} 41614.592000000004 # HELP node_disk_io_time_weighted_seconds_total The weighted # of seconds spent doing I/Os. @@ -376,6 +531,7 @@ node_disk_io_time_weighted_seconds_total{device="mmcblk0p2"} 0.068 node_disk_io_time_weighted_seconds_total{device="nvme0n1"} 1032.546 node_disk_io_time_weighted_seconds_total{device="sda"} 82621.804 node_disk_io_time_weighted_seconds_total{device="sdb"} 67.07000000000001 +node_disk_io_time_weighted_seconds_total{device="sdc"} 17.07 node_disk_io_time_weighted_seconds_total{device="sr0"} 0 node_disk_io_time_weighted_seconds_total{device="vda"} 2.0778722280000001e+06 # HELP node_disk_read_bytes_total The total number of bytes read successfully. @@ -392,6 +548,7 @@ node_disk_read_bytes_total{device="mmcblk0p2"} 389120 node_disk_read_bytes_total{device="nvme0n1"} 2.377714176e+09 node_disk_read_bytes_total{device="sda"} 5.13713216512e+11 node_disk_read_bytes_total{device="sdb"} 4.944782848e+09 +node_disk_read_bytes_total{device="sdc"} 8.48782848e+08 node_disk_read_bytes_total{device="sr0"} 0 node_disk_read_bytes_total{device="vda"} 1.6727491584e+10 # HELP node_disk_read_time_seconds_total The total number of seconds spent by all reads. @@ -408,6 +565,7 @@ node_disk_read_time_seconds_total{device="mmcblk0p2"} 0.068 node_disk_read_time_seconds_total{device="nvme0n1"} 21.650000000000002 node_disk_read_time_seconds_total{device="sda"} 18492.372 node_disk_read_time_seconds_total{device="sdb"} 0.084 +node_disk_read_time_seconds_total{device="sdc"} 0.014 node_disk_read_time_seconds_total{device="sr0"} 0 node_disk_read_time_seconds_total{device="vda"} 8655.768 # HELP node_disk_reads_completed_total The total number of reads completed successfully. @@ -424,6 +582,7 @@ node_disk_reads_completed_total{device="mmcblk0p2"} 95 node_disk_reads_completed_total{device="nvme0n1"} 47114 node_disk_reads_completed_total{device="sda"} 2.5354637e+07 node_disk_reads_completed_total{device="sdb"} 326552 +node_disk_reads_completed_total{device="sdc"} 126552 node_disk_reads_completed_total{device="sr0"} 0 node_disk_reads_completed_total{device="vda"} 1.775784e+06 # HELP node_disk_reads_merged_total The total number of reads merged. @@ -440,6 +599,7 @@ node_disk_reads_merged_total{device="mmcblk0p2"} 0 node_disk_reads_merged_total{device="nvme0n1"} 4 node_disk_reads_merged_total{device="sda"} 3.4367663e+07 node_disk_reads_merged_total{device="sdb"} 841 +node_disk_reads_merged_total{device="sdc"} 141 node_disk_reads_merged_total{device="sr0"} 0 node_disk_reads_merged_total{device="vda"} 15386 # HELP node_disk_write_time_seconds_total This is the total number of seconds spent by all writes. @@ -456,6 +616,7 @@ node_disk_write_time_seconds_total{device="mmcblk0p2"} 0 node_disk_write_time_seconds_total{device="nvme0n1"} 1011.053 node_disk_write_time_seconds_total{device="sda"} 63877.96 node_disk_write_time_seconds_total{device="sdb"} 5.007 +node_disk_write_time_seconds_total{device="sdc"} 1.0070000000000001 node_disk_write_time_seconds_total{device="sr0"} 0 node_disk_write_time_seconds_total{device="vda"} 2.069221364e+06 # HELP node_disk_writes_completed_total The total number of writes completed successfully. @@ -472,6 +633,7 @@ node_disk_writes_completed_total{device="mmcblk0p2"} 0 node_disk_writes_completed_total{device="nvme0n1"} 1.07832e+06 node_disk_writes_completed_total{device="sda"} 2.8444756e+07 node_disk_writes_completed_total{device="sdb"} 41822 +node_disk_writes_completed_total{device="sdc"} 11822 node_disk_writes_completed_total{device="sr0"} 0 node_disk_writes_completed_total{device="vda"} 6.038856e+06 # HELP node_disk_writes_merged_total The number of writes merged. @@ -488,6 +650,7 @@ node_disk_writes_merged_total{device="mmcblk0p2"} 0 node_disk_writes_merged_total{device="nvme0n1"} 43950 node_disk_writes_merged_total{device="sda"} 1.1134226e+07 node_disk_writes_merged_total{device="sdb"} 2895 +node_disk_writes_merged_total{device="sdc"} 1895 node_disk_writes_merged_total{device="sr0"} 0 node_disk_writes_merged_total{device="vda"} 2.0711856e+07 # HELP node_disk_written_bytes_total The total number of bytes written successfully. @@ -504,11 +667,12 @@ node_disk_written_bytes_total{device="mmcblk0p2"} 0 node_disk_written_bytes_total{device="nvme0n1"} 2.0199236096e+10 node_disk_written_bytes_total{device="sda"} 2.58916880384e+11 node_disk_written_bytes_total{device="sdb"} 1.01012736e+09 +node_disk_written_bytes_total{device="sdc"} 8.852736e+07 node_disk_written_bytes_total{device="sr0"} 0 node_disk_written_bytes_total{device="vda"} 1.0938236928e+11 # HELP node_dmi_info A metric with a constant '1' value labeled by bios_date, bios_release, bios_vendor, bios_version, board_asset_tag, board_name, board_serial, board_vendor, board_version, chassis_asset_tag, chassis_serial, chassis_vendor, chassis_version, product_family, product_name, product_serial, product_sku, product_uuid, product_version, system_vendor if provided by DMI. # TYPE node_dmi_info gauge -node_dmi_info{bios_date="04/12/2021",bios_release="2.2",bios_vendor="Dell Inc.",bios_version="2.2.4",board_name="07PXPY",board_serial=".7N62AI2.GRTCL6944100GP.",board_vendor="Dell Inc.",board_version="A01",chassis_asset_tag="",chassis_serial="7N62AI2",chassis_vendor="Dell Inc.",chassis_version="",product_family="PowerEdge",product_name="PowerEdge R6515",product_serial="7N62AI2",product_sku="SKU=NotProvided;ModelName=PowerEdge R6515",product_uuid="83340ca8-cb49-4474-8c29-d2088ca84dd9",product_version="",system_vendor="Dell Inc."} 1 +node_dmi_info{bios_date="04/12/2021",bios_release="2.2",bios_vendor="Dell Inc.",bios_version="2.2.4",board_name="07PXPY",board_serial=".7N62AI2.GRTCL6944100GP.",board_vendor="Dell Inc.",board_version="A01",chassis_asset_tag="",chassis_serial="7N62AI2",chassis_vendor="Dell Inc.",chassis_version="",product_family="PowerEdge",product_name="PowerEdge R6515",product_serial="7N62AI2",product_sku="SKU=NotProvided;ModelName=PowerEdge R6515",product_uuid="83340ca8-cb49-4474-8c29-d2088ca84dd9",product_version="�[�",system_vendor="Dell Inc."} 1 # HELP node_drbd_activitylog_writes_total Number of updates of the activity log area of the meta data. # TYPE node_drbd_activitylog_writes_total counter node_drbd_activitylog_writes_total{device="drbd1"} 1100 @@ -573,8 +737,53 @@ node_edac_uncorrectable_errors_total{controller="0"} 5 # HELP node_entropy_available_bits Bits of available entropy. # TYPE node_entropy_available_bits gauge node_entropy_available_bits 1337 -# HELP node_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, and goversion from which node_exporter was built. +# HELP node_entropy_pool_size_bits Bits of entropy pool. +# TYPE node_entropy_pool_size_bits gauge +node_entropy_pool_size_bits 4096 +# HELP node_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, goversion from which node_exporter was built, and the goos and goarch for the build. # TYPE node_exporter_build_info gauge +# HELP node_fibrechannel_error_frames_total Number of errors in frames +# TYPE node_fibrechannel_error_frames_total counter +node_fibrechannel_error_frames_total{fc_host="host0"} 0 +# HELP node_fibrechannel_fcp_packet_aborts_total Number of aborted packets +# TYPE node_fibrechannel_fcp_packet_aborts_total counter +node_fibrechannel_fcp_packet_aborts_total{fc_host="host0"} 19 +# HELP node_fibrechannel_info Non-numeric data from /sys/class/fc_host/, value is always 1. +# TYPE node_fibrechannel_info gauge +node_fibrechannel_info{dev_loss_tmo="30",fabric_name="0",fc_host="host0",port_id="000002",port_name="1000e0071bce95f2",port_state="Online",port_type="Point-To-Point (direct nport connection)",speed="16 Gbit",supported_classes="Class 3",supported_speeds="4 Gbit, 8 Gbit, 16 Gbit",symbolic_name="Emulex SN1100E2P FV12.4.270.3 DV12.4.0.0. HN:gotest. OS:Linux"} 1 +# HELP node_fibrechannel_invalid_crc_total Invalid Cyclic Redundancy Check count +# TYPE node_fibrechannel_invalid_crc_total counter +node_fibrechannel_invalid_crc_total{fc_host="host0"} 2 +# HELP node_fibrechannel_invalid_tx_words_total Number of invalid words transmitted by host port +# TYPE node_fibrechannel_invalid_tx_words_total counter +node_fibrechannel_invalid_tx_words_total{fc_host="host0"} 8 +# HELP node_fibrechannel_link_failure_total Number of times the host port link has failed +# TYPE node_fibrechannel_link_failure_total counter +node_fibrechannel_link_failure_total{fc_host="host0"} 9 +# HELP node_fibrechannel_loss_of_signal_total Number of times signal has been lost +# TYPE node_fibrechannel_loss_of_signal_total counter +node_fibrechannel_loss_of_signal_total{fc_host="host0"} 17 +# HELP node_fibrechannel_loss_of_sync_total Number of failures on either bit or transmission word boundaries +# TYPE node_fibrechannel_loss_of_sync_total counter +node_fibrechannel_loss_of_sync_total{fc_host="host0"} 16 +# HELP node_fibrechannel_nos_total Number Not_Operational Primitive Sequence received by host port +# TYPE node_fibrechannel_nos_total counter +node_fibrechannel_nos_total{fc_host="host0"} 18 +# HELP node_fibrechannel_rx_frames_total Number of frames received +# TYPE node_fibrechannel_rx_frames_total counter +node_fibrechannel_rx_frames_total{fc_host="host0"} 3 +# HELP node_fibrechannel_rx_words_total Number of words received by host port +# TYPE node_fibrechannel_rx_words_total counter +node_fibrechannel_rx_words_total{fc_host="host0"} 4 +# HELP node_fibrechannel_seconds_since_last_reset_total Number of seconds since last host port reset +# TYPE node_fibrechannel_seconds_since_last_reset_total counter +node_fibrechannel_seconds_since_last_reset_total{fc_host="host0"} 7 +# HELP node_fibrechannel_tx_frames_total Number of frames transmitted by host port +# TYPE node_fibrechannel_tx_frames_total counter +node_fibrechannel_tx_frames_total{fc_host="host0"} 5 +# HELP node_fibrechannel_tx_words_total Number of words transmitted by host port +# TYPE node_fibrechannel_tx_words_total counter +node_fibrechannel_tx_words_total{fc_host="host0"} 6 # HELP node_filefd_allocated File descriptor statistics: allocated. # TYPE node_filefd_allocated gauge node_filefd_allocated 1024 @@ -739,18 +948,18 @@ node_hwmon_pwm_weight_temp_step_tol{chip="nct6779",sensor="pwm1"} 0 # TYPE node_hwmon_sensor_label gauge node_hwmon_sensor_label{chip="hwmon4",label="foosensor",sensor="temp1"} 1 node_hwmon_sensor_label{chip="hwmon4",label="foosensor",sensor="temp2"} 1 -node_hwmon_sensor_label{chip="platform_applesmc_768",label="left_side",sensor="fan1"} 1 -node_hwmon_sensor_label{chip="platform_applesmc_768",label="right_side",sensor="fan2"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_0",sensor="temp2"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_1",sensor="temp3"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_2",sensor="temp4"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_3",sensor="temp5"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="physical_id_0",sensor="temp1"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_0",sensor="temp2"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_1",sensor="temp3"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_2",sensor="temp4"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_3",sensor="temp5"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="physical_id_0",sensor="temp1"} 1 +node_hwmon_sensor_label{chip="platform_applesmc_768",label="Left side ",sensor="fan1"} 1 +node_hwmon_sensor_label{chip="platform_applesmc_768",label="Right side ",sensor="fan2"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 0",sensor="temp2"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 1",sensor="temp3"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 2",sensor="temp4"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 3",sensor="temp5"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Physical id 0",sensor="temp1"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 0",sensor="temp2"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 1",sensor="temp3"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 2",sensor="temp4"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 3",sensor="temp5"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Physical id 0",sensor="temp1"} 1 # HELP node_hwmon_temp_celsius Hardware monitor for temperature (input) # TYPE node_hwmon_temp_celsius gauge node_hwmon_temp_celsius{chip="hwmon4",sensor="temp1"} 55 @@ -1109,6 +1318,184 @@ node_ksmd_run 1 # HELP node_ksmd_sleep_seconds ksmd 'sleep_millisecs' file. # TYPE node_ksmd_sleep_seconds gauge node_ksmd_sleep_seconds 0.02 +# HELP node_lnstat_allocs_total linux network cache stats +# TYPE node_lnstat_allocs_total counter +node_lnstat_allocs_total{cpu="0",subsystem="arp_cache"} 1 +node_lnstat_allocs_total{cpu="0",subsystem="ndisc_cache"} 240 +node_lnstat_allocs_total{cpu="1",subsystem="arp_cache"} 13 +node_lnstat_allocs_total{cpu="1",subsystem="ndisc_cache"} 252 +# HELP node_lnstat_delete_list_total linux network cache stats +# TYPE node_lnstat_delete_list_total counter +node_lnstat_delete_list_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_delete_list_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_delete_list_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_delete_list_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_delete_total linux network cache stats +# TYPE node_lnstat_delete_total counter +node_lnstat_delete_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_delete_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_delete_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_delete_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_destroys_total linux network cache stats +# TYPE node_lnstat_destroys_total counter +node_lnstat_destroys_total{cpu="0",subsystem="arp_cache"} 2 +node_lnstat_destroys_total{cpu="0",subsystem="ndisc_cache"} 241 +node_lnstat_destroys_total{cpu="1",subsystem="arp_cache"} 14 +node_lnstat_destroys_total{cpu="1",subsystem="ndisc_cache"} 253 +# HELP node_lnstat_drop_total linux network cache stats +# TYPE node_lnstat_drop_total counter +node_lnstat_drop_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_drop_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_drop_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_drop_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_early_drop_total linux network cache stats +# TYPE node_lnstat_early_drop_total counter +node_lnstat_early_drop_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_early_drop_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_early_drop_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_early_drop_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_entries_total linux network cache stats +# TYPE node_lnstat_entries_total counter +node_lnstat_entries_total{cpu="0",subsystem="arp_cache"} 20 +node_lnstat_entries_total{cpu="0",subsystem="ndisc_cache"} 36 +node_lnstat_entries_total{cpu="0",subsystem="nf_conntrack"} 33 +node_lnstat_entries_total{cpu="1",subsystem="arp_cache"} 20 +node_lnstat_entries_total{cpu="1",subsystem="ndisc_cache"} 36 +node_lnstat_entries_total{cpu="1",subsystem="nf_conntrack"} 33 +node_lnstat_entries_total{cpu="2",subsystem="nf_conntrack"} 33 +node_lnstat_entries_total{cpu="3",subsystem="nf_conntrack"} 33 +# HELP node_lnstat_expect_create_total linux network cache stats +# TYPE node_lnstat_expect_create_total counter +node_lnstat_expect_create_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_expect_create_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_expect_create_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_expect_create_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_expect_delete_total linux network cache stats +# TYPE node_lnstat_expect_delete_total counter +node_lnstat_expect_delete_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_expect_delete_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_expect_delete_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_expect_delete_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_expect_new_total linux network cache stats +# TYPE node_lnstat_expect_new_total counter +node_lnstat_expect_new_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_expect_new_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_expect_new_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_expect_new_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_forced_gc_runs_total linux network cache stats +# TYPE node_lnstat_forced_gc_runs_total counter +node_lnstat_forced_gc_runs_total{cpu="0",subsystem="arp_cache"} 10 +node_lnstat_forced_gc_runs_total{cpu="0",subsystem="ndisc_cache"} 249 +node_lnstat_forced_gc_runs_total{cpu="1",subsystem="arp_cache"} 22 +node_lnstat_forced_gc_runs_total{cpu="1",subsystem="ndisc_cache"} 261 +# HELP node_lnstat_found_total linux network cache stats +# TYPE node_lnstat_found_total counter +node_lnstat_found_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_found_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_found_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_found_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_hash_grows_total linux network cache stats +# TYPE node_lnstat_hash_grows_total counter +node_lnstat_hash_grows_total{cpu="0",subsystem="arp_cache"} 3 +node_lnstat_hash_grows_total{cpu="0",subsystem="ndisc_cache"} 242 +node_lnstat_hash_grows_total{cpu="1",subsystem="arp_cache"} 15 +node_lnstat_hash_grows_total{cpu="1",subsystem="ndisc_cache"} 254 +# HELP node_lnstat_hits_total linux network cache stats +# TYPE node_lnstat_hits_total counter +node_lnstat_hits_total{cpu="0",subsystem="arp_cache"} 5 +node_lnstat_hits_total{cpu="0",subsystem="ndisc_cache"} 244 +node_lnstat_hits_total{cpu="1",subsystem="arp_cache"} 17 +node_lnstat_hits_total{cpu="1",subsystem="ndisc_cache"} 256 +# HELP node_lnstat_icmp_error_total linux network cache stats +# TYPE node_lnstat_icmp_error_total counter +node_lnstat_icmp_error_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_icmp_error_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_icmp_error_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_icmp_error_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_ignore_total linux network cache stats +# TYPE node_lnstat_ignore_total counter +node_lnstat_ignore_total{cpu="0",subsystem="nf_conntrack"} 22666 +node_lnstat_ignore_total{cpu="1",subsystem="nf_conntrack"} 22180 +node_lnstat_ignore_total{cpu="2",subsystem="nf_conntrack"} 22740 +node_lnstat_ignore_total{cpu="3",subsystem="nf_conntrack"} 22152 +# HELP node_lnstat_insert_failed_total linux network cache stats +# TYPE node_lnstat_insert_failed_total counter +node_lnstat_insert_failed_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_insert_failed_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_insert_failed_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_insert_failed_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_insert_total linux network cache stats +# TYPE node_lnstat_insert_total counter +node_lnstat_insert_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_insert_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_insert_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_insert_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_invalid_total linux network cache stats +# TYPE node_lnstat_invalid_total counter +node_lnstat_invalid_total{cpu="0",subsystem="nf_conntrack"} 3 +node_lnstat_invalid_total{cpu="1",subsystem="nf_conntrack"} 2 +node_lnstat_invalid_total{cpu="2",subsystem="nf_conntrack"} 1 +node_lnstat_invalid_total{cpu="3",subsystem="nf_conntrack"} 47 +# HELP node_lnstat_lookups_total linux network cache stats +# TYPE node_lnstat_lookups_total counter +node_lnstat_lookups_total{cpu="0",subsystem="arp_cache"} 4 +node_lnstat_lookups_total{cpu="0",subsystem="ndisc_cache"} 243 +node_lnstat_lookups_total{cpu="1",subsystem="arp_cache"} 16 +node_lnstat_lookups_total{cpu="1",subsystem="ndisc_cache"} 255 +# HELP node_lnstat_new_total linux network cache stats +# TYPE node_lnstat_new_total counter +node_lnstat_new_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_new_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_new_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_new_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_periodic_gc_runs_total linux network cache stats +# TYPE node_lnstat_periodic_gc_runs_total counter +node_lnstat_periodic_gc_runs_total{cpu="0",subsystem="arp_cache"} 9 +node_lnstat_periodic_gc_runs_total{cpu="0",subsystem="ndisc_cache"} 248 +node_lnstat_periodic_gc_runs_total{cpu="1",subsystem="arp_cache"} 21 +node_lnstat_periodic_gc_runs_total{cpu="1",subsystem="ndisc_cache"} 260 +# HELP node_lnstat_rcv_probes_mcast_total linux network cache stats +# TYPE node_lnstat_rcv_probes_mcast_total counter +node_lnstat_rcv_probes_mcast_total{cpu="0",subsystem="arp_cache"} 7 +node_lnstat_rcv_probes_mcast_total{cpu="0",subsystem="ndisc_cache"} 246 +node_lnstat_rcv_probes_mcast_total{cpu="1",subsystem="arp_cache"} 19 +node_lnstat_rcv_probes_mcast_total{cpu="1",subsystem="ndisc_cache"} 258 +# HELP node_lnstat_rcv_probes_ucast_total linux network cache stats +# TYPE node_lnstat_rcv_probes_ucast_total counter +node_lnstat_rcv_probes_ucast_total{cpu="0",subsystem="arp_cache"} 8 +node_lnstat_rcv_probes_ucast_total{cpu="0",subsystem="ndisc_cache"} 247 +node_lnstat_rcv_probes_ucast_total{cpu="1",subsystem="arp_cache"} 20 +node_lnstat_rcv_probes_ucast_total{cpu="1",subsystem="ndisc_cache"} 259 +# HELP node_lnstat_res_failed_total linux network cache stats +# TYPE node_lnstat_res_failed_total counter +node_lnstat_res_failed_total{cpu="0",subsystem="arp_cache"} 6 +node_lnstat_res_failed_total{cpu="0",subsystem="ndisc_cache"} 245 +node_lnstat_res_failed_total{cpu="1",subsystem="arp_cache"} 18 +node_lnstat_res_failed_total{cpu="1",subsystem="ndisc_cache"} 257 +# HELP node_lnstat_search_restart_total linux network cache stats +# TYPE node_lnstat_search_restart_total counter +node_lnstat_search_restart_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_search_restart_total{cpu="1",subsystem="nf_conntrack"} 2 +node_lnstat_search_restart_total{cpu="2",subsystem="nf_conntrack"} 1 +node_lnstat_search_restart_total{cpu="3",subsystem="nf_conntrack"} 4 +# HELP node_lnstat_searched_total linux network cache stats +# TYPE node_lnstat_searched_total counter +node_lnstat_searched_total{cpu="0",subsystem="nf_conntrack"} 0 +node_lnstat_searched_total{cpu="1",subsystem="nf_conntrack"} 0 +node_lnstat_searched_total{cpu="2",subsystem="nf_conntrack"} 0 +node_lnstat_searched_total{cpu="3",subsystem="nf_conntrack"} 0 +# HELP node_lnstat_table_fulls_total linux network cache stats +# TYPE node_lnstat_table_fulls_total counter +node_lnstat_table_fulls_total{cpu="0",subsystem="arp_cache"} 12 +node_lnstat_table_fulls_total{cpu="0",subsystem="ndisc_cache"} 251 +node_lnstat_table_fulls_total{cpu="1",subsystem="arp_cache"} 24 +node_lnstat_table_fulls_total{cpu="1",subsystem="ndisc_cache"} 263 +# HELP node_lnstat_unresolved_discards_total linux network cache stats +# TYPE node_lnstat_unresolved_discards_total counter +node_lnstat_unresolved_discards_total{cpu="0",subsystem="arp_cache"} 11 +node_lnstat_unresolved_discards_total{cpu="0",subsystem="ndisc_cache"} 250 +node_lnstat_unresolved_discards_total{cpu="1",subsystem="arp_cache"} 23 +node_lnstat_unresolved_discards_total{cpu="1",subsystem="ndisc_cache"} 262 # HELP node_load1 1m load average. # TYPE node_load1 gauge node_load1 0.21 @@ -1129,6 +1516,7 @@ node_md_blocks{device="md12"} 3.886394368e+09 node_md_blocks{device="md120"} 2.095104e+06 node_md_blocks{device="md126"} 1.855870976e+09 node_md_blocks{device="md127"} 3.12319552e+08 +node_md_blocks{device="md201"} 1.993728e+06 node_md_blocks{device="md219"} 7932 node_md_blocks{device="md3"} 5.853468288e+09 node_md_blocks{device="md4"} 4.883648e+06 @@ -1147,6 +1535,7 @@ node_md_blocks_synced{device="md12"} 3.886394368e+09 node_md_blocks_synced{device="md120"} 2.095104e+06 node_md_blocks_synced{device="md126"} 1.855870976e+09 node_md_blocks_synced{device="md127"} 3.12319552e+08 +node_md_blocks_synced{device="md201"} 114176 node_md_blocks_synced{device="md219"} 7932 node_md_blocks_synced{device="md3"} 5.853468288e+09 node_md_blocks_synced{device="md4"} 4.883648e+06 @@ -1183,6 +1572,9 @@ node_md_disks{device="md126",state="spare"} 0 node_md_disks{device="md127",state="active"} 2 node_md_disks{device="md127",state="failed"} 0 node_md_disks{device="md127",state="spare"} 0 +node_md_disks{device="md201",state="active"} 2 +node_md_disks{device="md201",state="failed"} 0 +node_md_disks{device="md201",state="spare"} 0 node_md_disks{device="md219",state="active"} 0 node_md_disks{device="md219",state="failed"} 0 node_md_disks{device="md219",state="spare"} 3 @@ -1215,6 +1607,7 @@ node_md_disks_required{device="md12"} 2 node_md_disks_required{device="md120"} 2 node_md_disks_required{device="md126"} 2 node_md_disks_required{device="md127"} 2 +node_md_disks_required{device="md201"} 2 node_md_disks_required{device="md219"} 0 node_md_disks_required{device="md3"} 8 node_md_disks_required{device="md4"} 0 @@ -1225,66 +1618,87 @@ node_md_disks_required{device="md9"} 4 # HELP node_md_state Indicates the state of md-device. # TYPE node_md_state gauge node_md_state{device="md0",state="active"} 1 +node_md_state{device="md0",state="check"} 0 node_md_state{device="md0",state="inactive"} 0 node_md_state{device="md0",state="recovering"} 0 node_md_state{device="md0",state="resync"} 0 node_md_state{device="md00",state="active"} 1 +node_md_state{device="md00",state="check"} 0 node_md_state{device="md00",state="inactive"} 0 node_md_state{device="md00",state="recovering"} 0 node_md_state{device="md00",state="resync"} 0 node_md_state{device="md10",state="active"} 1 +node_md_state{device="md10",state="check"} 0 node_md_state{device="md10",state="inactive"} 0 node_md_state{device="md10",state="recovering"} 0 node_md_state{device="md10",state="resync"} 0 node_md_state{device="md101",state="active"} 1 +node_md_state{device="md101",state="check"} 0 node_md_state{device="md101",state="inactive"} 0 node_md_state{device="md101",state="recovering"} 0 node_md_state{device="md101",state="resync"} 0 node_md_state{device="md11",state="active"} 0 +node_md_state{device="md11",state="check"} 0 node_md_state{device="md11",state="inactive"} 0 node_md_state{device="md11",state="recovering"} 0 node_md_state{device="md11",state="resync"} 1 node_md_state{device="md12",state="active"} 1 +node_md_state{device="md12",state="check"} 0 node_md_state{device="md12",state="inactive"} 0 node_md_state{device="md12",state="recovering"} 0 node_md_state{device="md12",state="resync"} 0 node_md_state{device="md120",state="active"} 1 +node_md_state{device="md120",state="check"} 0 node_md_state{device="md120",state="inactive"} 0 node_md_state{device="md120",state="recovering"} 0 node_md_state{device="md120",state="resync"} 0 node_md_state{device="md126",state="active"} 1 +node_md_state{device="md126",state="check"} 0 node_md_state{device="md126",state="inactive"} 0 node_md_state{device="md126",state="recovering"} 0 node_md_state{device="md126",state="resync"} 0 node_md_state{device="md127",state="active"} 1 +node_md_state{device="md127",state="check"} 0 node_md_state{device="md127",state="inactive"} 0 node_md_state{device="md127",state="recovering"} 0 node_md_state{device="md127",state="resync"} 0 +node_md_state{device="md201",state="active"} 0 +node_md_state{device="md201",state="check"} 1 +node_md_state{device="md201",state="inactive"} 0 +node_md_state{device="md201",state="recovering"} 0 +node_md_state{device="md201",state="resync"} 0 node_md_state{device="md219",state="active"} 0 +node_md_state{device="md219",state="check"} 0 node_md_state{device="md219",state="inactive"} 1 node_md_state{device="md219",state="recovering"} 0 node_md_state{device="md219",state="resync"} 0 node_md_state{device="md3",state="active"} 1 +node_md_state{device="md3",state="check"} 0 node_md_state{device="md3",state="inactive"} 0 node_md_state{device="md3",state="recovering"} 0 node_md_state{device="md3",state="resync"} 0 node_md_state{device="md4",state="active"} 0 +node_md_state{device="md4",state="check"} 0 node_md_state{device="md4",state="inactive"} 1 node_md_state{device="md4",state="recovering"} 0 node_md_state{device="md4",state="resync"} 0 node_md_state{device="md6",state="active"} 0 +node_md_state{device="md6",state="check"} 0 node_md_state{device="md6",state="inactive"} 0 node_md_state{device="md6",state="recovering"} 1 node_md_state{device="md6",state="resync"} 0 node_md_state{device="md7",state="active"} 1 +node_md_state{device="md7",state="check"} 0 node_md_state{device="md7",state="inactive"} 0 node_md_state{device="md7",state="recovering"} 0 node_md_state{device="md7",state="resync"} 0 node_md_state{device="md8",state="active"} 0 +node_md_state{device="md8",state="check"} 0 node_md_state{device="md8",state="inactive"} 0 node_md_state{device="md8",state="recovering"} 0 node_md_state{device="md8",state="resync"} 1 node_md_state{device="md9",state="active"} 0 +node_md_state{device="md9",state="check"} 0 node_md_state{device="md9",state="inactive"} 0 node_md_state{device="md9",state="recovering"} 0 node_md_state{device="md9",state="resync"} 1 @@ -1889,6 +2303,12 @@ node_netstat_TcpExt_SyncookiesRecv 0 # HELP node_netstat_TcpExt_SyncookiesSent Statistic TcpExtSyncookiesSent. # TYPE node_netstat_TcpExt_SyncookiesSent untyped node_netstat_TcpExt_SyncookiesSent 0 +# HELP node_netstat_TcpExt_TCPOFOQueue Statistic TcpExtTCPOFOQueue. +# TYPE node_netstat_TcpExt_TCPOFOQueue untyped +node_netstat_TcpExt_TCPOFOQueue 42 +# HELP node_netstat_TcpExt_TCPTimeouts Statistic TcpExtTCPTimeouts. +# TYPE node_netstat_TcpExt_TCPTimeouts untyped +node_netstat_TcpExt_TCPTimeouts 115 # HELP node_netstat_Tcp_ActiveOpens Statistic TcpActiveOpens. # TYPE node_netstat_Tcp_ActiveOpens untyped node_netstat_Tcp_ActiveOpens 3556 @@ -1955,254 +2375,127 @@ node_netstat_Udp_RcvbufErrors 9 # HELP node_netstat_Udp_SndbufErrors Statistic UdpSndbufErrors. # TYPE node_netstat_Udp_SndbufErrors untyped node_netstat_Udp_SndbufErrors 8 -# HELP node_network_address_assign_type address_assign_type value of /sys/class/net/. +# HELP node_network_address_assign_type Network device property: address_assign_type # TYPE node_network_address_assign_type gauge +node_network_address_assign_type{device="bond0"} 3 node_network_address_assign_type{device="eth0"} 3 -# HELP node_network_carrier carrier value of /sys/class/net/. +# HELP node_network_carrier Network device property: carrier # TYPE node_network_carrier gauge +node_network_carrier{device="bond0"} 1 node_network_carrier{device="eth0"} 1 -# HELP node_network_carrier_changes_total carrier_changes_total value of /sys/class/net/. +# HELP node_network_carrier_changes_total Network device property: carrier_changes_total # TYPE node_network_carrier_changes_total counter +node_network_carrier_changes_total{device="bond0"} 2 node_network_carrier_changes_total{device="eth0"} 2 -# HELP node_network_carrier_down_changes_total carrier_down_changes_total value of /sys/class/net/. +# HELP node_network_carrier_down_changes_total Network device property: carrier_down_changes_total # TYPE node_network_carrier_down_changes_total counter +node_network_carrier_down_changes_total{device="bond0"} 1 node_network_carrier_down_changes_total{device="eth0"} 1 -# HELP node_network_carrier_up_changes_total carrier_up_changes_total value of /sys/class/net/. +# HELP node_network_carrier_up_changes_total Network device property: carrier_up_changes_total # TYPE node_network_carrier_up_changes_total counter +node_network_carrier_up_changes_total{device="bond0"} 1 node_network_carrier_up_changes_total{device="eth0"} 1 -# HELP node_network_device_id device_id value of /sys/class/net/. +# HELP node_network_device_id Network device property: device_id # TYPE node_network_device_id gauge +node_network_device_id{device="bond0"} 32 node_network_device_id{device="eth0"} 32 -# HELP node_network_dormant dormant value of /sys/class/net/. +# HELP node_network_dormant Network device property: dormant # TYPE node_network_dormant gauge +node_network_dormant{device="bond0"} 1 node_network_dormant{device="eth0"} 1 -# HELP node_network_flags flags value of /sys/class/net/. +# HELP node_network_flags Network device property: flags # TYPE node_network_flags gauge +node_network_flags{device="bond0"} 4867 node_network_flags{device="eth0"} 4867 -# HELP node_network_iface_id iface_id value of /sys/class/net/. +# HELP node_network_iface_id Network device property: iface_id # TYPE node_network_iface_id gauge +node_network_iface_id{device="bond0"} 2 node_network_iface_id{device="eth0"} 2 -# HELP node_network_iface_link iface_link value of /sys/class/net/. +# HELP node_network_iface_link Network device property: iface_link # TYPE node_network_iface_link gauge +node_network_iface_link{device="bond0"} 2 node_network_iface_link{device="eth0"} 2 -# HELP node_network_iface_link_mode iface_link_mode value of /sys/class/net/. +# HELP node_network_iface_link_mode Network device property: iface_link_mode # TYPE node_network_iface_link_mode gauge +node_network_iface_link_mode{device="bond0"} 1 node_network_iface_link_mode{device="eth0"} 1 # HELP node_network_info Non-numeric data from /sys/class/net/, value is always 1. # TYPE node_network_info gauge -node_network_info{address="01:01:01:01:01:01",broadcast="ff:ff:ff:ff:ff:ff",device="eth0",duplex="full",ifalias="",operstate="up"} 1 -# HELP node_network_mtu_bytes mtu_bytes value of /sys/class/net/. +node_network_info{address="01:01:01:01:01:01",adminstate="up",broadcast="ff:ff:ff:ff:ff:ff",device="bond0",duplex="full",ifalias="",operstate="up"} 1 +node_network_info{address="01:01:01:01:01:01",adminstate="up",broadcast="ff:ff:ff:ff:ff:ff",device="eth0",duplex="full",ifalias="",operstate="up"} 1 +# HELP node_network_mtu_bytes Network device property: mtu_bytes # TYPE node_network_mtu_bytes gauge +node_network_mtu_bytes{device="bond0"} 1500 node_network_mtu_bytes{device="eth0"} 1500 -# HELP node_network_name_assign_type name_assign_type value of /sys/class/net/. +# HELP node_network_name_assign_type Network device property: name_assign_type # TYPE node_network_name_assign_type gauge +node_network_name_assign_type{device="bond0"} 2 node_network_name_assign_type{device="eth0"} 2 -# HELP node_network_net_dev_group net_dev_group value of /sys/class/net/. +# HELP node_network_net_dev_group Network device property: net_dev_group # TYPE node_network_net_dev_group gauge +node_network_net_dev_group{device="bond0"} 0 node_network_net_dev_group{device="eth0"} 0 -# HELP node_network_protocol_type protocol_type value of /sys/class/net/. +# HELP node_network_protocol_type Network device property: protocol_type # TYPE node_network_protocol_type gauge +node_network_protocol_type{device="bond0"} 1 node_network_protocol_type{device="eth0"} 1 # HELP node_network_receive_bytes_total Network device statistic receive_bytes. # TYPE node_network_receive_bytes_total counter -node_network_receive_bytes_total{device="docker0"} 6.4910168e+07 -node_network_receive_bytes_total{device="eth0"} 6.8210035552e+10 -node_network_receive_bytes_total{device="flannel.1"} 1.8144009813e+10 -node_network_receive_bytes_total{device="ibr10:30"} 0 -node_network_receive_bytes_total{device="lo"} 4.35303245e+08 -node_network_receive_bytes_total{device="lxcbr0"} 0 -node_network_receive_bytes_total{device="tun0"} 1888 -node_network_receive_bytes_total{device="veth4B09XN"} 648 -node_network_receive_bytes_total{device="wlan0"} 1.0437182923e+10 -node_network_receive_bytes_total{device="💩0"} 5.7750104e+07 # HELP node_network_receive_compressed_total Network device statistic receive_compressed. # TYPE node_network_receive_compressed_total counter -node_network_receive_compressed_total{device="docker0"} 0 -node_network_receive_compressed_total{device="eth0"} 0 -node_network_receive_compressed_total{device="flannel.1"} 0 -node_network_receive_compressed_total{device="ibr10:30"} 0 node_network_receive_compressed_total{device="lo"} 0 -node_network_receive_compressed_total{device="lxcbr0"} 0 -node_network_receive_compressed_total{device="tun0"} 0 -node_network_receive_compressed_total{device="veth4B09XN"} 0 -node_network_receive_compressed_total{device="wlan0"} 0 -node_network_receive_compressed_total{device="💩0"} 0 # HELP node_network_receive_drop_total Network device statistic receive_drop. # TYPE node_network_receive_drop_total counter -node_network_receive_drop_total{device="docker0"} 0 -node_network_receive_drop_total{device="eth0"} 0 -node_network_receive_drop_total{device="flannel.1"} 0 -node_network_receive_drop_total{device="ibr10:30"} 0 node_network_receive_drop_total{device="lo"} 0 -node_network_receive_drop_total{device="lxcbr0"} 0 -node_network_receive_drop_total{device="tun0"} 0 -node_network_receive_drop_total{device="veth4B09XN"} 0 -node_network_receive_drop_total{device="wlan0"} 0 -node_network_receive_drop_total{device="💩0"} 0 # HELP node_network_receive_errs_total Network device statistic receive_errs. # TYPE node_network_receive_errs_total counter -node_network_receive_errs_total{device="docker0"} 0 -node_network_receive_errs_total{device="eth0"} 0 -node_network_receive_errs_total{device="flannel.1"} 0 -node_network_receive_errs_total{device="ibr10:30"} 0 node_network_receive_errs_total{device="lo"} 0 -node_network_receive_errs_total{device="lxcbr0"} 0 -node_network_receive_errs_total{device="tun0"} 0 -node_network_receive_errs_total{device="veth4B09XN"} 0 -node_network_receive_errs_total{device="wlan0"} 0 -node_network_receive_errs_total{device="💩0"} 0 # HELP node_network_receive_fifo_total Network device statistic receive_fifo. # TYPE node_network_receive_fifo_total counter -node_network_receive_fifo_total{device="docker0"} 0 -node_network_receive_fifo_total{device="eth0"} 0 -node_network_receive_fifo_total{device="flannel.1"} 0 -node_network_receive_fifo_total{device="ibr10:30"} 0 node_network_receive_fifo_total{device="lo"} 0 -node_network_receive_fifo_total{device="lxcbr0"} 0 -node_network_receive_fifo_total{device="tun0"} 0 -node_network_receive_fifo_total{device="veth4B09XN"} 0 -node_network_receive_fifo_total{device="wlan0"} 0 -node_network_receive_fifo_total{device="💩0"} 0 # HELP node_network_receive_frame_total Network device statistic receive_frame. # TYPE node_network_receive_frame_total counter -node_network_receive_frame_total{device="docker0"} 0 -node_network_receive_frame_total{device="eth0"} 0 -node_network_receive_frame_total{device="flannel.1"} 0 -node_network_receive_frame_total{device="ibr10:30"} 0 node_network_receive_frame_total{device="lo"} 0 -node_network_receive_frame_total{device="lxcbr0"} 0 -node_network_receive_frame_total{device="tun0"} 0 -node_network_receive_frame_total{device="veth4B09XN"} 0 -node_network_receive_frame_total{device="wlan0"} 0 -node_network_receive_frame_total{device="💩0"} 0 # HELP node_network_receive_multicast_total Network device statistic receive_multicast. # TYPE node_network_receive_multicast_total counter -node_network_receive_multicast_total{device="docker0"} 0 -node_network_receive_multicast_total{device="eth0"} 0 -node_network_receive_multicast_total{device="flannel.1"} 0 -node_network_receive_multicast_total{device="ibr10:30"} 0 node_network_receive_multicast_total{device="lo"} 0 -node_network_receive_multicast_total{device="lxcbr0"} 0 -node_network_receive_multicast_total{device="tun0"} 0 -node_network_receive_multicast_total{device="veth4B09XN"} 0 -node_network_receive_multicast_total{device="wlan0"} 0 -node_network_receive_multicast_total{device="💩0"} 72 +# HELP node_network_receive_nohandler_total Network device statistic receive_nohandler. +# TYPE node_network_receive_nohandler_total counter +node_network_receive_nohandler_total{device="lo"} 0 # HELP node_network_receive_packets_total Network device statistic receive_packets. # TYPE node_network_receive_packets_total counter -node_network_receive_packets_total{device="docker0"} 1.065585e+06 -node_network_receive_packets_total{device="eth0"} 5.20993275e+08 -node_network_receive_packets_total{device="flannel.1"} 2.28499337e+08 -node_network_receive_packets_total{device="ibr10:30"} 0 -node_network_receive_packets_total{device="lo"} 1.832522e+06 -node_network_receive_packets_total{device="lxcbr0"} 0 -node_network_receive_packets_total{device="tun0"} 24 -node_network_receive_packets_total{device="veth4B09XN"} 8 -node_network_receive_packets_total{device="wlan0"} 1.3899359e+07 -node_network_receive_packets_total{device="💩0"} 105557 -# HELP node_network_speed_bytes speed_bytes value of /sys/class/net/. +# HELP node_network_speed_bytes Network device property: speed_bytes # TYPE node_network_speed_bytes gauge node_network_speed_bytes{device="eth0"} 1.25e+08 # HELP node_network_transmit_bytes_total Network device statistic transmit_bytes. # TYPE node_network_transmit_bytes_total counter -node_network_transmit_bytes_total{device="docker0"} 2.681662018e+09 -node_network_transmit_bytes_total{device="eth0"} 9.315587528e+09 -node_network_transmit_bytes_total{device="flannel.1"} 2.0758990068e+10 -node_network_transmit_bytes_total{device="ibr10:30"} 0 -node_network_transmit_bytes_total{device="lo"} 4.35303245e+08 -node_network_transmit_bytes_total{device="lxcbr0"} 2.630299e+06 -node_network_transmit_bytes_total{device="tun0"} 67120 -node_network_transmit_bytes_total{device="veth4B09XN"} 1.943284e+06 -node_network_transmit_bytes_total{device="wlan0"} 2.85164936e+09 -node_network_transmit_bytes_total{device="💩0"} 4.04570255e+08 # HELP node_network_transmit_carrier_total Network device statistic transmit_carrier. # TYPE node_network_transmit_carrier_total counter -node_network_transmit_carrier_total{device="docker0"} 0 -node_network_transmit_carrier_total{device="eth0"} 0 -node_network_transmit_carrier_total{device="flannel.1"} 0 -node_network_transmit_carrier_total{device="ibr10:30"} 0 node_network_transmit_carrier_total{device="lo"} 0 -node_network_transmit_carrier_total{device="lxcbr0"} 0 -node_network_transmit_carrier_total{device="tun0"} 0 -node_network_transmit_carrier_total{device="veth4B09XN"} 0 -node_network_transmit_carrier_total{device="wlan0"} 0 -node_network_transmit_carrier_total{device="💩0"} 0 # HELP node_network_transmit_colls_total Network device statistic transmit_colls. # TYPE node_network_transmit_colls_total counter -node_network_transmit_colls_total{device="docker0"} 0 -node_network_transmit_colls_total{device="eth0"} 0 -node_network_transmit_colls_total{device="flannel.1"} 0 -node_network_transmit_colls_total{device="ibr10:30"} 0 node_network_transmit_colls_total{device="lo"} 0 -node_network_transmit_colls_total{device="lxcbr0"} 0 -node_network_transmit_colls_total{device="tun0"} 0 -node_network_transmit_colls_total{device="veth4B09XN"} 0 -node_network_transmit_colls_total{device="wlan0"} 0 -node_network_transmit_colls_total{device="💩0"} 0 # HELP node_network_transmit_compressed_total Network device statistic transmit_compressed. # TYPE node_network_transmit_compressed_total counter -node_network_transmit_compressed_total{device="docker0"} 0 -node_network_transmit_compressed_total{device="eth0"} 0 -node_network_transmit_compressed_total{device="flannel.1"} 0 -node_network_transmit_compressed_total{device="ibr10:30"} 0 node_network_transmit_compressed_total{device="lo"} 0 -node_network_transmit_compressed_total{device="lxcbr0"} 0 -node_network_transmit_compressed_total{device="tun0"} 0 -node_network_transmit_compressed_total{device="veth4B09XN"} 0 -node_network_transmit_compressed_total{device="wlan0"} 0 -node_network_transmit_compressed_total{device="💩0"} 0 # HELP node_network_transmit_drop_total Network device statistic transmit_drop. # TYPE node_network_transmit_drop_total counter -node_network_transmit_drop_total{device="docker0"} 0 -node_network_transmit_drop_total{device="eth0"} 0 -node_network_transmit_drop_total{device="flannel.1"} 64 -node_network_transmit_drop_total{device="ibr10:30"} 0 node_network_transmit_drop_total{device="lo"} 0 -node_network_transmit_drop_total{device="lxcbr0"} 0 -node_network_transmit_drop_total{device="tun0"} 0 -node_network_transmit_drop_total{device="veth4B09XN"} 0 -node_network_transmit_drop_total{device="wlan0"} 0 -node_network_transmit_drop_total{device="💩0"} 0 # HELP node_network_transmit_errs_total Network device statistic transmit_errs. # TYPE node_network_transmit_errs_total counter -node_network_transmit_errs_total{device="docker0"} 0 -node_network_transmit_errs_total{device="eth0"} 0 -node_network_transmit_errs_total{device="flannel.1"} 0 -node_network_transmit_errs_total{device="ibr10:30"} 0 node_network_transmit_errs_total{device="lo"} 0 -node_network_transmit_errs_total{device="lxcbr0"} 0 -node_network_transmit_errs_total{device="tun0"} 0 -node_network_transmit_errs_total{device="veth4B09XN"} 0 -node_network_transmit_errs_total{device="wlan0"} 0 -node_network_transmit_errs_total{device="💩0"} 0 # HELP node_network_transmit_fifo_total Network device statistic transmit_fifo. # TYPE node_network_transmit_fifo_total counter -node_network_transmit_fifo_total{device="docker0"} 0 -node_network_transmit_fifo_total{device="eth0"} 0 -node_network_transmit_fifo_total{device="flannel.1"} 0 -node_network_transmit_fifo_total{device="ibr10:30"} 0 node_network_transmit_fifo_total{device="lo"} 0 -node_network_transmit_fifo_total{device="lxcbr0"} 0 -node_network_transmit_fifo_total{device="tun0"} 0 -node_network_transmit_fifo_total{device="veth4B09XN"} 0 -node_network_transmit_fifo_total{device="wlan0"} 0 -node_network_transmit_fifo_total{device="💩0"} 0 # HELP node_network_transmit_packets_total Network device statistic transmit_packets. # TYPE node_network_transmit_packets_total counter -node_network_transmit_packets_total{device="docker0"} 1.929779e+06 -node_network_transmit_packets_total{device="eth0"} 4.3451486e+07 -node_network_transmit_packets_total{device="flannel.1"} 2.58369223e+08 -node_network_transmit_packets_total{device="ibr10:30"} 0 -node_network_transmit_packets_total{device="lo"} 1.832522e+06 -node_network_transmit_packets_total{device="lxcbr0"} 28339 -node_network_transmit_packets_total{device="tun0"} 934 -node_network_transmit_packets_total{device="veth4B09XN"} 10640 -node_network_transmit_packets_total{device="wlan0"} 1.17262e+07 -node_network_transmit_packets_total{device="💩0"} 304261 -# HELP node_network_transmit_queue_length transmit_queue_length value of /sys/class/net/. +# HELP node_network_transmit_queue_length Network device property: transmit_queue_length # TYPE node_network_transmit_queue_length gauge +node_network_transmit_queue_length{device="bond0"} 1000 node_network_transmit_queue_length{device="eth0"} 1000 # HELP node_network_up Value is 1 if operstate is 'up', 0 otherwise. # TYPE node_network_up gauge +node_network_up{device="bond0"} 1 node_network_up{device="eth0"} 1 # HELP node_nf_conntrack_entries Number of currently allocated flow entries for connection tracking. # TYPE node_nf_conntrack_entries gauge @@ -2210,6 +2503,30 @@ node_nf_conntrack_entries 123 # HELP node_nf_conntrack_entries_limit Maximum size of connection tracking table. # TYPE node_nf_conntrack_entries_limit gauge node_nf_conntrack_entries_limit 65536 +# HELP node_nf_conntrack_stat_drop Number of packets dropped due to conntrack failure. +# TYPE node_nf_conntrack_stat_drop gauge +node_nf_conntrack_stat_drop 0 +# HELP node_nf_conntrack_stat_early_drop Number of dropped conntrack entries to make room for new ones, if maximum table size was reached. +# TYPE node_nf_conntrack_stat_early_drop gauge +node_nf_conntrack_stat_early_drop 0 +# HELP node_nf_conntrack_stat_found Number of searched entries which were successful. +# TYPE node_nf_conntrack_stat_found gauge +node_nf_conntrack_stat_found 0 +# HELP node_nf_conntrack_stat_ignore Number of packets seen which are already connected to a conntrack entry. +# TYPE node_nf_conntrack_stat_ignore gauge +node_nf_conntrack_stat_ignore 89738 +# HELP node_nf_conntrack_stat_insert Number of entries inserted into the list. +# TYPE node_nf_conntrack_stat_insert gauge +node_nf_conntrack_stat_insert 0 +# HELP node_nf_conntrack_stat_insert_failed Number of entries for which list insertion was attempted but failed. +# TYPE node_nf_conntrack_stat_insert_failed gauge +node_nf_conntrack_stat_insert_failed 0 +# HELP node_nf_conntrack_stat_invalid Number of packets seen which can not be tracked. +# TYPE node_nf_conntrack_stat_invalid gauge +node_nf_conntrack_stat_invalid 53 +# HELP node_nf_conntrack_stat_search_restart Number of conntrack table lookups which had to be restarted due to hashtable resizes. +# TYPE node_nf_conntrack_stat_search_restart gauge +node_nf_conntrack_stat_search_restart 7 # HELP node_nfs_connections_total Total number of NFSd TCP connections. # TYPE node_nfs_connections_total counter node_nfs_connections_total 45 @@ -2424,13 +2741,16 @@ node_nfsd_requests_total{method="SecInfo",proto="4"} 0 node_nfsd_requests_total{method="SetAttr",proto="2"} 0 node_nfsd_requests_total{method="SetAttr",proto="3"} 0 node_nfsd_requests_total{method="SetAttr",proto="4"} 0 +node_nfsd_requests_total{method="SetClientID",proto="4"} 3 +node_nfsd_requests_total{method="SetClientIDConfirm",proto="4"} 3 node_nfsd_requests_total{method="SymLink",proto="2"} 0 node_nfsd_requests_total{method="SymLink",proto="3"} 0 -node_nfsd_requests_total{method="Verify",proto="4"} 3 +node_nfsd_requests_total{method="Verify",proto="4"} 0 +node_nfsd_requests_total{method="WdelegGetattr",proto="4"} 15 node_nfsd_requests_total{method="WrCache",proto="2"} 0 node_nfsd_requests_total{method="Write",proto="2"} 0 node_nfsd_requests_total{method="Write",proto="3"} 0 -node_nfsd_requests_total{method="Write",proto="4"} 3 +node_nfsd_requests_total{method="Write",proto="4"} 0 # HELP node_nfsd_rpc_errors_total Total number of NFSd RPC errors by error type. # TYPE node_nfsd_rpc_errors_total counter node_nfsd_rpc_errors_total{error="auth"} 2 @@ -2459,32 +2779,32 @@ node_power_supply_capacity{power_supply="BAT0"} 81 node_power_supply_cyclecount{power_supply="BAT0"} 0 # HELP node_power_supply_energy_full energy_full value of /sys/class/power_supply/. # TYPE node_power_supply_energy_full gauge -node_power_supply_energy_full{power_supply="BAT0"} 4.507e+07 +node_power_supply_energy_full{power_supply="BAT0"} 45.07 # HELP node_power_supply_energy_full_design energy_full_design value of /sys/class/power_supply/. # TYPE node_power_supply_energy_full_design gauge -node_power_supply_energy_full_design{power_supply="BAT0"} 4.752e+07 -# HELP node_power_supply_energy_now energy_now value of /sys/class/power_supply/. -# TYPE node_power_supply_energy_now gauge -node_power_supply_energy_now{power_supply="BAT0"} 3.658e+07 +node_power_supply_energy_full_design{power_supply="BAT0"} 47.52 +# HELP node_power_supply_energy_watthour energy_watthour value of /sys/class/power_supply/. +# TYPE node_power_supply_energy_watthour gauge +node_power_supply_energy_watthour{power_supply="BAT0"} 36.58 # HELP node_power_supply_info info of /sys/class/power_supply/. # TYPE node_power_supply_info gauge node_power_supply_info{power_supply="AC",type="Mains"} 1 -node_power_supply_info{capacity_level="Normal",manufacturer="LGC",model_name="LNV-45N1",power_supply="BAT0",serial_number="38109",status="Discharging",technology="Li-ion",type="Battery"} 1 +node_power_supply_info{capacity_level="Normal",manufacturer="LGC",model_name="LNV-45N1��",power_supply="BAT0",serial_number="38109",status="Discharging",technology="Li-ion",type="Battery"} 1 # HELP node_power_supply_online online value of /sys/class/power_supply/. # TYPE node_power_supply_online gauge node_power_supply_online{power_supply="AC"} 0 -# HELP node_power_supply_power_now power_now value of /sys/class/power_supply/. -# TYPE node_power_supply_power_now gauge -node_power_supply_power_now{power_supply="BAT0"} 5.002e+06 +# HELP node_power_supply_power_watt power_watt value of /sys/class/power_supply/. +# TYPE node_power_supply_power_watt gauge +node_power_supply_power_watt{power_supply="BAT0"} 5.002 # HELP node_power_supply_present present value of /sys/class/power_supply/. # TYPE node_power_supply_present gauge node_power_supply_present{power_supply="BAT0"} 1 # HELP node_power_supply_voltage_min_design voltage_min_design value of /sys/class/power_supply/. # TYPE node_power_supply_voltage_min_design gauge -node_power_supply_voltage_min_design{power_supply="BAT0"} 1.08e+07 -# HELP node_power_supply_voltage_now voltage_now value of /sys/class/power_supply/. -# TYPE node_power_supply_voltage_now gauge -node_power_supply_voltage_now{power_supply="BAT0"} 1.166e+07 +node_power_supply_voltage_min_design{power_supply="BAT0"} 10.8 +# HELP node_power_supply_voltage_volt voltage_volt value of /sys/class/power_supply/. +# TYPE node_power_supply_voltage_volt gauge +node_power_supply_voltage_volt{power_supply="BAT0"} 11.66 # HELP node_pressure_cpu_waiting_seconds_total Total time in seconds that processes have waited for CPU time # TYPE node_pressure_cpu_waiting_seconds_total counter node_pressure_cpu_waiting_seconds_total 14.036781000000001 @@ -2508,13 +2828,14 @@ node_processes_max_processes 123 node_processes_max_threads 7801 # HELP node_processes_pids Number of PIDs # TYPE node_processes_pids gauge -node_processes_pids 1 +node_processes_pids 3 # HELP node_processes_state Number of processes in each state. # TYPE node_processes_state gauge -node_processes_state{state="S"} 1 +node_processes_state{state="I"} 1 +node_processes_state{state="S"} 2 # HELP node_processes_threads Allocated threads in system # TYPE node_processes_threads gauge -node_processes_threads 1 +node_processes_threads 3 # HELP node_procs_blocked Number of processes blocked waiting for I/O to complete. # TYPE node_procs_blocked gauge node_procs_blocked 0 @@ -2551,10 +2872,10 @@ node_qdisc_requeues_total{device="eth0",kind="pfifo_fast"} 2 node_qdisc_requeues_total{device="wlan0",kind="fq"} 1 # HELP node_rapl_core_joules_total Current RAPL core value in joules # TYPE node_rapl_core_joules_total counter -node_rapl_core_joules_total{index="0"} 118821.284256 +node_rapl_core_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0:0"} 118821.284256 # HELP node_rapl_package_joules_total Current RAPL package value in joules # TYPE node_rapl_package_joules_total counter -node_rapl_package_joules_total{index="0"} 240422.366267 +node_rapl_package_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0"} 240422.366267 # HELP node_schedstat_running_seconds_total Number of seconds CPU spent running a process. # TYPE node_schedstat_running_seconds_total counter node_schedstat_running_seconds_total{cpu="0"} 2.045936778163039e+06 @@ -2574,21 +2895,26 @@ node_schedstat_waiting_seconds_total{cpu="1"} 364107.263788241 node_scrape_collector_success{collector="arp"} 1 node_scrape_collector_success{collector="bcache"} 1 node_scrape_collector_success{collector="bonding"} 1 +node_scrape_collector_success{collector="btrfs"} 1 node_scrape_collector_success{collector="buddyinfo"} 1 +node_scrape_collector_success{collector="cgroups"} 1 node_scrape_collector_success{collector="conntrack"} 1 node_scrape_collector_success{collector="cpu"} 1 +node_scrape_collector_success{collector="cpu_vulnerabilities"} 1 node_scrape_collector_success{collector="cpufreq"} 1 node_scrape_collector_success{collector="diskstats"} 1 node_scrape_collector_success{collector="dmi"} 1 node_scrape_collector_success{collector="drbd"} 1 node_scrape_collector_success{collector="edac"} 1 node_scrape_collector_success{collector="entropy"} 1 +node_scrape_collector_success{collector="fibrechannel"} 1 node_scrape_collector_success{collector="filefd"} 1 node_scrape_collector_success{collector="hwmon"} 1 node_scrape_collector_success{collector="infiniband"} 1 node_scrape_collector_success{collector="interrupts"} 1 node_scrape_collector_success{collector="ipvs"} 1 node_scrape_collector_success{collector="ksmd"} 1 +node_scrape_collector_success{collector="lnstat"} 1 node_scrape_collector_success{collector="loadavg"} 1 node_scrape_collector_success{collector="mdadm"} 1 node_scrape_collector_success{collector="meminfo"} 1 @@ -2607,24 +2933,78 @@ node_scrape_collector_success{collector="processes"} 1 node_scrape_collector_success{collector="qdisc"} 1 node_scrape_collector_success{collector="rapl"} 1 node_scrape_collector_success{collector="schedstat"} 1 +node_scrape_collector_success{collector="selinux"} 1 +node_scrape_collector_success{collector="slabinfo"} 1 node_scrape_collector_success{collector="sockstat"} 1 +node_scrape_collector_success{collector="softirqs"} 1 node_scrape_collector_success{collector="softnet"} 1 node_scrape_collector_success{collector="stat"} 1 +node_scrape_collector_success{collector="sysctl"} 1 +node_scrape_collector_success{collector="tapestats"} 1 node_scrape_collector_success{collector="textfile"} 1 node_scrape_collector_success{collector="thermal_zone"} 1 +node_scrape_collector_success{collector="time"} 1 +node_scrape_collector_success{collector="udp_queues"} 1 node_scrape_collector_success{collector="vmstat"} 1 node_scrape_collector_success{collector="wifi"} 1 +node_scrape_collector_success{collector="xfrm"} 1 node_scrape_collector_success{collector="xfs"} 1 node_scrape_collector_success{collector="zfs"} 1 +node_scrape_collector_success{collector="zoneinfo"} 1 +# HELP node_selinux_enabled SELinux is enabled, 1 is true, 0 is false +# TYPE node_selinux_enabled gauge +node_selinux_enabled 0 +# HELP node_slabinfo_active_objects The number of objects that are currently active (i.e., in use). +# TYPE node_slabinfo_active_objects gauge +node_slabinfo_active_objects{slab="dmaengine-unmap-128"} 1206 +node_slabinfo_active_objects{slab="kmalloc-8192"} 132 +node_slabinfo_active_objects{slab="kmem_cache"} 320 +node_slabinfo_active_objects{slab="tw_sock_TCP"} 704 +# HELP node_slabinfo_object_size_bytes The size of objects in this slab, in bytes. +# TYPE node_slabinfo_object_size_bytes gauge +node_slabinfo_object_size_bytes{slab="dmaengine-unmap-128"} 1088 +node_slabinfo_object_size_bytes{slab="kmalloc-8192"} 8192 +node_slabinfo_object_size_bytes{slab="kmem_cache"} 256 +node_slabinfo_object_size_bytes{slab="tw_sock_TCP"} 256 +# HELP node_slabinfo_objects The total number of allocated objects (i.e., objects that are both in use and not in use). +# TYPE node_slabinfo_objects gauge +node_slabinfo_objects{slab="dmaengine-unmap-128"} 1320 +node_slabinfo_objects{slab="kmalloc-8192"} 148 +node_slabinfo_objects{slab="kmem_cache"} 320 +node_slabinfo_objects{slab="tw_sock_TCP"} 864 +# HELP node_slabinfo_objects_per_slab The number of objects stored in each slab. +# TYPE node_slabinfo_objects_per_slab gauge +node_slabinfo_objects_per_slab{slab="dmaengine-unmap-128"} 30 +node_slabinfo_objects_per_slab{slab="kmalloc-8192"} 4 +node_slabinfo_objects_per_slab{slab="kmem_cache"} 32 +node_slabinfo_objects_per_slab{slab="tw_sock_TCP"} 32 +# HELP node_slabinfo_pages_per_slab The number of pages allocated for each slab. +# TYPE node_slabinfo_pages_per_slab gauge +node_slabinfo_pages_per_slab{slab="dmaengine-unmap-128"} 8 +node_slabinfo_pages_per_slab{slab="kmalloc-8192"} 8 +node_slabinfo_pages_per_slab{slab="kmem_cache"} 2 +node_slabinfo_pages_per_slab{slab="tw_sock_TCP"} 2 +# HELP node_sockstat_FRAG6_inuse Number of FRAG6 sockets in state inuse. +# TYPE node_sockstat_FRAG6_inuse gauge +node_sockstat_FRAG6_inuse 0 +# HELP node_sockstat_FRAG6_memory Number of FRAG6 sockets in state memory. +# TYPE node_sockstat_FRAG6_memory gauge +node_sockstat_FRAG6_memory 0 # HELP node_sockstat_FRAG_inuse Number of FRAG sockets in state inuse. # TYPE node_sockstat_FRAG_inuse gauge node_sockstat_FRAG_inuse 0 # HELP node_sockstat_FRAG_memory Number of FRAG sockets in state memory. # TYPE node_sockstat_FRAG_memory gauge node_sockstat_FRAG_memory 0 +# HELP node_sockstat_RAW6_inuse Number of RAW6 sockets in state inuse. +# TYPE node_sockstat_RAW6_inuse gauge +node_sockstat_RAW6_inuse 1 # HELP node_sockstat_RAW_inuse Number of RAW sockets in state inuse. # TYPE node_sockstat_RAW_inuse gauge node_sockstat_RAW_inuse 0 +# HELP node_sockstat_TCP6_inuse Number of TCP6 sockets in state inuse. +# TYPE node_sockstat_TCP6_inuse gauge +node_sockstat_TCP6_inuse 17 # HELP node_sockstat_TCP_alloc Number of TCP sockets in state alloc. # TYPE node_sockstat_TCP_alloc gauge node_sockstat_TCP_alloc 17 @@ -2636,13 +3016,19 @@ node_sockstat_TCP_inuse 4 node_sockstat_TCP_mem 1 # HELP node_sockstat_TCP_mem_bytes Number of TCP sockets in state mem_bytes. # TYPE node_sockstat_TCP_mem_bytes gauge -node_sockstat_TCP_mem_bytes 65536 +node_sockstat_TCP_mem_bytes 4096 # HELP node_sockstat_TCP_orphan Number of TCP sockets in state orphan. # TYPE node_sockstat_TCP_orphan gauge node_sockstat_TCP_orphan 0 # HELP node_sockstat_TCP_tw Number of TCP sockets in state tw. # TYPE node_sockstat_TCP_tw gauge node_sockstat_TCP_tw 4 +# HELP node_sockstat_UDP6_inuse Number of UDP6 sockets in state inuse. +# TYPE node_sockstat_UDP6_inuse gauge +node_sockstat_UDP6_inuse 9 +# HELP node_sockstat_UDPLITE6_inuse Number of UDPLITE6 sockets in state inuse. +# TYPE node_sockstat_UDPLITE6_inuse gauge +node_sockstat_UDPLITE6_inuse 0 # HELP node_sockstat_UDPLITE_inuse Number of UDPLITE sockets in state inuse. # TYPE node_sockstat_UDPLITE_inuse gauge node_sockstat_UDPLITE_inuse 0 @@ -2655,27 +3041,142 @@ node_sockstat_UDP_mem 0 # HELP node_sockstat_UDP_mem_bytes Number of UDP sockets in state mem_bytes. # TYPE node_sockstat_UDP_mem_bytes gauge node_sockstat_UDP_mem_bytes 0 -# HELP node_sockstat_sockets_used Number of sockets sockets in state used. +# HELP node_sockstat_sockets_used Number of IPv4 sockets in use. # TYPE node_sockstat_sockets_used gauge node_sockstat_sockets_used 229 +# HELP node_softirqs_functions_total Softirq counts per CPU. +# TYPE node_softirqs_functions_total counter +node_softirqs_functions_total{cpu="0",type="BLOCK"} 23776 +node_softirqs_functions_total{cpu="0",type="HI"} 7 +node_softirqs_functions_total{cpu="0",type="HRTIMER"} 40 +node_softirqs_functions_total{cpu="0",type="IRQ_POLL"} 0 +node_softirqs_functions_total{cpu="0",type="NET_RX"} 43066 +node_softirqs_functions_total{cpu="0",type="NET_TX"} 2301 +node_softirqs_functions_total{cpu="0",type="RCU"} 155929 +node_softirqs_functions_total{cpu="0",type="SCHED"} 378895 +node_softirqs_functions_total{cpu="0",type="TASKLET"} 372 +node_softirqs_functions_total{cpu="0",type="TIMER"} 424191 +node_softirqs_functions_total{cpu="1",type="BLOCK"} 24115 +node_softirqs_functions_total{cpu="1",type="HI"} 1 +node_softirqs_functions_total{cpu="1",type="HRTIMER"} 346 +node_softirqs_functions_total{cpu="1",type="IRQ_POLL"} 0 +node_softirqs_functions_total{cpu="1",type="NET_RX"} 104508 +node_softirqs_functions_total{cpu="1",type="NET_TX"} 2430 +node_softirqs_functions_total{cpu="1",type="RCU"} 146631 +node_softirqs_functions_total{cpu="1",type="SCHED"} 152852 +node_softirqs_functions_total{cpu="1",type="TASKLET"} 1899 +node_softirqs_functions_total{cpu="1",type="TIMER"} 108342 +# HELP node_softirqs_total Number of softirq calls. +# TYPE node_softirqs_total counter +node_softirqs_total{vector="block"} 186066 +node_softirqs_total{vector="block_iopoll"} 0 +node_softirqs_total{vector="hi"} 250191 +node_softirqs_total{vector="hrtimer"} 12499 +node_softirqs_total{vector="net_rx"} 211099 +node_softirqs_total{vector="net_tx"} 1647 +node_softirqs_total{vector="rcu"} 508444 +node_softirqs_total{vector="sched"} 622196 +node_softirqs_total{vector="tasklet"} 1.783454e+06 +node_softirqs_total{vector="timer"} 1.481983e+06 +# HELP node_softnet_backlog_len Softnet backlog status +# TYPE node_softnet_backlog_len gauge +node_softnet_backlog_len{cpu="0"} 0 +node_softnet_backlog_len{cpu="1"} 0 +node_softnet_backlog_len{cpu="2"} 0 +node_softnet_backlog_len{cpu="3"} 0 +# HELP node_softnet_cpu_collision_total Number of collision occur while obtaining device lock while transmitting +# TYPE node_softnet_cpu_collision_total counter +node_softnet_cpu_collision_total{cpu="0"} 0 +node_softnet_cpu_collision_total{cpu="1"} 0 +node_softnet_cpu_collision_total{cpu="2"} 0 +node_softnet_cpu_collision_total{cpu="3"} 0 # HELP node_softnet_dropped_total Number of dropped packets # TYPE node_softnet_dropped_total counter node_softnet_dropped_total{cpu="0"} 0 node_softnet_dropped_total{cpu="1"} 41 node_softnet_dropped_total{cpu="2"} 0 node_softnet_dropped_total{cpu="3"} 0 +# HELP node_softnet_flow_limit_count_total Number of times flow limit has been reached +# TYPE node_softnet_flow_limit_count_total counter +node_softnet_flow_limit_count_total{cpu="0"} 0 +node_softnet_flow_limit_count_total{cpu="1"} 0 +node_softnet_flow_limit_count_total{cpu="2"} 0 +node_softnet_flow_limit_count_total{cpu="3"} 0 # HELP node_softnet_processed_total Number of processed packets # TYPE node_softnet_processed_total counter node_softnet_processed_total{cpu="0"} 299641 node_softnet_processed_total{cpu="1"} 916354 node_softnet_processed_total{cpu="2"} 5.577791e+06 node_softnet_processed_total{cpu="3"} 3.113785e+06 +# HELP node_softnet_received_rps_total Number of times cpu woken up received_rps +# TYPE node_softnet_received_rps_total counter +node_softnet_received_rps_total{cpu="0"} 0 +node_softnet_received_rps_total{cpu="1"} 0 +node_softnet_received_rps_total{cpu="2"} 0 +node_softnet_received_rps_total{cpu="3"} 0 # HELP node_softnet_times_squeezed_total Number of times processing packets ran out of quota # TYPE node_softnet_times_squeezed_total counter node_softnet_times_squeezed_total{cpu="0"} 1 node_softnet_times_squeezed_total{cpu="1"} 10 node_softnet_times_squeezed_total{cpu="2"} 85 node_softnet_times_squeezed_total{cpu="3"} 50 +# HELP node_sysctl_fs_file_nr sysctl fs.file-nr +# TYPE node_sysctl_fs_file_nr untyped +node_sysctl_fs_file_nr{index="0"} 1024 +node_sysctl_fs_file_nr{index="1"} 0 +node_sysctl_fs_file_nr{index="2"} 1.631329e+06 +# HELP node_sysctl_fs_file_nr_current sysctl fs.file-nr, field 1 +# TYPE node_sysctl_fs_file_nr_current untyped +node_sysctl_fs_file_nr_current 0 +# HELP node_sysctl_fs_file_nr_max sysctl fs.file-nr, field 2 +# TYPE node_sysctl_fs_file_nr_max untyped +node_sysctl_fs_file_nr_max 1.631329e+06 +# HELP node_sysctl_fs_file_nr_total sysctl fs.file-nr, field 0 +# TYPE node_sysctl_fs_file_nr_total untyped +node_sysctl_fs_file_nr_total 1024 +# HELP node_sysctl_info sysctl info +# TYPE node_sysctl_info gauge +node_sysctl_info{index="0",name="kernel.seccomp.actions_avail",value="kill_process"} 1 +node_sysctl_info{index="1",name="kernel.seccomp.actions_avail",value="kill_thread"} 1 +node_sysctl_info{index="2",name="kernel.seccomp.actions_avail",value="trap"} 1 +node_sysctl_info{index="3",name="kernel.seccomp.actions_avail",value="errno"} 1 +node_sysctl_info{index="4",name="kernel.seccomp.actions_avail",value="user_notif"} 1 +node_sysctl_info{index="5",name="kernel.seccomp.actions_avail",value="trace"} 1 +node_sysctl_info{index="6",name="kernel.seccomp.actions_avail",value="log"} 1 +node_sysctl_info{index="7",name="kernel.seccomp.actions_avail",value="allow"} 1 +# HELP node_sysctl_kernel_threads_max sysctl kernel.threads-max +# TYPE node_sysctl_kernel_threads_max untyped +node_sysctl_kernel_threads_max 7801 +# HELP node_tape_io_now The number of I/Os currently outstanding to this device. +# TYPE node_tape_io_now gauge +node_tape_io_now{device="st0"} 1 +# HELP node_tape_io_others_total The number of I/Os issued to the tape drive other than read or write commands. The time taken to complete these commands uses the following calculation io_time_seconds_total-read_time_seconds_total-write_time_seconds_total +# TYPE node_tape_io_others_total counter +node_tape_io_others_total{device="st0"} 1409 +# HELP node_tape_io_time_seconds_total The amount of time spent waiting for all I/O to complete (including read and write). This includes tape movement commands such as seeking between file or set marks and implicit tape movement such as when rewind on close tape devices are used. +# TYPE node_tape_io_time_seconds_total counter +node_tape_io_time_seconds_total{device="st0"} 9247.01108772 +# HELP node_tape_read_bytes_total The number of bytes read from the tape drive. +# TYPE node_tape_read_bytes_total counter +node_tape_read_bytes_total{device="st0"} 9.79383912e+08 +# HELP node_tape_read_time_seconds_total The amount of time spent waiting for read requests to complete. +# TYPE node_tape_read_time_seconds_total counter +node_tape_read_time_seconds_total{device="st0"} 33.788355744 +# HELP node_tape_reads_completed_total The number of read requests issued to the tape drive. +# TYPE node_tape_reads_completed_total counter +node_tape_reads_completed_total{device="st0"} 3741 +# HELP node_tape_residual_total The number of times during a read or write we found the residual amount to be non-zero. This should mean that a program is issuing a read larger thean the block size on tape. For write not all data made it to tape. +# TYPE node_tape_residual_total counter +node_tape_residual_total{device="st0"} 19 +# HELP node_tape_write_time_seconds_total The amount of time spent waiting for write requests to complete. +# TYPE node_tape_write_time_seconds_total counter +node_tape_write_time_seconds_total{device="st0"} 5233.597394395 +# HELP node_tape_writes_completed_total The number of write requests issued to the tape drive. +# TYPE node_tape_writes_completed_total counter +node_tape_writes_completed_total{device="st0"} 5.3772916e+07 +# HELP node_tape_written_bytes_total The number of bytes written to the tape drive. +# TYPE node_tape_written_bytes_total counter +node_tape_written_bytes_total{device="st0"} 1.496246784e+12 # HELP node_textfile_mtime_seconds Unixtime mtime of textfiles successfully read. # TYPE node_textfile_mtime_seconds gauge # HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise @@ -2684,6 +3185,22 @@ node_textfile_scrape_error 0 # HELP node_thermal_zone_temp Zone temperature in Celsius # TYPE node_thermal_zone_temp gauge node_thermal_zone_temp{type="cpu-thermal",zone="0"} 12.376 +# HELP node_time_clocksource_available_info Available clocksources read from '/sys/devices/system/clocksource'. +# TYPE node_time_clocksource_available_info gauge +node_time_clocksource_available_info{clocksource="acpi_pm",device="0"} 1 +node_time_clocksource_available_info{clocksource="hpet",device="0"} 1 +node_time_clocksource_available_info{clocksource="tsc",device="0"} 1 +# HELP node_time_clocksource_current_info Current clocksource read from '/sys/devices/system/clocksource'. +# TYPE node_time_clocksource_current_info gauge +node_time_clocksource_current_info{clocksource="tsc",device="0"} 1 +# HELP node_time_seconds System time in seconds since epoch (1970). +# TYPE node_time_seconds gauge +# HELP node_time_zone_offset_seconds System time zone offset in seconds. +# TYPE node_time_zone_offset_seconds gauge +# HELP node_udp_queues Number of allocated memory in the kernel for UDP datagrams in bytes. +# TYPE node_udp_queues gauge +node_udp_queues{ip="v4",queue="rx"} 0 +node_udp_queues{ip="v4",queue="tx"} 21 # HELP node_vmstat_oom_kill /proc/vmstat information field oom_kill. # TYPE node_vmstat_oom_kill untyped node_vmstat_oom_kill 0 @@ -2752,6 +3269,90 @@ node_wifi_station_transmit_failed_total{device="wlan0",mac_address="aa:bb:cc:dd: # TYPE node_wifi_station_transmit_retries_total counter node_wifi_station_transmit_retries_total{device="wlan0",mac_address="01:02:03:04:05:06"} 20 node_wifi_station_transmit_retries_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 10 +# HELP node_xfrm_acquire_error_packets_total State hasn’t been fully acquired before use +# TYPE node_xfrm_acquire_error_packets_total counter +node_xfrm_acquire_error_packets_total 24532 +# HELP node_xfrm_fwd_hdr_error_packets_total Forward routing of a packet is not allowed +# TYPE node_xfrm_fwd_hdr_error_packets_total counter +node_xfrm_fwd_hdr_error_packets_total 6654 +# HELP node_xfrm_in_buffer_error_packets_total No buffer is left +# TYPE node_xfrm_in_buffer_error_packets_total counter +node_xfrm_in_buffer_error_packets_total 2 +# HELP node_xfrm_in_error_packets_total All errors not matched by other +# TYPE node_xfrm_in_error_packets_total counter +node_xfrm_in_error_packets_total 1 +# HELP node_xfrm_in_hdr_error_packets_total Header error +# TYPE node_xfrm_in_hdr_error_packets_total counter +node_xfrm_in_hdr_error_packets_total 4 +# HELP node_xfrm_in_no_pols_packets_total No policy is found for states e.g. Inbound SAs are correct but no SP is found +# TYPE node_xfrm_in_no_pols_packets_total counter +node_xfrm_in_no_pols_packets_total 65432 +# HELP node_xfrm_in_no_states_packets_total No state is found i.e. Either inbound SPI, address, or IPsec protocol at SA is wrong +# TYPE node_xfrm_in_no_states_packets_total counter +node_xfrm_in_no_states_packets_total 3 +# HELP node_xfrm_in_pol_block_packets_total Policy discards +# TYPE node_xfrm_in_pol_block_packets_total counter +node_xfrm_in_pol_block_packets_total 100 +# HELP node_xfrm_in_pol_error_packets_total Policy error +# TYPE node_xfrm_in_pol_error_packets_total counter +node_xfrm_in_pol_error_packets_total 10000 +# HELP node_xfrm_in_state_expired_packets_total State is expired +# TYPE node_xfrm_in_state_expired_packets_total counter +node_xfrm_in_state_expired_packets_total 7 +# HELP node_xfrm_in_state_invalid_packets_total State is invalid +# TYPE node_xfrm_in_state_invalid_packets_total counter +node_xfrm_in_state_invalid_packets_total 55555 +# HELP node_xfrm_in_state_mismatch_packets_total State has mismatch option e.g. UDP encapsulation type is mismatch +# TYPE node_xfrm_in_state_mismatch_packets_total counter +node_xfrm_in_state_mismatch_packets_total 23451 +# HELP node_xfrm_in_state_mode_error_packets_total Transformation mode specific error +# TYPE node_xfrm_in_state_mode_error_packets_total counter +node_xfrm_in_state_mode_error_packets_total 100 +# HELP node_xfrm_in_state_proto_error_packets_total Transformation protocol specific error e.g. SA key is wrong +# TYPE node_xfrm_in_state_proto_error_packets_total counter +node_xfrm_in_state_proto_error_packets_total 40 +# HELP node_xfrm_in_state_seq_error_packets_total Sequence error i.e. Sequence number is out of window +# TYPE node_xfrm_in_state_seq_error_packets_total counter +node_xfrm_in_state_seq_error_packets_total 6000 +# HELP node_xfrm_in_tmpl_mismatch_packets_total No matching template for states e.g. Inbound SAs are correct but SP rule is wrong +# TYPE node_xfrm_in_tmpl_mismatch_packets_total counter +node_xfrm_in_tmpl_mismatch_packets_total 51 +# HELP node_xfrm_out_bundle_check_error_packets_total Bundle check error +# TYPE node_xfrm_out_bundle_check_error_packets_total counter +node_xfrm_out_bundle_check_error_packets_total 555 +# HELP node_xfrm_out_bundle_gen_error_packets_total Bundle generation error +# TYPE node_xfrm_out_bundle_gen_error_packets_total counter +node_xfrm_out_bundle_gen_error_packets_total 43321 +# HELP node_xfrm_out_error_packets_total All errors which is not matched others +# TYPE node_xfrm_out_error_packets_total counter +node_xfrm_out_error_packets_total 1e+06 +# HELP node_xfrm_out_no_states_packets_total No state is found +# TYPE node_xfrm_out_no_states_packets_total counter +node_xfrm_out_no_states_packets_total 869 +# HELP node_xfrm_out_pol_block_packets_total Policy discards +# TYPE node_xfrm_out_pol_block_packets_total counter +node_xfrm_out_pol_block_packets_total 43456 +# HELP node_xfrm_out_pol_dead_packets_total Policy is dead +# TYPE node_xfrm_out_pol_dead_packets_total counter +node_xfrm_out_pol_dead_packets_total 7656 +# HELP node_xfrm_out_pol_error_packets_total Policy error +# TYPE node_xfrm_out_pol_error_packets_total counter +node_xfrm_out_pol_error_packets_total 1454 +# HELP node_xfrm_out_state_expired_packets_total State is expired +# TYPE node_xfrm_out_state_expired_packets_total counter +node_xfrm_out_state_expired_packets_total 565 +# HELP node_xfrm_out_state_invalid_packets_total State is invalid, perhaps expired +# TYPE node_xfrm_out_state_invalid_packets_total counter +node_xfrm_out_state_invalid_packets_total 28765 +# HELP node_xfrm_out_state_mode_error_packets_total Transformation mode specific error +# TYPE node_xfrm_out_state_mode_error_packets_total counter +node_xfrm_out_state_mode_error_packets_total 8 +# HELP node_xfrm_out_state_proto_error_packets_total Transformation protocol specific error +# TYPE node_xfrm_out_state_proto_error_packets_total counter +node_xfrm_out_state_proto_error_packets_total 4542 +# HELP node_xfrm_out_state_seq_error_packets_total Sequence error i.e. Sequence number overflow +# TYPE node_xfrm_out_state_seq_error_packets_total counter +node_xfrm_out_state_seq_error_packets_total 543 # HELP node_xfs_allocation_btree_compares_total Number of allocation B-tree compares for a filesystem. # TYPE node_xfs_allocation_btree_compares_total counter node_xfs_allocation_btree_compares_total{device="sda1"} 0 @@ -2843,9 +3444,8 @@ node_xfs_inode_operation_reclaims_total{device="sda1"} 0 # TYPE node_xfs_inode_operation_recycled_total counter node_xfs_inode_operation_recycled_total{device="sda1"} 0 # HELP node_xfs_read_calls_total Number of read(2) system calls made to files in a filesystem. -# HELP node_xfs_read_calls_total Number of read(2) system calls made to files in a filesystem. # TYPE node_xfs_read_calls_total counter -node_xfs_read_calls_total{device="sda1"} 28 +node_xfs_read_calls_total{device="sda1"} 0 # HELP node_xfs_vnode_active_total Number of vnodes not on free lists for a filesystem. # TYPE node_xfs_vnode_active_total counter node_xfs_vnode_active_total{device="sda1"} 4 @@ -2869,7 +3469,7 @@ node_xfs_vnode_release_total{device="sda1"} 1 node_xfs_vnode_remove_total{device="sda1"} 1 # HELP node_xfs_write_calls_total Number of write(2) system calls made to files in a filesystem. # TYPE node_xfs_write_calls_total counter -node_xfs_write_calls_total{device="sda1"} 0 +node_xfs_write_calls_total{device="sda1"} 28 # HELP node_zfs_abd_linear_cnt kstat.zfs.misc.abdstats.linear_cnt # TYPE node_zfs_abd_linear_cnt untyped node_zfs_abd_linear_cnt 62 @@ -3206,193 +3806,193 @@ node_zfs_arc_prefetch_metadata_misses 16071 # HELP node_zfs_arc_size kstat.zfs.misc.arcstats.size # TYPE node_zfs_arc_size untyped node_zfs_arc_size 1.603939792e+09 -# HELP node_zfs_dbuf_dbuf_cache_count kstat.zfs.misc.dbuf_stats.dbuf_cache_count +# HELP node_zfs_dbuf_dbuf_cache_count kstat.zfs.misc.dbufstats.dbuf_cache_count # TYPE node_zfs_dbuf_dbuf_cache_count untyped node_zfs_dbuf_dbuf_cache_count 27 -# HELP node_zfs_dbuf_dbuf_cache_hiwater_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_hiwater_bytes +# HELP node_zfs_dbuf_dbuf_cache_hiwater_bytes kstat.zfs.misc.dbufstats.dbuf_cache_hiwater_bytes # TYPE node_zfs_dbuf_dbuf_cache_hiwater_bytes untyped node_zfs_dbuf_dbuf_cache_hiwater_bytes 6.9117804e+07 -# HELP node_zfs_dbuf_dbuf_cache_level_0 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_0 +# HELP node_zfs_dbuf_dbuf_cache_level_0 kstat.zfs.misc.dbufstats.dbuf_cache_level_0 # TYPE node_zfs_dbuf_dbuf_cache_level_0 untyped node_zfs_dbuf_dbuf_cache_level_0 27 -# HELP node_zfs_dbuf_dbuf_cache_level_0_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_0_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_0_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_0_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_0_bytes untyped node_zfs_dbuf_dbuf_cache_level_0_bytes 302080 -# HELP node_zfs_dbuf_dbuf_cache_level_1 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_1 +# HELP node_zfs_dbuf_dbuf_cache_level_1 kstat.zfs.misc.dbufstats.dbuf_cache_level_1 # TYPE node_zfs_dbuf_dbuf_cache_level_1 untyped node_zfs_dbuf_dbuf_cache_level_1 0 -# HELP node_zfs_dbuf_dbuf_cache_level_10 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_10 +# HELP node_zfs_dbuf_dbuf_cache_level_10 kstat.zfs.misc.dbufstats.dbuf_cache_level_10 # TYPE node_zfs_dbuf_dbuf_cache_level_10 untyped node_zfs_dbuf_dbuf_cache_level_10 0 -# HELP node_zfs_dbuf_dbuf_cache_level_10_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_10_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_10_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_10_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_10_bytes untyped node_zfs_dbuf_dbuf_cache_level_10_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_11 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_11 +# HELP node_zfs_dbuf_dbuf_cache_level_11 kstat.zfs.misc.dbufstats.dbuf_cache_level_11 # TYPE node_zfs_dbuf_dbuf_cache_level_11 untyped node_zfs_dbuf_dbuf_cache_level_11 0 -# HELP node_zfs_dbuf_dbuf_cache_level_11_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_11_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_11_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_11_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_11_bytes untyped node_zfs_dbuf_dbuf_cache_level_11_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_1_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_1_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_1_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_1_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_1_bytes untyped node_zfs_dbuf_dbuf_cache_level_1_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_2 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_2 +# HELP node_zfs_dbuf_dbuf_cache_level_2 kstat.zfs.misc.dbufstats.dbuf_cache_level_2 # TYPE node_zfs_dbuf_dbuf_cache_level_2 untyped node_zfs_dbuf_dbuf_cache_level_2 0 -# HELP node_zfs_dbuf_dbuf_cache_level_2_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_2_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_2_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_2_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_2_bytes untyped node_zfs_dbuf_dbuf_cache_level_2_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_3 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_3 +# HELP node_zfs_dbuf_dbuf_cache_level_3 kstat.zfs.misc.dbufstats.dbuf_cache_level_3 # TYPE node_zfs_dbuf_dbuf_cache_level_3 untyped node_zfs_dbuf_dbuf_cache_level_3 0 -# HELP node_zfs_dbuf_dbuf_cache_level_3_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_3_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_3_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_3_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_3_bytes untyped node_zfs_dbuf_dbuf_cache_level_3_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_4 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_4 +# HELP node_zfs_dbuf_dbuf_cache_level_4 kstat.zfs.misc.dbufstats.dbuf_cache_level_4 # TYPE node_zfs_dbuf_dbuf_cache_level_4 untyped node_zfs_dbuf_dbuf_cache_level_4 0 -# HELP node_zfs_dbuf_dbuf_cache_level_4_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_4_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_4_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_4_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_4_bytes untyped node_zfs_dbuf_dbuf_cache_level_4_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_5 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_5 +# HELP node_zfs_dbuf_dbuf_cache_level_5 kstat.zfs.misc.dbufstats.dbuf_cache_level_5 # TYPE node_zfs_dbuf_dbuf_cache_level_5 untyped node_zfs_dbuf_dbuf_cache_level_5 0 -# HELP node_zfs_dbuf_dbuf_cache_level_5_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_5_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_5_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_5_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_5_bytes untyped node_zfs_dbuf_dbuf_cache_level_5_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_6 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_6 +# HELP node_zfs_dbuf_dbuf_cache_level_6 kstat.zfs.misc.dbufstats.dbuf_cache_level_6 # TYPE node_zfs_dbuf_dbuf_cache_level_6 untyped node_zfs_dbuf_dbuf_cache_level_6 0 -# HELP node_zfs_dbuf_dbuf_cache_level_6_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_6_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_6_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_6_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_6_bytes untyped node_zfs_dbuf_dbuf_cache_level_6_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_7 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_7 +# HELP node_zfs_dbuf_dbuf_cache_level_7 kstat.zfs.misc.dbufstats.dbuf_cache_level_7 # TYPE node_zfs_dbuf_dbuf_cache_level_7 untyped node_zfs_dbuf_dbuf_cache_level_7 0 -# HELP node_zfs_dbuf_dbuf_cache_level_7_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_7_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_7_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_7_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_7_bytes untyped node_zfs_dbuf_dbuf_cache_level_7_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_8 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_8 +# HELP node_zfs_dbuf_dbuf_cache_level_8 kstat.zfs.misc.dbufstats.dbuf_cache_level_8 # TYPE node_zfs_dbuf_dbuf_cache_level_8 untyped node_zfs_dbuf_dbuf_cache_level_8 0 -# HELP node_zfs_dbuf_dbuf_cache_level_8_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_8_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_8_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_8_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_8_bytes untyped node_zfs_dbuf_dbuf_cache_level_8_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_9 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_9 +# HELP node_zfs_dbuf_dbuf_cache_level_9 kstat.zfs.misc.dbufstats.dbuf_cache_level_9 # TYPE node_zfs_dbuf_dbuf_cache_level_9 untyped node_zfs_dbuf_dbuf_cache_level_9 0 -# HELP node_zfs_dbuf_dbuf_cache_level_9_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_9_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_9_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_9_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_9_bytes untyped node_zfs_dbuf_dbuf_cache_level_9_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_lowater_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_lowater_bytes +# HELP node_zfs_dbuf_dbuf_cache_lowater_bytes kstat.zfs.misc.dbufstats.dbuf_cache_lowater_bytes # TYPE node_zfs_dbuf_dbuf_cache_lowater_bytes untyped node_zfs_dbuf_dbuf_cache_lowater_bytes 5.6550932e+07 -# HELP node_zfs_dbuf_dbuf_cache_max_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_max_bytes +# HELP node_zfs_dbuf_dbuf_cache_max_bytes kstat.zfs.misc.dbufstats.dbuf_cache_max_bytes # TYPE node_zfs_dbuf_dbuf_cache_max_bytes untyped node_zfs_dbuf_dbuf_cache_max_bytes 6.2834368e+07 -# HELP node_zfs_dbuf_dbuf_cache_size kstat.zfs.misc.dbuf_stats.dbuf_cache_size +# HELP node_zfs_dbuf_dbuf_cache_size kstat.zfs.misc.dbufstats.dbuf_cache_size # TYPE node_zfs_dbuf_dbuf_cache_size untyped node_zfs_dbuf_dbuf_cache_size 302080 -# HELP node_zfs_dbuf_dbuf_cache_size_max kstat.zfs.misc.dbuf_stats.dbuf_cache_size_max +# HELP node_zfs_dbuf_dbuf_cache_size_max kstat.zfs.misc.dbufstats.dbuf_cache_size_max # TYPE node_zfs_dbuf_dbuf_cache_size_max untyped node_zfs_dbuf_dbuf_cache_size_max 394240 -# HELP node_zfs_dbuf_dbuf_cache_total_evicts kstat.zfs.misc.dbuf_stats.dbuf_cache_total_evicts +# HELP node_zfs_dbuf_dbuf_cache_total_evicts kstat.zfs.misc.dbufstats.dbuf_cache_total_evicts # TYPE node_zfs_dbuf_dbuf_cache_total_evicts untyped node_zfs_dbuf_dbuf_cache_total_evicts 0 -# HELP node_zfs_dbuf_hash_chain_max kstat.zfs.misc.dbuf_stats.hash_chain_max +# HELP node_zfs_dbuf_hash_chain_max kstat.zfs.misc.dbufstats.hash_chain_max # TYPE node_zfs_dbuf_hash_chain_max untyped node_zfs_dbuf_hash_chain_max 0 -# HELP node_zfs_dbuf_hash_chains kstat.zfs.misc.dbuf_stats.hash_chains +# HELP node_zfs_dbuf_hash_chains kstat.zfs.misc.dbufstats.hash_chains # TYPE node_zfs_dbuf_hash_chains untyped node_zfs_dbuf_hash_chains 0 -# HELP node_zfs_dbuf_hash_collisions kstat.zfs.misc.dbuf_stats.hash_collisions +# HELP node_zfs_dbuf_hash_collisions kstat.zfs.misc.dbufstats.hash_collisions # TYPE node_zfs_dbuf_hash_collisions untyped node_zfs_dbuf_hash_collisions 0 -# HELP node_zfs_dbuf_hash_dbuf_level_0 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_0 +# HELP node_zfs_dbuf_hash_dbuf_level_0 kstat.zfs.misc.dbufstats.hash_dbuf_level_0 # TYPE node_zfs_dbuf_hash_dbuf_level_0 untyped node_zfs_dbuf_hash_dbuf_level_0 37 -# HELP node_zfs_dbuf_hash_dbuf_level_0_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_0_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_0_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_0_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_0_bytes untyped node_zfs_dbuf_hash_dbuf_level_0_bytes 465920 -# HELP node_zfs_dbuf_hash_dbuf_level_1 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_1 +# HELP node_zfs_dbuf_hash_dbuf_level_1 kstat.zfs.misc.dbufstats.hash_dbuf_level_1 # TYPE node_zfs_dbuf_hash_dbuf_level_1 untyped node_zfs_dbuf_hash_dbuf_level_1 10 -# HELP node_zfs_dbuf_hash_dbuf_level_10 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_10 +# HELP node_zfs_dbuf_hash_dbuf_level_10 kstat.zfs.misc.dbufstats.hash_dbuf_level_10 # TYPE node_zfs_dbuf_hash_dbuf_level_10 untyped node_zfs_dbuf_hash_dbuf_level_10 0 -# HELP node_zfs_dbuf_hash_dbuf_level_10_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_10_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_10_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_10_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_10_bytes untyped node_zfs_dbuf_hash_dbuf_level_10_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_11 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_11 +# HELP node_zfs_dbuf_hash_dbuf_level_11 kstat.zfs.misc.dbufstats.hash_dbuf_level_11 # TYPE node_zfs_dbuf_hash_dbuf_level_11 untyped node_zfs_dbuf_hash_dbuf_level_11 0 -# HELP node_zfs_dbuf_hash_dbuf_level_11_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_11_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_11_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_11_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_11_bytes untyped node_zfs_dbuf_hash_dbuf_level_11_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_1_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_1_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_1_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_1_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_1_bytes untyped node_zfs_dbuf_hash_dbuf_level_1_bytes 1.31072e+06 -# HELP node_zfs_dbuf_hash_dbuf_level_2 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_2 +# HELP node_zfs_dbuf_hash_dbuf_level_2 kstat.zfs.misc.dbufstats.hash_dbuf_level_2 # TYPE node_zfs_dbuf_hash_dbuf_level_2 untyped node_zfs_dbuf_hash_dbuf_level_2 2 -# HELP node_zfs_dbuf_hash_dbuf_level_2_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_2_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_2_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_2_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_2_bytes untyped node_zfs_dbuf_hash_dbuf_level_2_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_3 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_3 +# HELP node_zfs_dbuf_hash_dbuf_level_3 kstat.zfs.misc.dbufstats.hash_dbuf_level_3 # TYPE node_zfs_dbuf_hash_dbuf_level_3 untyped node_zfs_dbuf_hash_dbuf_level_3 2 -# HELP node_zfs_dbuf_hash_dbuf_level_3_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_3_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_3_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_3_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_3_bytes untyped node_zfs_dbuf_hash_dbuf_level_3_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_4 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_4 +# HELP node_zfs_dbuf_hash_dbuf_level_4 kstat.zfs.misc.dbufstats.hash_dbuf_level_4 # TYPE node_zfs_dbuf_hash_dbuf_level_4 untyped node_zfs_dbuf_hash_dbuf_level_4 2 -# HELP node_zfs_dbuf_hash_dbuf_level_4_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_4_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_4_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_4_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_4_bytes untyped node_zfs_dbuf_hash_dbuf_level_4_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_5 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_5 +# HELP node_zfs_dbuf_hash_dbuf_level_5 kstat.zfs.misc.dbufstats.hash_dbuf_level_5 # TYPE node_zfs_dbuf_hash_dbuf_level_5 untyped node_zfs_dbuf_hash_dbuf_level_5 2 -# HELP node_zfs_dbuf_hash_dbuf_level_5_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_5_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_5_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_5_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_5_bytes untyped node_zfs_dbuf_hash_dbuf_level_5_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_6 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_6 +# HELP node_zfs_dbuf_hash_dbuf_level_6 kstat.zfs.misc.dbufstats.hash_dbuf_level_6 # TYPE node_zfs_dbuf_hash_dbuf_level_6 untyped node_zfs_dbuf_hash_dbuf_level_6 0 -# HELP node_zfs_dbuf_hash_dbuf_level_6_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_6_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_6_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_6_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_6_bytes untyped node_zfs_dbuf_hash_dbuf_level_6_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_7 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_7 +# HELP node_zfs_dbuf_hash_dbuf_level_7 kstat.zfs.misc.dbufstats.hash_dbuf_level_7 # TYPE node_zfs_dbuf_hash_dbuf_level_7 untyped node_zfs_dbuf_hash_dbuf_level_7 0 -# HELP node_zfs_dbuf_hash_dbuf_level_7_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_7_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_7_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_7_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_7_bytes untyped node_zfs_dbuf_hash_dbuf_level_7_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_8 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_8 +# HELP node_zfs_dbuf_hash_dbuf_level_8 kstat.zfs.misc.dbufstats.hash_dbuf_level_8 # TYPE node_zfs_dbuf_hash_dbuf_level_8 untyped node_zfs_dbuf_hash_dbuf_level_8 0 -# HELP node_zfs_dbuf_hash_dbuf_level_8_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_8_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_8_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_8_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_8_bytes untyped node_zfs_dbuf_hash_dbuf_level_8_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_9 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_9 +# HELP node_zfs_dbuf_hash_dbuf_level_9 kstat.zfs.misc.dbufstats.hash_dbuf_level_9 # TYPE node_zfs_dbuf_hash_dbuf_level_9 untyped node_zfs_dbuf_hash_dbuf_level_9 0 -# HELP node_zfs_dbuf_hash_dbuf_level_9_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_9_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_9_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_9_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_9_bytes untyped node_zfs_dbuf_hash_dbuf_level_9_bytes 0 -# HELP node_zfs_dbuf_hash_elements kstat.zfs.misc.dbuf_stats.hash_elements +# HELP node_zfs_dbuf_hash_elements kstat.zfs.misc.dbufstats.hash_elements # TYPE node_zfs_dbuf_hash_elements untyped node_zfs_dbuf_hash_elements 55 -# HELP node_zfs_dbuf_hash_elements_max kstat.zfs.misc.dbuf_stats.hash_elements_max +# HELP node_zfs_dbuf_hash_elements_max kstat.zfs.misc.dbufstats.hash_elements_max # TYPE node_zfs_dbuf_hash_elements_max untyped node_zfs_dbuf_hash_elements_max 55 -# HELP node_zfs_dbuf_hash_hits kstat.zfs.misc.dbuf_stats.hash_hits +# HELP node_zfs_dbuf_hash_hits kstat.zfs.misc.dbufstats.hash_hits # TYPE node_zfs_dbuf_hash_hits untyped node_zfs_dbuf_hash_hits 108807 -# HELP node_zfs_dbuf_hash_insert_race kstat.zfs.misc.dbuf_stats.hash_insert_race +# HELP node_zfs_dbuf_hash_insert_race kstat.zfs.misc.dbufstats.hash_insert_race # TYPE node_zfs_dbuf_hash_insert_race untyped node_zfs_dbuf_hash_insert_race 0 -# HELP node_zfs_dbuf_hash_misses kstat.zfs.misc.dbuf_stats.hash_misses +# HELP node_zfs_dbuf_hash_misses kstat.zfs.misc.dbufstats.hash_misses # TYPE node_zfs_dbuf_hash_misses untyped node_zfs_dbuf_hash_misses 1851 # HELP node_zfs_dmu_tx_dmu_tx_assigned kstat.zfs.misc.dmu_tx.dmu_tx_assigned @@ -3708,6 +4308,29 @@ node_zfs_zpool_rtime{zpool="poolz1"} 9.82909164e+09 # TYPE node_zfs_zpool_rupdate untyped node_zfs_zpool_rupdate{zpool="pool1"} 7.921048984922e+13 node_zfs_zpool_rupdate{zpool="poolz1"} 1.10734831944501e+14 +# HELP node_zfs_zpool_state kstat.zfs.misc.state +# TYPE node_zfs_zpool_state gauge +node_zfs_zpool_state{state="degraded",zpool="pool1"} 0 +node_zfs_zpool_state{state="degraded",zpool="pool2"} 0 +node_zfs_zpool_state{state="degraded",zpool="poolz1"} 1 +node_zfs_zpool_state{state="faulted",zpool="pool1"} 0 +node_zfs_zpool_state{state="faulted",zpool="pool2"} 0 +node_zfs_zpool_state{state="faulted",zpool="poolz1"} 0 +node_zfs_zpool_state{state="offline",zpool="pool1"} 0 +node_zfs_zpool_state{state="offline",zpool="pool2"} 0 +node_zfs_zpool_state{state="offline",zpool="poolz1"} 0 +node_zfs_zpool_state{state="online",zpool="pool1"} 1 +node_zfs_zpool_state{state="online",zpool="pool2"} 0 +node_zfs_zpool_state{state="online",zpool="poolz1"} 0 +node_zfs_zpool_state{state="removed",zpool="pool1"} 0 +node_zfs_zpool_state{state="removed",zpool="pool2"} 0 +node_zfs_zpool_state{state="removed",zpool="poolz1"} 0 +node_zfs_zpool_state{state="suspended",zpool="pool1"} 0 +node_zfs_zpool_state{state="suspended",zpool="pool2"} 1 +node_zfs_zpool_state{state="suspended",zpool="poolz1"} 0 +node_zfs_zpool_state{state="unavail",zpool="pool1"} 0 +node_zfs_zpool_state{state="unavail",zpool="pool2"} 0 +node_zfs_zpool_state{state="unavail",zpool="poolz1"} 0 # HELP node_zfs_zpool_wcnt kstat.zfs.misc.io.wcnt # TYPE node_zfs_zpool_wcnt untyped node_zfs_zpool_wcnt{zpool="pool1"} 0 @@ -3728,6 +4351,177 @@ node_zfs_zpool_wtime{zpool="poolz1"} 9.673715628e+09 # TYPE node_zfs_zpool_wupdate untyped node_zfs_zpool_wupdate{zpool="pool1"} 7.9210489694949e+13 node_zfs_zpool_wupdate{zpool="poolz1"} 1.10734831833266e+14 +# HELP node_zoneinfo_high_pages Zone watermark pages_high +# TYPE node_zoneinfo_high_pages gauge +node_zoneinfo_high_pages{node="0",zone="DMA"} 14 +node_zoneinfo_high_pages{node="0",zone="DMA32"} 2122 +node_zoneinfo_high_pages{node="0",zone="Device"} 0 +node_zoneinfo_high_pages{node="0",zone="Movable"} 0 +node_zoneinfo_high_pages{node="0",zone="Normal"} 31113 +# HELP node_zoneinfo_low_pages Zone watermark pages_low +# TYPE node_zoneinfo_low_pages gauge +node_zoneinfo_low_pages{node="0",zone="DMA"} 11 +node_zoneinfo_low_pages{node="0",zone="DMA32"} 1600 +node_zoneinfo_low_pages{node="0",zone="Device"} 0 +node_zoneinfo_low_pages{node="0",zone="Movable"} 0 +node_zoneinfo_low_pages{node="0",zone="Normal"} 23461 +# HELP node_zoneinfo_managed_pages Present pages managed by the buddy system +# TYPE node_zoneinfo_managed_pages gauge +node_zoneinfo_managed_pages{node="0",zone="DMA"} 3973 +node_zoneinfo_managed_pages{node="0",zone="DMA32"} 530339 +node_zoneinfo_managed_pages{node="0",zone="Device"} 0 +node_zoneinfo_managed_pages{node="0",zone="Movable"} 0 +node_zoneinfo_managed_pages{node="0",zone="Normal"} 7.654794e+06 +# HELP node_zoneinfo_min_pages Zone watermark pages_min +# TYPE node_zoneinfo_min_pages gauge +node_zoneinfo_min_pages{node="0",zone="DMA"} 8 +node_zoneinfo_min_pages{node="0",zone="DMA32"} 1078 +node_zoneinfo_min_pages{node="0",zone="Device"} 0 +node_zoneinfo_min_pages{node="0",zone="Movable"} 0 +node_zoneinfo_min_pages{node="0",zone="Normal"} 15809 +# HELP node_zoneinfo_nr_active_anon_pages Number of anonymous pages recently more used +# TYPE node_zoneinfo_nr_active_anon_pages gauge +node_zoneinfo_nr_active_anon_pages{node="0",zone="DMA"} 1.175853e+06 +# HELP node_zoneinfo_nr_active_file_pages Number of active pages with file-backing +# TYPE node_zoneinfo_nr_active_file_pages gauge +node_zoneinfo_nr_active_file_pages{node="0",zone="DMA"} 688810 +# HELP node_zoneinfo_nr_anon_pages Number of anonymous pages currently used by the system +# TYPE node_zoneinfo_nr_anon_pages gauge +node_zoneinfo_nr_anon_pages{node="0",zone="DMA"} 1.156608e+06 +# HELP node_zoneinfo_nr_anon_transparent_hugepages Number of anonymous transparent huge pages currently used by the system +# TYPE node_zoneinfo_nr_anon_transparent_hugepages gauge +node_zoneinfo_nr_anon_transparent_hugepages{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_dirtied_total Page dirtyings since bootup +# TYPE node_zoneinfo_nr_dirtied_total counter +node_zoneinfo_nr_dirtied_total{node="0",zone="DMA"} 1.189097e+06 +# HELP node_zoneinfo_nr_dirty_pages Number of dirty pages +# TYPE node_zoneinfo_nr_dirty_pages gauge +node_zoneinfo_nr_dirty_pages{node="0",zone="DMA"} 103 +# HELP node_zoneinfo_nr_file_pages Number of file pages +# TYPE node_zoneinfo_nr_file_pages gauge +node_zoneinfo_nr_file_pages{node="0",zone="DMA"} 1.740118e+06 +# HELP node_zoneinfo_nr_free_pages Total number of free pages in the zone +# TYPE node_zoneinfo_nr_free_pages gauge +node_zoneinfo_nr_free_pages{node="0",zone="DMA"} 2949 +node_zoneinfo_nr_free_pages{node="0",zone="DMA32"} 528427 +node_zoneinfo_nr_free_pages{node="0",zone="Normal"} 4.539739e+06 +# HELP node_zoneinfo_nr_inactive_anon_pages Number of anonymous pages recently less used +# TYPE node_zoneinfo_nr_inactive_anon_pages gauge +node_zoneinfo_nr_inactive_anon_pages{node="0",zone="DMA"} 95612 +# HELP node_zoneinfo_nr_inactive_file_pages Number of inactive pages with file-backing +# TYPE node_zoneinfo_nr_inactive_file_pages gauge +node_zoneinfo_nr_inactive_file_pages{node="0",zone="DMA"} 723339 +# HELP node_zoneinfo_nr_isolated_anon_pages Temporary isolated pages from anon lru +# TYPE node_zoneinfo_nr_isolated_anon_pages gauge +node_zoneinfo_nr_isolated_anon_pages{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_isolated_file_pages Temporary isolated pages from file lru +# TYPE node_zoneinfo_nr_isolated_file_pages gauge +node_zoneinfo_nr_isolated_file_pages{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_kernel_stacks Number of kernel stacks +# TYPE node_zoneinfo_nr_kernel_stacks gauge +node_zoneinfo_nr_kernel_stacks{node="0",zone="DMA"} 0 +node_zoneinfo_nr_kernel_stacks{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_kernel_stacks{node="0",zone="Normal"} 18864 +# HELP node_zoneinfo_nr_mapped_pages Number of mapped pages +# TYPE node_zoneinfo_nr_mapped_pages gauge +node_zoneinfo_nr_mapped_pages{node="0",zone="DMA"} 423143 +# HELP node_zoneinfo_nr_shmem_pages Number of shmem pages (included tmpfs/GEM pages) +# TYPE node_zoneinfo_nr_shmem_pages gauge +node_zoneinfo_nr_shmem_pages{node="0",zone="DMA"} 330517 +# HELP node_zoneinfo_nr_slab_reclaimable_pages Number of reclaimable slab pages +# TYPE node_zoneinfo_nr_slab_reclaimable_pages gauge +node_zoneinfo_nr_slab_reclaimable_pages{node="0",zone="DMA"} 121763 +# HELP node_zoneinfo_nr_slab_unreclaimable_pages Number of unreclaimable slab pages +# TYPE node_zoneinfo_nr_slab_unreclaimable_pages gauge +node_zoneinfo_nr_slab_unreclaimable_pages{node="0",zone="DMA"} 56182 +# HELP node_zoneinfo_nr_unevictable_pages Number of unevictable pages +# TYPE node_zoneinfo_nr_unevictable_pages gauge +node_zoneinfo_nr_unevictable_pages{node="0",zone="DMA"} 213111 +# HELP node_zoneinfo_nr_writeback_pages Number of writeback pages +# TYPE node_zoneinfo_nr_writeback_pages gauge +node_zoneinfo_nr_writeback_pages{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_written_total Page writings since bootup +# TYPE node_zoneinfo_nr_written_total counter +node_zoneinfo_nr_written_total{node="0",zone="DMA"} 1.181554e+06 +# HELP node_zoneinfo_numa_foreign_total Was intended here, hit elsewhere +# TYPE node_zoneinfo_numa_foreign_total counter +node_zoneinfo_numa_foreign_total{node="0",zone="DMA"} 0 +node_zoneinfo_numa_foreign_total{node="0",zone="DMA32"} 0 +node_zoneinfo_numa_foreign_total{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_numa_hit_total Allocated in intended node +# TYPE node_zoneinfo_numa_hit_total counter +node_zoneinfo_numa_hit_total{node="0",zone="DMA"} 1 +node_zoneinfo_numa_hit_total{node="0",zone="DMA32"} 13 +node_zoneinfo_numa_hit_total{node="0",zone="Normal"} 6.2836441e+07 +# HELP node_zoneinfo_numa_interleave_total Interleaver preferred this zone +# TYPE node_zoneinfo_numa_interleave_total counter +node_zoneinfo_numa_interleave_total{node="0",zone="DMA"} 1 +node_zoneinfo_numa_interleave_total{node="0",zone="DMA32"} 1 +node_zoneinfo_numa_interleave_total{node="0",zone="Normal"} 23174 +# HELP node_zoneinfo_numa_local_total Allocation from local node +# TYPE node_zoneinfo_numa_local_total counter +node_zoneinfo_numa_local_total{node="0",zone="DMA"} 1 +node_zoneinfo_numa_local_total{node="0",zone="DMA32"} 13 +node_zoneinfo_numa_local_total{node="0",zone="Normal"} 6.2836441e+07 +# HELP node_zoneinfo_numa_miss_total Allocated in non intended node +# TYPE node_zoneinfo_numa_miss_total counter +node_zoneinfo_numa_miss_total{node="0",zone="DMA"} 0 +node_zoneinfo_numa_miss_total{node="0",zone="DMA32"} 0 +node_zoneinfo_numa_miss_total{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_numa_other_total Allocation from other node +# TYPE node_zoneinfo_numa_other_total counter +node_zoneinfo_numa_other_total{node="0",zone="DMA"} 0 +node_zoneinfo_numa_other_total{node="0",zone="DMA32"} 0 +node_zoneinfo_numa_other_total{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_present_pages Physical pages existing within the zone +# TYPE node_zoneinfo_present_pages gauge +node_zoneinfo_present_pages{node="0",zone="DMA"} 3997 +node_zoneinfo_present_pages{node="0",zone="DMA32"} 546847 +node_zoneinfo_present_pages{node="0",zone="Device"} 0 +node_zoneinfo_present_pages{node="0",zone="Movable"} 0 +node_zoneinfo_present_pages{node="0",zone="Normal"} 7.806976e+06 +# HELP node_zoneinfo_protection_0 Protection array 0. field +# TYPE node_zoneinfo_protection_0 gauge +node_zoneinfo_protection_0{node="0",zone="DMA"} 0 +node_zoneinfo_protection_0{node="0",zone="DMA32"} 0 +node_zoneinfo_protection_0{node="0",zone="Device"} 0 +node_zoneinfo_protection_0{node="0",zone="Movable"} 0 +node_zoneinfo_protection_0{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_protection_1 Protection array 1. field +# TYPE node_zoneinfo_protection_1 gauge +node_zoneinfo_protection_1{node="0",zone="DMA"} 2039 +node_zoneinfo_protection_1{node="0",zone="DMA32"} 0 +node_zoneinfo_protection_1{node="0",zone="Device"} 0 +node_zoneinfo_protection_1{node="0",zone="Movable"} 0 +node_zoneinfo_protection_1{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_protection_2 Protection array 2. field +# TYPE node_zoneinfo_protection_2 gauge +node_zoneinfo_protection_2{node="0",zone="DMA"} 31932 +node_zoneinfo_protection_2{node="0",zone="DMA32"} 29893 +node_zoneinfo_protection_2{node="0",zone="Device"} 0 +node_zoneinfo_protection_2{node="0",zone="Movable"} 0 +node_zoneinfo_protection_2{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_protection_3 Protection array 3. field +# TYPE node_zoneinfo_protection_3 gauge +node_zoneinfo_protection_3{node="0",zone="DMA"} 31932 +node_zoneinfo_protection_3{node="0",zone="DMA32"} 29893 +node_zoneinfo_protection_3{node="0",zone="Device"} 0 +node_zoneinfo_protection_3{node="0",zone="Movable"} 0 +node_zoneinfo_protection_3{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_protection_4 Protection array 4. field +# TYPE node_zoneinfo_protection_4 gauge +node_zoneinfo_protection_4{node="0",zone="DMA"} 31932 +node_zoneinfo_protection_4{node="0",zone="DMA32"} 29893 +node_zoneinfo_protection_4{node="0",zone="Device"} 0 +node_zoneinfo_protection_4{node="0",zone="Movable"} 0 +node_zoneinfo_protection_4{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_spanned_pages Total pages spanned by the zone, including holes +# TYPE node_zoneinfo_spanned_pages gauge +node_zoneinfo_spanned_pages{node="0",zone="DMA"} 4095 +node_zoneinfo_spanned_pages{node="0",zone="DMA32"} 1.04448e+06 +node_zoneinfo_spanned_pages{node="0",zone="Device"} 0 +node_zoneinfo_spanned_pages{node="0",zone="Movable"} 0 +node_zoneinfo_spanned_pages{node="0",zone="Normal"} 7.806976e+06 # HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. # TYPE process_cpu_seconds_total counter # HELP process_max_fds Maximum number of open file descriptors. diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index 3219c84fa4..8920e56203 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -12,8 +12,6 @@ # TYPE go_memstats_buck_hash_sys_bytes gauge # HELP go_memstats_frees_total Total number of frees. # TYPE go_memstats_frees_total counter -# HELP go_memstats_gc_cpu_fraction The fraction of this program's available CPU time used by the GC since the program started. -# TYPE go_memstats_gc_cpu_fraction gauge # HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata. # TYPE go_memstats_gc_sys_bytes gauge # HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use. @@ -99,7 +97,7 @@ node_bcache_cache_misses_total{backing_device="bdev0",uuid="deaddd54-c735-46d5-8 node_bcache_cache_read_races_total{uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 # HELP node_bcache_cache_readaheads_total Count of times readahead occurred. # TYPE node_bcache_cache_readaheads_total counter -node_bcache_cache_readaheads_total{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 +node_bcache_cache_readaheads_total{backing_device="bdev0",uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 13 # HELP node_bcache_congested Congestion. # TYPE node_bcache_congested gauge node_bcache_congested{uuid="deaddd54-c735-46d5-868e-f331c5fd7c74"} 0 @@ -238,6 +236,34 @@ node_buddyinfo_blocks{node="0",size="8",zone="Normal"} 0 node_buddyinfo_blocks{node="0",size="9",zone="DMA"} 1 node_buddyinfo_blocks{node="0",size="9",zone="DMA32"} 0 node_buddyinfo_blocks{node="0",size="9",zone="Normal"} 0 +# HELP node_cgroups_cgroups Current cgroup number of the subsystem. +# TYPE node_cgroups_cgroups gauge +node_cgroups_cgroups{subsys_name="blkio"} 170 +node_cgroups_cgroups{subsys_name="cpu"} 172 +node_cgroups_cgroups{subsys_name="cpuacct"} 172 +node_cgroups_cgroups{subsys_name="cpuset"} 47 +node_cgroups_cgroups{subsys_name="devices"} 170 +node_cgroups_cgroups{subsys_name="freezer"} 47 +node_cgroups_cgroups{subsys_name="hugetlb"} 47 +node_cgroups_cgroups{subsys_name="memory"} 234 +node_cgroups_cgroups{subsys_name="net_cls"} 47 +node_cgroups_cgroups{subsys_name="perf_event"} 47 +node_cgroups_cgroups{subsys_name="pids"} 170 +node_cgroups_cgroups{subsys_name="rdma"} 1 +# HELP node_cgroups_enabled Current cgroup number of the subsystem. +# TYPE node_cgroups_enabled gauge +node_cgroups_enabled{subsys_name="blkio"} 1 +node_cgroups_enabled{subsys_name="cpu"} 1 +node_cgroups_enabled{subsys_name="cpuacct"} 1 +node_cgroups_enabled{subsys_name="cpuset"} 1 +node_cgroups_enabled{subsys_name="devices"} 1 +node_cgroups_enabled{subsys_name="freezer"} 1 +node_cgroups_enabled{subsys_name="hugetlb"} 1 +node_cgroups_enabled{subsys_name="memory"} 1 +node_cgroups_enabled{subsys_name="net_cls"} 1 +node_cgroups_enabled{subsys_name="perf_event"} 1 +node_cgroups_enabled{subsys_name="pids"} 1 +node_cgroups_enabled{subsys_name="rdma"} 1 # HELP node_context_switches_total Total number of context switches. # TYPE node_context_switches_total counter node_context_switches_total 3.8014093e+07 @@ -293,6 +319,13 @@ node_cpu_info{cachesize="8192 KB",core="2",cpu="2",family="6",microcode="0xb4",m node_cpu_info{cachesize="8192 KB",core="2",cpu="6",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 node_cpu_info{cachesize="8192 KB",core="3",cpu="3",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 node_cpu_info{cachesize="8192 KB",core="3",cpu="7",family="6",microcode="0xb4",model="142",model_name="Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz",package="0",stepping="10",vendor="GenuineIntel"} 1 +# HELP node_cpu_isolated Whether each core is isolated, information from /sys/devices/system/cpu/isolated. +# TYPE node_cpu_isolated gauge +node_cpu_isolated{cpu="1"} 1 +node_cpu_isolated{cpu="3"} 1 +node_cpu_isolated{cpu="4"} 1 +node_cpu_isolated{cpu="5"} 1 +node_cpu_isolated{cpu="9"} 1 # HELP node_cpu_package_throttles_total Number of times this CPU package has been throttled. # TYPE node_cpu_package_throttles_total counter node_cpu_package_throttles_total{package="0"} 30 @@ -315,6 +348,16 @@ node_cpu_scaling_frequency_min_hertz{cpu="0"} 8e+08 node_cpu_scaling_frequency_min_hertz{cpu="1"} 8e+08 node_cpu_scaling_frequency_min_hertz{cpu="2"} 1e+06 node_cpu_scaling_frequency_min_hertz{cpu="3"} 1e+06 +# HELP node_cpu_scaling_governor Current enabled CPU frequency governor. +# TYPE node_cpu_scaling_governor gauge +node_cpu_scaling_governor{cpu="0",governor="performance"} 0 +node_cpu_scaling_governor{cpu="0",governor="powersave"} 1 +node_cpu_scaling_governor{cpu="1",governor="performance"} 0 +node_cpu_scaling_governor{cpu="1",governor="powersave"} 1 +node_cpu_scaling_governor{cpu="2",governor="performance"} 0 +node_cpu_scaling_governor{cpu="2",governor="powersave"} 1 +node_cpu_scaling_governor{cpu="3",governor="performance"} 0 +node_cpu_scaling_governor{cpu="3",governor="powersave"} 1 # HELP node_cpu_seconds_total Seconds the CPUs spent in each mode. # TYPE node_cpu_seconds_total counter node_cpu_seconds_total{cpu="0",mode="idle"} 10870.69 @@ -381,6 +424,36 @@ node_cpu_seconds_total{cpu="7",mode="softirq"} 0.31 node_cpu_seconds_total{cpu="7",mode="steal"} 0 node_cpu_seconds_total{cpu="7",mode="system"} 101.64 node_cpu_seconds_total{cpu="7",mode="user"} 290.98 +# HELP node_cpu_vulnerabilities_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 +# TYPE node_cpu_vulnerabilities_info gauge +node_cpu_vulnerabilities_info{codename="itlb_multihit",mitigation="",state="not affected"} 1 +node_cpu_vulnerabilities_info{codename="mds",mitigation="",state="vulnerable"} 1 +node_cpu_vulnerabilities_info{codename="retbleed",mitigation="untrained return thunk; SMT enabled with STIBP protection",state="mitigation"} 1 +node_cpu_vulnerabilities_info{codename="spectre_v1",mitigation="usercopy/swapgs barriers and __user pointer sanitization",state="mitigation"} 1 +node_cpu_vulnerabilities_info{codename="spectre_v2",mitigation="Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected",state="mitigation"} 1 +# HELP node_disk_ata_rotation_rate_rpm ATA disk rotation rate in RPMs (0 for SSDs). +# TYPE node_disk_ata_rotation_rate_rpm gauge +node_disk_ata_rotation_rate_rpm{device="sda"} 7200 +node_disk_ata_rotation_rate_rpm{device="sdb"} 0 +node_disk_ata_rotation_rate_rpm{device="sdc"} 0 +# HELP node_disk_ata_write_cache ATA disk has a write cache. +# TYPE node_disk_ata_write_cache gauge +node_disk_ata_write_cache{device="sda"} 1 +node_disk_ata_write_cache{device="sdb"} 1 +node_disk_ata_write_cache{device="sdc"} 1 +# HELP node_disk_ata_write_cache_enabled ATA disk has its write cache enabled. +# TYPE node_disk_ata_write_cache_enabled gauge +node_disk_ata_write_cache_enabled{device="sda"} 0 +node_disk_ata_write_cache_enabled{device="sdb"} 1 +node_disk_ata_write_cache_enabled{device="sdc"} 0 +# HELP node_disk_device_mapper_info Info about disk device mapper. +# TYPE node_disk_device_mapper_info gauge +node_disk_device_mapper_info{device="dm-0",lv_layer="",lv_name="",name="nvme0n1_crypt",uuid="CRYPT-LUKS2-jolaulot80fy9zsiobkxyxo7y2dqeho2-nvme0n1_crypt",vg_name=""} 1 +node_disk_device_mapper_info{device="dm-1",lv_layer="",lv_name="swap_1",name="system-swap_1",uuid="LVM-wbGqQEBL9SxrW2DLntJwgg8fAv946hw3Tvjqh0v31fWgxEtD4BoHO0lROWFUY65T",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-2",lv_layer="",lv_name="root",name="system-root",uuid="LVM-NWEDo8q5ABDyJuC3F8veKNyWfYmeIBfFMS4MF3HakzUhkk7ekDm6fJTHkl2fYHe7",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-3",lv_layer="",lv_name="var",name="system-var",uuid="LVM-hrxHo0rlZ6U95ku5841Lpd17bS1Z7V7lrtEE60DVgE6YEOCdS9gcDGyonWim4hGP",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-4",lv_layer="",lv_name="tmp",name="system-tmp",uuid="LVM-XTNGOHjPWLHcxmJmVu5cWTXEtuzqDeBkdEHAZW5q9LxWQ2d4mb5CchUQzUPJpl8H",vg_name="system"} 1 +node_disk_device_mapper_info{device="dm-5",lv_layer="",lv_name="home",name="system-home",uuid="LVM-MtoJaWTpjWRXlUnNFlpxZauTEuYlMvGFutigEzCCrfj8CNh6jCRi5LQJXZCpLjPf",vg_name="system"} 1 # HELP node_disk_discard_time_seconds_total This is the total number of seconds spent by all discards. # TYPE node_disk_discard_time_seconds_total counter node_disk_discard_time_seconds_total{device="sdb"} 11.13 @@ -397,6 +470,18 @@ node_disk_discards_completed_total{device="sdc"} 18851 # TYPE node_disk_discards_merged_total counter node_disk_discards_merged_total{device="sdb"} 0 node_disk_discards_merged_total{device="sdc"} 0 +# HELP node_disk_filesystem_info Info about disk filesystem. +# TYPE node_disk_filesystem_info gauge +node_disk_filesystem_info{device="dm-0",type="LVM2_member",usage="raid",uuid="c3C3uW-gD96-Yw69-c1CJ-5MwT-6ysM-mST0vB",version="LVM2 001"} 1 +node_disk_filesystem_info{device="dm-1",type="swap",usage="other",uuid="5272bb60-04b5-49cd-b730-be57c7604450",version="1"} 1 +node_disk_filesystem_info{device="dm-2",type="ext4",usage="filesystem",uuid="3deafd0d-faff-4695-8d15-51061ae1f51b",version="1.0"} 1 +node_disk_filesystem_info{device="dm-3",type="ext4",usage="filesystem",uuid="5c772222-f7d4-4c8e-87e8-e97df6b7a45e",version="1.0"} 1 +node_disk_filesystem_info{device="dm-4",type="ext4",usage="filesystem",uuid="a9479d44-60e1-4015-a1e5-bb065e6dd11b",version="1.0"} 1 +node_disk_filesystem_info{device="dm-5",type="ext4",usage="filesystem",uuid="b05b726a-c718-4c4d-8641-7c73a7696d83",version="1.0"} 1 +node_disk_filesystem_info{device="mmcblk0p1",type="vfat",usage="filesystem",uuid="6284-658D",version="FAT32"} 1 +node_disk_filesystem_info{device="mmcblk0p2",type="ext4",usage="filesystem",uuid="83324ce8-a6f3-4e35-ad64-dbb3d6b87a32",version="1.0"} 1 +node_disk_filesystem_info{device="sda",type="LVM2_member",usage="raid",uuid="cVVv6j-HSA2-IY33-1Jmj-dO2H-YL7w-b4Oxqw",version="LVM2 001"} 1 +node_disk_filesystem_info{device="sdc",type="LVM2_member",usage="raid",uuid="QFy9W7-Brj3-hQ6v-AF8i-3Zqg-n3Vs-kGY4vb",version="LVM2 001"} 1 # HELP node_disk_flush_requests_time_seconds_total This is the total number of seconds spent by all flush requests. # TYPE node_disk_flush_requests_time_seconds_total counter node_disk_flush_requests_time_seconds_total{device="sdc"} 1.944 @@ -405,21 +490,21 @@ node_disk_flush_requests_time_seconds_total{device="sdc"} 1.944 node_disk_flush_requests_total{device="sdc"} 1555 # HELP node_disk_info Info of /sys/block/. # TYPE node_disk_info gauge -node_disk_info{device="dm-0",major="252",minor="0"} 1 -node_disk_info{device="dm-1",major="252",minor="1"} 1 -node_disk_info{device="dm-2",major="252",minor="2"} 1 -node_disk_info{device="dm-3",major="252",minor="3"} 1 -node_disk_info{device="dm-4",major="252",minor="4"} 1 -node_disk_info{device="dm-5",major="252",minor="5"} 1 -node_disk_info{device="mmcblk0",major="179",minor="0"} 1 -node_disk_info{device="mmcblk0p1",major="179",minor="1"} 1 -node_disk_info{device="mmcblk0p2",major="179",minor="2"} 1 -node_disk_info{device="nvme0n1",major="259",minor="0"} 1 -node_disk_info{device="sda",major="8",minor="0"} 1 -node_disk_info{device="sdb",major="8",minor="0"} 1 -node_disk_info{device="sdc",major="8",minor="0"} 1 -node_disk_info{device="sr0",major="11",minor="0"} 1 -node_disk_info{device="vda",major="254",minor="0"} 1 +node_disk_info{device="dm-0",major="252",minor="0",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-1",major="252",minor="1",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-2",major="252",minor="2",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-3",major="252",minor="3",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-4",major="252",minor="4",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="dm-5",major="252",minor="5",model="",path="",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0",major="179",minor="0",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0p1",major="179",minor="1",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="mmcblk0p2",major="179",minor="2",model="",path="platform-df2969f3.mmc",revision="",serial="",wwn=""} 1 +node_disk_info{device="nvme0n1",major="259",minor="0",model="SAMSUNG EHFTF55LURSY-000Y9",path="pci-0000:02:00.0-nvme-1",revision="4NBTUY95",serial="S252B6CU1HG3M1",wwn="eui.p3vbbiejx5aae2r3"} 1 +node_disk_info{device="sda",major="8",minor="0",model="TOSHIBA_KSDB4U86",path="pci-0000:3b:00.0-sas-phy7-lun-0",revision="0102",serial="2160A0D5FVGG",wwn="0x7c72382b8de36a64"} 1 +node_disk_info{device="sdb",major="8",minor="16",model="SuperMicro_SSD",path="pci-0000:00:1f.2-ata-1",revision="0R",serial="SMC0E1B87ABBB16BD84E",wwn="0xe1b87abbb16bd84e"} 1 +node_disk_info{device="sdc",major="8",minor="32",model="INTEL_SSDS9X9SI0",path="pci-0000:00:1f.2-ata-4",revision="0100",serial="3EWB5Y25CWQWA7EH1U",wwn="0x58907ddc573a5de"} 1 +node_disk_info{device="sr0",major="11",minor="0",model="Virtual_CDROM0",path="pci-0000:00:14.0-usb-0:1.1:1.0-scsi-0:0:0:0",revision="1.00",serial="AAAABBBBCCCC1",wwn=""} 1 +node_disk_info{device="vda",major="254",minor="0",model="",path="pci-0000:00:06.0",revision="",serial="",wwn=""} 1 # HELP node_disk_io_now The number of I/Os currently in progress. # TYPE node_disk_io_now gauge node_disk_io_now{device="dm-0"} 0 @@ -609,7 +694,7 @@ node_disk_written_bytes_total{device="sr0"} 0 node_disk_written_bytes_total{device="vda"} 1.0938236928e+11 # HELP node_dmi_info A metric with a constant '1' value labeled by bios_date, bios_release, bios_vendor, bios_version, board_asset_tag, board_name, board_serial, board_vendor, board_version, chassis_asset_tag, chassis_serial, chassis_vendor, chassis_version, product_family, product_name, product_serial, product_sku, product_uuid, product_version, system_vendor if provided by DMI. # TYPE node_dmi_info gauge -node_dmi_info{bios_date="04/12/2021",bios_release="2.2",bios_vendor="Dell Inc.",bios_version="2.2.4",board_name="07PXPY",board_serial=".7N62AI2.GRTCL6944100GP.",board_vendor="Dell Inc.",board_version="A01",chassis_asset_tag="",chassis_serial="7N62AI2",chassis_vendor="Dell Inc.",chassis_version="",product_family="PowerEdge",product_name="PowerEdge R6515",product_serial="7N62AI2",product_sku="SKU=NotProvided;ModelName=PowerEdge R6515",product_uuid="83340ca8-cb49-4474-8c29-d2088ca84dd9",product_version="",system_vendor="Dell Inc."} 1 +node_dmi_info{bios_date="04/12/2021",bios_release="2.2",bios_vendor="Dell Inc.",bios_version="2.2.4",board_name="07PXPY",board_serial=".7N62AI2.GRTCL6944100GP.",board_vendor="Dell Inc.",board_version="A01",chassis_asset_tag="",chassis_serial="7N62AI2",chassis_vendor="Dell Inc.",chassis_version="",product_family="PowerEdge",product_name="PowerEdge R6515",product_serial="7N62AI2",product_sku="SKU=NotProvided;ModelName=PowerEdge R6515",product_uuid="83340ca8-cb49-4474-8c29-d2088ca84dd9",product_version="�[�",system_vendor="Dell Inc."} 1 # HELP node_drbd_activitylog_writes_total Number of updates of the activity log area of the meta data. # TYPE node_drbd_activitylog_writes_total counter node_drbd_activitylog_writes_total{device="drbd1"} 1100 @@ -677,7 +762,7 @@ node_entropy_available_bits 1337 # HELP node_entropy_pool_size_bits Bits of entropy pool. # TYPE node_entropy_pool_size_bits gauge node_entropy_pool_size_bits 4096 -# HELP node_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, and goversion from which node_exporter was built. +# HELP node_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, goversion from which node_exporter was built, and the goos and goarch for the build. # TYPE node_exporter_build_info gauge # HELP node_fibrechannel_error_frames_total Number of errors in frames # TYPE node_fibrechannel_error_frames_total counter @@ -885,18 +970,18 @@ node_hwmon_pwm_weight_temp_step_tol{chip="nct6779",sensor="pwm1"} 0 # TYPE node_hwmon_sensor_label gauge node_hwmon_sensor_label{chip="hwmon4",label="foosensor",sensor="temp1"} 1 node_hwmon_sensor_label{chip="hwmon4",label="foosensor",sensor="temp2"} 1 -node_hwmon_sensor_label{chip="platform_applesmc_768",label="left_side",sensor="fan1"} 1 -node_hwmon_sensor_label{chip="platform_applesmc_768",label="right_side",sensor="fan2"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_0",sensor="temp2"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_1",sensor="temp3"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_2",sensor="temp4"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="core_3",sensor="temp5"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_0",label="physical_id_0",sensor="temp1"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_0",sensor="temp2"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_1",sensor="temp3"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_2",sensor="temp4"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="core_3",sensor="temp5"} 1 -node_hwmon_sensor_label{chip="platform_coretemp_1",label="physical_id_0",sensor="temp1"} 1 +node_hwmon_sensor_label{chip="platform_applesmc_768",label="Left side ",sensor="fan1"} 1 +node_hwmon_sensor_label{chip="platform_applesmc_768",label="Right side ",sensor="fan2"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 0",sensor="temp2"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 1",sensor="temp3"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 2",sensor="temp4"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Core 3",sensor="temp5"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_0",label="Physical id 0",sensor="temp1"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 0",sensor="temp2"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 1",sensor="temp3"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 2",sensor="temp4"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Core 3",sensor="temp5"} 1 +node_hwmon_sensor_label{chip="platform_coretemp_1",label="Physical id 0",sensor="temp1"} 1 # HELP node_hwmon_temp_celsius Hardware monitor for temperature (input) # TYPE node_hwmon_temp_celsius gauge node_hwmon_temp_celsius{chip="hwmon4",sensor="temp1"} 55 @@ -2240,6 +2325,12 @@ node_netstat_TcpExt_SyncookiesRecv 0 # HELP node_netstat_TcpExt_SyncookiesSent Statistic TcpExtSyncookiesSent. # TYPE node_netstat_TcpExt_SyncookiesSent untyped node_netstat_TcpExt_SyncookiesSent 0 +# HELP node_netstat_TcpExt_TCPOFOQueue Statistic TcpExtTCPOFOQueue. +# TYPE node_netstat_TcpExt_TCPOFOQueue untyped +node_netstat_TcpExt_TCPOFOQueue 42 +# HELP node_netstat_TcpExt_TCPTimeouts Statistic TcpExtTCPTimeouts. +# TYPE node_netstat_TcpExt_TCPTimeouts untyped +node_netstat_TcpExt_TCPTimeouts 115 # HELP node_netstat_Tcp_ActiveOpens Statistic TcpActiveOpens. # TYPE node_netstat_Tcp_ActiveOpens untyped node_netstat_Tcp_ActiveOpens 3556 @@ -2306,266 +2397,121 @@ node_netstat_Udp_RcvbufErrors 9 # HELP node_netstat_Udp_SndbufErrors Statistic UdpSndbufErrors. # TYPE node_netstat_Udp_SndbufErrors untyped node_netstat_Udp_SndbufErrors 8 -# HELP node_network_address_assign_type address_assign_type value of /sys/class/net/. +# HELP node_network_address_assign_type Network device property: address_assign_type # TYPE node_network_address_assign_type gauge node_network_address_assign_type{device="bond0"} 3 node_network_address_assign_type{device="eth0"} 3 -# HELP node_network_carrier carrier value of /sys/class/net/. +# HELP node_network_carrier Network device property: carrier # TYPE node_network_carrier gauge node_network_carrier{device="bond0"} 1 node_network_carrier{device="eth0"} 1 -# HELP node_network_carrier_changes_total carrier_changes_total value of /sys/class/net/. +# HELP node_network_carrier_changes_total Network device property: carrier_changes_total # TYPE node_network_carrier_changes_total counter node_network_carrier_changes_total{device="bond0"} 2 node_network_carrier_changes_total{device="eth0"} 2 -# HELP node_network_carrier_down_changes_total carrier_down_changes_total value of /sys/class/net/. +# HELP node_network_carrier_down_changes_total Network device property: carrier_down_changes_total # TYPE node_network_carrier_down_changes_total counter node_network_carrier_down_changes_total{device="bond0"} 1 node_network_carrier_down_changes_total{device="eth0"} 1 -# HELP node_network_carrier_up_changes_total carrier_up_changes_total value of /sys/class/net/. +# HELP node_network_carrier_up_changes_total Network device property: carrier_up_changes_total # TYPE node_network_carrier_up_changes_total counter node_network_carrier_up_changes_total{device="bond0"} 1 node_network_carrier_up_changes_total{device="eth0"} 1 -# HELP node_network_device_id device_id value of /sys/class/net/. +# HELP node_network_device_id Network device property: device_id # TYPE node_network_device_id gauge node_network_device_id{device="bond0"} 32 node_network_device_id{device="eth0"} 32 -# HELP node_network_dormant dormant value of /sys/class/net/. +# HELP node_network_dormant Network device property: dormant # TYPE node_network_dormant gauge node_network_dormant{device="bond0"} 1 node_network_dormant{device="eth0"} 1 -# HELP node_network_flags flags value of /sys/class/net/. +# HELP node_network_flags Network device property: flags # TYPE node_network_flags gauge node_network_flags{device="bond0"} 4867 node_network_flags{device="eth0"} 4867 -# HELP node_network_iface_id iface_id value of /sys/class/net/. +# HELP node_network_iface_id Network device property: iface_id # TYPE node_network_iface_id gauge node_network_iface_id{device="bond0"} 2 node_network_iface_id{device="eth0"} 2 -# HELP node_network_iface_link iface_link value of /sys/class/net/. +# HELP node_network_iface_link Network device property: iface_link # TYPE node_network_iface_link gauge node_network_iface_link{device="bond0"} 2 node_network_iface_link{device="eth0"} 2 -# HELP node_network_iface_link_mode iface_link_mode value of /sys/class/net/. +# HELP node_network_iface_link_mode Network device property: iface_link_mode # TYPE node_network_iface_link_mode gauge node_network_iface_link_mode{device="bond0"} 1 node_network_iface_link_mode{device="eth0"} 1 # HELP node_network_info Non-numeric data from /sys/class/net/, value is always 1. # TYPE node_network_info gauge -node_network_info{address="01:01:01:01:01:01",broadcast="ff:ff:ff:ff:ff:ff",device="bond0",duplex="full",ifalias="",operstate="up"} 1 -node_network_info{address="01:01:01:01:01:01",broadcast="ff:ff:ff:ff:ff:ff",device="eth0",duplex="full",ifalias="",operstate="up"} 1 -# HELP node_network_mtu_bytes mtu_bytes value of /sys/class/net/. +node_network_info{address="01:01:01:01:01:01",adminstate="up",broadcast="ff:ff:ff:ff:ff:ff",device="bond0",duplex="full",ifalias="",operstate="up"} 1 +node_network_info{address="01:01:01:01:01:01",adminstate="up",broadcast="ff:ff:ff:ff:ff:ff",device="eth0",duplex="full",ifalias="",operstate="up"} 1 +# HELP node_network_mtu_bytes Network device property: mtu_bytes # TYPE node_network_mtu_bytes gauge node_network_mtu_bytes{device="bond0"} 1500 node_network_mtu_bytes{device="eth0"} 1500 -# HELP node_network_name_assign_type name_assign_type value of /sys/class/net/. +# HELP node_network_name_assign_type Network device property: name_assign_type # TYPE node_network_name_assign_type gauge node_network_name_assign_type{device="bond0"} 2 node_network_name_assign_type{device="eth0"} 2 -# HELP node_network_net_dev_group net_dev_group value of /sys/class/net/. +# HELP node_network_net_dev_group Network device property: net_dev_group # TYPE node_network_net_dev_group gauge node_network_net_dev_group{device="bond0"} 0 node_network_net_dev_group{device="eth0"} 0 -# HELP node_network_protocol_type protocol_type value of /sys/class/net/. +# HELP node_network_protocol_type Network device property: protocol_type # TYPE node_network_protocol_type gauge node_network_protocol_type{device="bond0"} 1 node_network_protocol_type{device="eth0"} 1 # HELP node_network_receive_bytes_total Network device statistic receive_bytes. # TYPE node_network_receive_bytes_total counter -node_network_receive_bytes_total{device="docker0"} 6.4910168e+07 -node_network_receive_bytes_total{device="eth0"} 6.8210035552e+10 -node_network_receive_bytes_total{device="flannel.1"} 1.8144009813e+10 -node_network_receive_bytes_total{device="ibr10:30"} 0 -node_network_receive_bytes_total{device="lo"} 4.35303245e+08 -node_network_receive_bytes_total{device="lxcbr0"} 0 -node_network_receive_bytes_total{device="tun0"} 1888 -node_network_receive_bytes_total{device="veth4B09XN"} 648 -node_network_receive_bytes_total{device="wlan0"} 1.0437182923e+10 -node_network_receive_bytes_total{device="💩0"} 5.7750104e+07 # HELP node_network_receive_compressed_total Network device statistic receive_compressed. # TYPE node_network_receive_compressed_total counter -node_network_receive_compressed_total{device="docker0"} 0 -node_network_receive_compressed_total{device="eth0"} 0 -node_network_receive_compressed_total{device="flannel.1"} 0 -node_network_receive_compressed_total{device="ibr10:30"} 0 node_network_receive_compressed_total{device="lo"} 0 -node_network_receive_compressed_total{device="lxcbr0"} 0 -node_network_receive_compressed_total{device="tun0"} 0 -node_network_receive_compressed_total{device="veth4B09XN"} 0 -node_network_receive_compressed_total{device="wlan0"} 0 -node_network_receive_compressed_total{device="💩0"} 0 # HELP node_network_receive_drop_total Network device statistic receive_drop. # TYPE node_network_receive_drop_total counter -node_network_receive_drop_total{device="docker0"} 0 -node_network_receive_drop_total{device="eth0"} 0 -node_network_receive_drop_total{device="flannel.1"} 0 -node_network_receive_drop_total{device="ibr10:30"} 0 node_network_receive_drop_total{device="lo"} 0 -node_network_receive_drop_total{device="lxcbr0"} 0 -node_network_receive_drop_total{device="tun0"} 0 -node_network_receive_drop_total{device="veth4B09XN"} 0 -node_network_receive_drop_total{device="wlan0"} 0 -node_network_receive_drop_total{device="💩0"} 0 # HELP node_network_receive_errs_total Network device statistic receive_errs. # TYPE node_network_receive_errs_total counter -node_network_receive_errs_total{device="docker0"} 0 -node_network_receive_errs_total{device="eth0"} 0 -node_network_receive_errs_total{device="flannel.1"} 0 -node_network_receive_errs_total{device="ibr10:30"} 0 node_network_receive_errs_total{device="lo"} 0 -node_network_receive_errs_total{device="lxcbr0"} 0 -node_network_receive_errs_total{device="tun0"} 0 -node_network_receive_errs_total{device="veth4B09XN"} 0 -node_network_receive_errs_total{device="wlan0"} 0 -node_network_receive_errs_total{device="💩0"} 0 # HELP node_network_receive_fifo_total Network device statistic receive_fifo. # TYPE node_network_receive_fifo_total counter -node_network_receive_fifo_total{device="docker0"} 0 -node_network_receive_fifo_total{device="eth0"} 0 -node_network_receive_fifo_total{device="flannel.1"} 0 -node_network_receive_fifo_total{device="ibr10:30"} 0 node_network_receive_fifo_total{device="lo"} 0 -node_network_receive_fifo_total{device="lxcbr0"} 0 -node_network_receive_fifo_total{device="tun0"} 0 -node_network_receive_fifo_total{device="veth4B09XN"} 0 -node_network_receive_fifo_total{device="wlan0"} 0 -node_network_receive_fifo_total{device="💩0"} 0 # HELP node_network_receive_frame_total Network device statistic receive_frame. # TYPE node_network_receive_frame_total counter -node_network_receive_frame_total{device="docker0"} 0 -node_network_receive_frame_total{device="eth0"} 0 -node_network_receive_frame_total{device="flannel.1"} 0 -node_network_receive_frame_total{device="ibr10:30"} 0 node_network_receive_frame_total{device="lo"} 0 -node_network_receive_frame_total{device="lxcbr0"} 0 -node_network_receive_frame_total{device="tun0"} 0 -node_network_receive_frame_total{device="veth4B09XN"} 0 -node_network_receive_frame_total{device="wlan0"} 0 -node_network_receive_frame_total{device="💩0"} 0 # HELP node_network_receive_multicast_total Network device statistic receive_multicast. # TYPE node_network_receive_multicast_total counter -node_network_receive_multicast_total{device="docker0"} 0 -node_network_receive_multicast_total{device="eth0"} 0 -node_network_receive_multicast_total{device="flannel.1"} 0 -node_network_receive_multicast_total{device="ibr10:30"} 0 node_network_receive_multicast_total{device="lo"} 0 -node_network_receive_multicast_total{device="lxcbr0"} 0 -node_network_receive_multicast_total{device="tun0"} 0 -node_network_receive_multicast_total{device="veth4B09XN"} 0 -node_network_receive_multicast_total{device="wlan0"} 0 -node_network_receive_multicast_total{device="💩0"} 72 +# HELP node_network_receive_nohandler_total Network device statistic receive_nohandler. +# TYPE node_network_receive_nohandler_total counter +node_network_receive_nohandler_total{device="lo"} 0 # HELP node_network_receive_packets_total Network device statistic receive_packets. # TYPE node_network_receive_packets_total counter -node_network_receive_packets_total{device="docker0"} 1.065585e+06 -node_network_receive_packets_total{device="eth0"} 5.20993275e+08 -node_network_receive_packets_total{device="flannel.1"} 2.28499337e+08 -node_network_receive_packets_total{device="ibr10:30"} 0 -node_network_receive_packets_total{device="lo"} 1.832522e+06 -node_network_receive_packets_total{device="lxcbr0"} 0 -node_network_receive_packets_total{device="tun0"} 24 -node_network_receive_packets_total{device="veth4B09XN"} 8 -node_network_receive_packets_total{device="wlan0"} 1.3899359e+07 -node_network_receive_packets_total{device="💩0"} 105557 -# HELP node_network_speed_bytes speed_bytes value of /sys/class/net/. +# HELP node_network_speed_bytes Network device property: speed_bytes # TYPE node_network_speed_bytes gauge node_network_speed_bytes{device="eth0"} 1.25e+08 # HELP node_network_transmit_bytes_total Network device statistic transmit_bytes. # TYPE node_network_transmit_bytes_total counter -node_network_transmit_bytes_total{device="docker0"} 2.681662018e+09 -node_network_transmit_bytes_total{device="eth0"} 9.315587528e+09 -node_network_transmit_bytes_total{device="flannel.1"} 2.0758990068e+10 -node_network_transmit_bytes_total{device="ibr10:30"} 0 -node_network_transmit_bytes_total{device="lo"} 4.35303245e+08 -node_network_transmit_bytes_total{device="lxcbr0"} 2.630299e+06 -node_network_transmit_bytes_total{device="tun0"} 67120 -node_network_transmit_bytes_total{device="veth4B09XN"} 1.943284e+06 -node_network_transmit_bytes_total{device="wlan0"} 2.85164936e+09 -node_network_transmit_bytes_total{device="💩0"} 4.04570255e+08 # HELP node_network_transmit_carrier_total Network device statistic transmit_carrier. # TYPE node_network_transmit_carrier_total counter -node_network_transmit_carrier_total{device="docker0"} 0 -node_network_transmit_carrier_total{device="eth0"} 0 -node_network_transmit_carrier_total{device="flannel.1"} 0 -node_network_transmit_carrier_total{device="ibr10:30"} 0 node_network_transmit_carrier_total{device="lo"} 0 -node_network_transmit_carrier_total{device="lxcbr0"} 0 -node_network_transmit_carrier_total{device="tun0"} 0 -node_network_transmit_carrier_total{device="veth4B09XN"} 0 -node_network_transmit_carrier_total{device="wlan0"} 0 -node_network_transmit_carrier_total{device="💩0"} 0 # HELP node_network_transmit_colls_total Network device statistic transmit_colls. # TYPE node_network_transmit_colls_total counter -node_network_transmit_colls_total{device="docker0"} 0 -node_network_transmit_colls_total{device="eth0"} 0 -node_network_transmit_colls_total{device="flannel.1"} 0 -node_network_transmit_colls_total{device="ibr10:30"} 0 node_network_transmit_colls_total{device="lo"} 0 -node_network_transmit_colls_total{device="lxcbr0"} 0 -node_network_transmit_colls_total{device="tun0"} 0 -node_network_transmit_colls_total{device="veth4B09XN"} 0 -node_network_transmit_colls_total{device="wlan0"} 0 -node_network_transmit_colls_total{device="💩0"} 0 # HELP node_network_transmit_compressed_total Network device statistic transmit_compressed. # TYPE node_network_transmit_compressed_total counter -node_network_transmit_compressed_total{device="docker0"} 0 -node_network_transmit_compressed_total{device="eth0"} 0 -node_network_transmit_compressed_total{device="flannel.1"} 0 -node_network_transmit_compressed_total{device="ibr10:30"} 0 node_network_transmit_compressed_total{device="lo"} 0 -node_network_transmit_compressed_total{device="lxcbr0"} 0 -node_network_transmit_compressed_total{device="tun0"} 0 -node_network_transmit_compressed_total{device="veth4B09XN"} 0 -node_network_transmit_compressed_total{device="wlan0"} 0 -node_network_transmit_compressed_total{device="💩0"} 0 # HELP node_network_transmit_drop_total Network device statistic transmit_drop. # TYPE node_network_transmit_drop_total counter -node_network_transmit_drop_total{device="docker0"} 0 -node_network_transmit_drop_total{device="eth0"} 0 -node_network_transmit_drop_total{device="flannel.1"} 64 -node_network_transmit_drop_total{device="ibr10:30"} 0 node_network_transmit_drop_total{device="lo"} 0 -node_network_transmit_drop_total{device="lxcbr0"} 0 -node_network_transmit_drop_total{device="tun0"} 0 -node_network_transmit_drop_total{device="veth4B09XN"} 0 -node_network_transmit_drop_total{device="wlan0"} 0 -node_network_transmit_drop_total{device="💩0"} 0 # HELP node_network_transmit_errs_total Network device statistic transmit_errs. # TYPE node_network_transmit_errs_total counter -node_network_transmit_errs_total{device="docker0"} 0 -node_network_transmit_errs_total{device="eth0"} 0 -node_network_transmit_errs_total{device="flannel.1"} 0 -node_network_transmit_errs_total{device="ibr10:30"} 0 node_network_transmit_errs_total{device="lo"} 0 -node_network_transmit_errs_total{device="lxcbr0"} 0 -node_network_transmit_errs_total{device="tun0"} 0 -node_network_transmit_errs_total{device="veth4B09XN"} 0 -node_network_transmit_errs_total{device="wlan0"} 0 -node_network_transmit_errs_total{device="💩0"} 0 # HELP node_network_transmit_fifo_total Network device statistic transmit_fifo. # TYPE node_network_transmit_fifo_total counter -node_network_transmit_fifo_total{device="docker0"} 0 -node_network_transmit_fifo_total{device="eth0"} 0 -node_network_transmit_fifo_total{device="flannel.1"} 0 -node_network_transmit_fifo_total{device="ibr10:30"} 0 node_network_transmit_fifo_total{device="lo"} 0 -node_network_transmit_fifo_total{device="lxcbr0"} 0 -node_network_transmit_fifo_total{device="tun0"} 0 -node_network_transmit_fifo_total{device="veth4B09XN"} 0 -node_network_transmit_fifo_total{device="wlan0"} 0 -node_network_transmit_fifo_total{device="💩0"} 0 # HELP node_network_transmit_packets_total Network device statistic transmit_packets. # TYPE node_network_transmit_packets_total counter -node_network_transmit_packets_total{device="docker0"} 1.929779e+06 -node_network_transmit_packets_total{device="eth0"} 4.3451486e+07 -node_network_transmit_packets_total{device="flannel.1"} 2.58369223e+08 -node_network_transmit_packets_total{device="ibr10:30"} 0 -node_network_transmit_packets_total{device="lo"} 1.832522e+06 -node_network_transmit_packets_total{device="lxcbr0"} 28339 -node_network_transmit_packets_total{device="tun0"} 934 -node_network_transmit_packets_total{device="veth4B09XN"} 10640 -node_network_transmit_packets_total{device="wlan0"} 1.17262e+07 -node_network_transmit_packets_total{device="💩0"} 304261 -# HELP node_network_transmit_queue_length transmit_queue_length value of /sys/class/net/. +# HELP node_network_transmit_queue_length Network device property: transmit_queue_length # TYPE node_network_transmit_queue_length gauge node_network_transmit_queue_length{device="bond0"} 1000 node_network_transmit_queue_length{device="eth0"} 1000 @@ -2817,13 +2763,16 @@ node_nfsd_requests_total{method="SecInfo",proto="4"} 0 node_nfsd_requests_total{method="SetAttr",proto="2"} 0 node_nfsd_requests_total{method="SetAttr",proto="3"} 0 node_nfsd_requests_total{method="SetAttr",proto="4"} 0 +node_nfsd_requests_total{method="SetClientID",proto="4"} 3 +node_nfsd_requests_total{method="SetClientIDConfirm",proto="4"} 3 node_nfsd_requests_total{method="SymLink",proto="2"} 0 node_nfsd_requests_total{method="SymLink",proto="3"} 0 -node_nfsd_requests_total{method="Verify",proto="4"} 3 +node_nfsd_requests_total{method="Verify",proto="4"} 0 +node_nfsd_requests_total{method="WdelegGetattr",proto="4"} 15 node_nfsd_requests_total{method="WrCache",proto="2"} 0 node_nfsd_requests_total{method="Write",proto="2"} 0 node_nfsd_requests_total{method="Write",proto="3"} 0 -node_nfsd_requests_total{method="Write",proto="4"} 3 +node_nfsd_requests_total{method="Write",proto="4"} 0 # HELP node_nfsd_rpc_errors_total Total number of NFSd RPC errors by error type. # TYPE node_nfsd_rpc_errors_total counter node_nfsd_rpc_errors_total{error="auth"} 2 @@ -2862,7 +2811,7 @@ node_power_supply_energy_watthour{power_supply="BAT0"} 36.58 # HELP node_power_supply_info info of /sys/class/power_supply/. # TYPE node_power_supply_info gauge node_power_supply_info{power_supply="AC",type="Mains"} 1 -node_power_supply_info{capacity_level="Normal",manufacturer="LGC",model_name="LNV-45N1�",power_supply="BAT0",serial_number="38109",status="Discharging",technology="Li-ion",type="Battery"} 1 +node_power_supply_info{capacity_level="Normal",manufacturer="LGC",model_name="LNV-45N1��",power_supply="BAT0",serial_number="38109",status="Discharging",technology="Li-ion",type="Battery"} 1 # HELP node_power_supply_online online value of /sys/class/power_supply/. # TYPE node_power_supply_online gauge node_power_supply_online{power_supply="AC"} 0 @@ -2970,8 +2919,10 @@ node_scrape_collector_success{collector="bcache"} 1 node_scrape_collector_success{collector="bonding"} 1 node_scrape_collector_success{collector="btrfs"} 1 node_scrape_collector_success{collector="buddyinfo"} 1 +node_scrape_collector_success{collector="cgroups"} 1 node_scrape_collector_success{collector="conntrack"} 1 node_scrape_collector_success{collector="cpu"} 1 +node_scrape_collector_success{collector="cpu_vulnerabilities"} 1 node_scrape_collector_success{collector="cpufreq"} 1 node_scrape_collector_success{collector="diskstats"} 1 node_scrape_collector_success{collector="dmi"} 1 @@ -3004,18 +2955,57 @@ node_scrape_collector_success{collector="processes"} 1 node_scrape_collector_success{collector="qdisc"} 1 node_scrape_collector_success{collector="rapl"} 1 node_scrape_collector_success{collector="schedstat"} 1 +node_scrape_collector_success{collector="selinux"} 1 +node_scrape_collector_success{collector="slabinfo"} 1 node_scrape_collector_success{collector="sockstat"} 1 +node_scrape_collector_success{collector="softirqs"} 1 node_scrape_collector_success{collector="softnet"} 1 node_scrape_collector_success{collector="stat"} 1 +node_scrape_collector_success{collector="sysctl"} 1 node_scrape_collector_success{collector="tapestats"} 1 node_scrape_collector_success{collector="textfile"} 1 node_scrape_collector_success{collector="thermal_zone"} 1 +node_scrape_collector_success{collector="time"} 1 node_scrape_collector_success{collector="udp_queues"} 1 node_scrape_collector_success{collector="vmstat"} 1 node_scrape_collector_success{collector="wifi"} 1 +node_scrape_collector_success{collector="xfrm"} 1 node_scrape_collector_success{collector="xfs"} 1 node_scrape_collector_success{collector="zfs"} 1 node_scrape_collector_success{collector="zoneinfo"} 1 +# HELP node_selinux_enabled SELinux is enabled, 1 is true, 0 is false +# TYPE node_selinux_enabled gauge +node_selinux_enabled 0 +# HELP node_slabinfo_active_objects The number of objects that are currently active (i.e., in use). +# TYPE node_slabinfo_active_objects gauge +node_slabinfo_active_objects{slab="dmaengine-unmap-128"} 1206 +node_slabinfo_active_objects{slab="kmalloc-8192"} 132 +node_slabinfo_active_objects{slab="kmem_cache"} 320 +node_slabinfo_active_objects{slab="tw_sock_TCP"} 704 +# HELP node_slabinfo_object_size_bytes The size of objects in this slab, in bytes. +# TYPE node_slabinfo_object_size_bytes gauge +node_slabinfo_object_size_bytes{slab="dmaengine-unmap-128"} 1088 +node_slabinfo_object_size_bytes{slab="kmalloc-8192"} 8192 +node_slabinfo_object_size_bytes{slab="kmem_cache"} 256 +node_slabinfo_object_size_bytes{slab="tw_sock_TCP"} 256 +# HELP node_slabinfo_objects The total number of allocated objects (i.e., objects that are both in use and not in use). +# TYPE node_slabinfo_objects gauge +node_slabinfo_objects{slab="dmaengine-unmap-128"} 1320 +node_slabinfo_objects{slab="kmalloc-8192"} 148 +node_slabinfo_objects{slab="kmem_cache"} 320 +node_slabinfo_objects{slab="tw_sock_TCP"} 864 +# HELP node_slabinfo_objects_per_slab The number of objects stored in each slab. +# TYPE node_slabinfo_objects_per_slab gauge +node_slabinfo_objects_per_slab{slab="dmaengine-unmap-128"} 30 +node_slabinfo_objects_per_slab{slab="kmalloc-8192"} 4 +node_slabinfo_objects_per_slab{slab="kmem_cache"} 32 +node_slabinfo_objects_per_slab{slab="tw_sock_TCP"} 32 +# HELP node_slabinfo_pages_per_slab The number of pages allocated for each slab. +# TYPE node_slabinfo_pages_per_slab gauge +node_slabinfo_pages_per_slab{slab="dmaengine-unmap-128"} 8 +node_slabinfo_pages_per_slab{slab="kmalloc-8192"} 8 +node_slabinfo_pages_per_slab{slab="kmem_cache"} 2 +node_slabinfo_pages_per_slab{slab="tw_sock_TCP"} 2 # HELP node_sockstat_FRAG6_inuse Number of FRAG6 sockets in state inuse. # TYPE node_sockstat_FRAG6_inuse gauge node_sockstat_FRAG6_inuse 0 @@ -3076,24 +3066,109 @@ node_sockstat_UDP_mem_bytes 0 # HELP node_sockstat_sockets_used Number of IPv4 sockets in use. # TYPE node_sockstat_sockets_used gauge node_sockstat_sockets_used 229 +# HELP node_softirqs_functions_total Softirq counts per CPU. +# TYPE node_softirqs_functions_total counter +node_softirqs_functions_total{cpu="0",type="BLOCK"} 23776 +node_softirqs_functions_total{cpu="0",type="HI"} 7 +node_softirqs_functions_total{cpu="0",type="HRTIMER"} 40 +node_softirqs_functions_total{cpu="0",type="IRQ_POLL"} 0 +node_softirqs_functions_total{cpu="0",type="NET_RX"} 43066 +node_softirqs_functions_total{cpu="0",type="NET_TX"} 2301 +node_softirqs_functions_total{cpu="0",type="RCU"} 155929 +node_softirqs_functions_total{cpu="0",type="SCHED"} 378895 +node_softirqs_functions_total{cpu="0",type="TASKLET"} 372 +node_softirqs_functions_total{cpu="0",type="TIMER"} 424191 +node_softirqs_functions_total{cpu="1",type="BLOCK"} 24115 +node_softirqs_functions_total{cpu="1",type="HI"} 1 +node_softirqs_functions_total{cpu="1",type="HRTIMER"} 346 +node_softirqs_functions_total{cpu="1",type="IRQ_POLL"} 0 +node_softirqs_functions_total{cpu="1",type="NET_RX"} 104508 +node_softirqs_functions_total{cpu="1",type="NET_TX"} 2430 +node_softirqs_functions_total{cpu="1",type="RCU"} 146631 +node_softirqs_functions_total{cpu="1",type="SCHED"} 152852 +node_softirqs_functions_total{cpu="1",type="TASKLET"} 1899 +node_softirqs_functions_total{cpu="1",type="TIMER"} 108342 +# HELP node_softirqs_total Number of softirq calls. +# TYPE node_softirqs_total counter +node_softirqs_total{vector="block"} 186066 +node_softirqs_total{vector="block_iopoll"} 0 +node_softirqs_total{vector="hi"} 250191 +node_softirqs_total{vector="hrtimer"} 12499 +node_softirqs_total{vector="net_rx"} 211099 +node_softirqs_total{vector="net_tx"} 1647 +node_softirqs_total{vector="rcu"} 508444 +node_softirqs_total{vector="sched"} 622196 +node_softirqs_total{vector="tasklet"} 1.783454e+06 +node_softirqs_total{vector="timer"} 1.481983e+06 +# HELP node_softnet_backlog_len Softnet backlog status +# TYPE node_softnet_backlog_len gauge +node_softnet_backlog_len{cpu="0"} 0 +node_softnet_backlog_len{cpu="1"} 0 +node_softnet_backlog_len{cpu="2"} 0 +node_softnet_backlog_len{cpu="3"} 0 +# HELP node_softnet_cpu_collision_total Number of collision occur while obtaining device lock while transmitting +# TYPE node_softnet_cpu_collision_total counter +node_softnet_cpu_collision_total{cpu="0"} 0 +node_softnet_cpu_collision_total{cpu="1"} 0 +node_softnet_cpu_collision_total{cpu="2"} 0 +node_softnet_cpu_collision_total{cpu="3"} 0 # HELP node_softnet_dropped_total Number of dropped packets # TYPE node_softnet_dropped_total counter node_softnet_dropped_total{cpu="0"} 0 node_softnet_dropped_total{cpu="1"} 41 node_softnet_dropped_total{cpu="2"} 0 node_softnet_dropped_total{cpu="3"} 0 +# HELP node_softnet_flow_limit_count_total Number of times flow limit has been reached +# TYPE node_softnet_flow_limit_count_total counter +node_softnet_flow_limit_count_total{cpu="0"} 0 +node_softnet_flow_limit_count_total{cpu="1"} 0 +node_softnet_flow_limit_count_total{cpu="2"} 0 +node_softnet_flow_limit_count_total{cpu="3"} 0 # HELP node_softnet_processed_total Number of processed packets # TYPE node_softnet_processed_total counter node_softnet_processed_total{cpu="0"} 299641 node_softnet_processed_total{cpu="1"} 916354 node_softnet_processed_total{cpu="2"} 5.577791e+06 node_softnet_processed_total{cpu="3"} 3.113785e+06 +# HELP node_softnet_received_rps_total Number of times cpu woken up received_rps +# TYPE node_softnet_received_rps_total counter +node_softnet_received_rps_total{cpu="0"} 0 +node_softnet_received_rps_total{cpu="1"} 0 +node_softnet_received_rps_total{cpu="2"} 0 +node_softnet_received_rps_total{cpu="3"} 0 # HELP node_softnet_times_squeezed_total Number of times processing packets ran out of quota # TYPE node_softnet_times_squeezed_total counter node_softnet_times_squeezed_total{cpu="0"} 1 node_softnet_times_squeezed_total{cpu="1"} 10 node_softnet_times_squeezed_total{cpu="2"} 85 node_softnet_times_squeezed_total{cpu="3"} 50 +# HELP node_sysctl_fs_file_nr sysctl fs.file-nr +# TYPE node_sysctl_fs_file_nr untyped +node_sysctl_fs_file_nr{index="0"} 1024 +node_sysctl_fs_file_nr{index="1"} 0 +node_sysctl_fs_file_nr{index="2"} 1.631329e+06 +# HELP node_sysctl_fs_file_nr_current sysctl fs.file-nr, field 1 +# TYPE node_sysctl_fs_file_nr_current untyped +node_sysctl_fs_file_nr_current 0 +# HELP node_sysctl_fs_file_nr_max sysctl fs.file-nr, field 2 +# TYPE node_sysctl_fs_file_nr_max untyped +node_sysctl_fs_file_nr_max 1.631329e+06 +# HELP node_sysctl_fs_file_nr_total sysctl fs.file-nr, field 0 +# TYPE node_sysctl_fs_file_nr_total untyped +node_sysctl_fs_file_nr_total 1024 +# HELP node_sysctl_info sysctl info +# TYPE node_sysctl_info gauge +node_sysctl_info{index="0",name="kernel.seccomp.actions_avail",value="kill_process"} 1 +node_sysctl_info{index="1",name="kernel.seccomp.actions_avail",value="kill_thread"} 1 +node_sysctl_info{index="2",name="kernel.seccomp.actions_avail",value="trap"} 1 +node_sysctl_info{index="3",name="kernel.seccomp.actions_avail",value="errno"} 1 +node_sysctl_info{index="4",name="kernel.seccomp.actions_avail",value="user_notif"} 1 +node_sysctl_info{index="5",name="kernel.seccomp.actions_avail",value="trace"} 1 +node_sysctl_info{index="6",name="kernel.seccomp.actions_avail",value="log"} 1 +node_sysctl_info{index="7",name="kernel.seccomp.actions_avail",value="allow"} 1 +# HELP node_sysctl_kernel_threads_max sysctl kernel.threads-max +# TYPE node_sysctl_kernel_threads_max untyped +node_sysctl_kernel_threads_max 7801 # HELP node_tape_io_now The number of I/Os currently outstanding to this device. # TYPE node_tape_io_now gauge node_tape_io_now{device="st0"} 1 @@ -3132,6 +3207,18 @@ node_textfile_scrape_error 0 # HELP node_thermal_zone_temp Zone temperature in Celsius # TYPE node_thermal_zone_temp gauge node_thermal_zone_temp{type="cpu-thermal",zone="0"} 12.376 +# HELP node_time_clocksource_available_info Available clocksources read from '/sys/devices/system/clocksource'. +# TYPE node_time_clocksource_available_info gauge +node_time_clocksource_available_info{clocksource="acpi_pm",device="0"} 1 +node_time_clocksource_available_info{clocksource="hpet",device="0"} 1 +node_time_clocksource_available_info{clocksource="tsc",device="0"} 1 +# HELP node_time_clocksource_current_info Current clocksource read from '/sys/devices/system/clocksource'. +# TYPE node_time_clocksource_current_info gauge +node_time_clocksource_current_info{clocksource="tsc",device="0"} 1 +# HELP node_time_seconds System time in seconds since epoch (1970). +# TYPE node_time_seconds gauge +# HELP node_time_zone_offset_seconds System time zone offset in seconds. +# TYPE node_time_zone_offset_seconds gauge # HELP node_udp_queues Number of allocated memory in the kernel for UDP datagrams in bytes. # TYPE node_udp_queues gauge node_udp_queues{ip="v4",queue="rx"} 0 @@ -3204,6 +3291,90 @@ node_wifi_station_transmit_failed_total{device="wlan0",mac_address="aa:bb:cc:dd: # TYPE node_wifi_station_transmit_retries_total counter node_wifi_station_transmit_retries_total{device="wlan0",mac_address="01:02:03:04:05:06"} 20 node_wifi_station_transmit_retries_total{device="wlan0",mac_address="aa:bb:cc:dd:ee:ff"} 10 +# HELP node_xfrm_acquire_error_packets_total State hasn’t been fully acquired before use +# TYPE node_xfrm_acquire_error_packets_total counter +node_xfrm_acquire_error_packets_total 24532 +# HELP node_xfrm_fwd_hdr_error_packets_total Forward routing of a packet is not allowed +# TYPE node_xfrm_fwd_hdr_error_packets_total counter +node_xfrm_fwd_hdr_error_packets_total 6654 +# HELP node_xfrm_in_buffer_error_packets_total No buffer is left +# TYPE node_xfrm_in_buffer_error_packets_total counter +node_xfrm_in_buffer_error_packets_total 2 +# HELP node_xfrm_in_error_packets_total All errors not matched by other +# TYPE node_xfrm_in_error_packets_total counter +node_xfrm_in_error_packets_total 1 +# HELP node_xfrm_in_hdr_error_packets_total Header error +# TYPE node_xfrm_in_hdr_error_packets_total counter +node_xfrm_in_hdr_error_packets_total 4 +# HELP node_xfrm_in_no_pols_packets_total No policy is found for states e.g. Inbound SAs are correct but no SP is found +# TYPE node_xfrm_in_no_pols_packets_total counter +node_xfrm_in_no_pols_packets_total 65432 +# HELP node_xfrm_in_no_states_packets_total No state is found i.e. Either inbound SPI, address, or IPsec protocol at SA is wrong +# TYPE node_xfrm_in_no_states_packets_total counter +node_xfrm_in_no_states_packets_total 3 +# HELP node_xfrm_in_pol_block_packets_total Policy discards +# TYPE node_xfrm_in_pol_block_packets_total counter +node_xfrm_in_pol_block_packets_total 100 +# HELP node_xfrm_in_pol_error_packets_total Policy error +# TYPE node_xfrm_in_pol_error_packets_total counter +node_xfrm_in_pol_error_packets_total 10000 +# HELP node_xfrm_in_state_expired_packets_total State is expired +# TYPE node_xfrm_in_state_expired_packets_total counter +node_xfrm_in_state_expired_packets_total 7 +# HELP node_xfrm_in_state_invalid_packets_total State is invalid +# TYPE node_xfrm_in_state_invalid_packets_total counter +node_xfrm_in_state_invalid_packets_total 55555 +# HELP node_xfrm_in_state_mismatch_packets_total State has mismatch option e.g. UDP encapsulation type is mismatch +# TYPE node_xfrm_in_state_mismatch_packets_total counter +node_xfrm_in_state_mismatch_packets_total 23451 +# HELP node_xfrm_in_state_mode_error_packets_total Transformation mode specific error +# TYPE node_xfrm_in_state_mode_error_packets_total counter +node_xfrm_in_state_mode_error_packets_total 100 +# HELP node_xfrm_in_state_proto_error_packets_total Transformation protocol specific error e.g. SA key is wrong +# TYPE node_xfrm_in_state_proto_error_packets_total counter +node_xfrm_in_state_proto_error_packets_total 40 +# HELP node_xfrm_in_state_seq_error_packets_total Sequence error i.e. Sequence number is out of window +# TYPE node_xfrm_in_state_seq_error_packets_total counter +node_xfrm_in_state_seq_error_packets_total 6000 +# HELP node_xfrm_in_tmpl_mismatch_packets_total No matching template for states e.g. Inbound SAs are correct but SP rule is wrong +# TYPE node_xfrm_in_tmpl_mismatch_packets_total counter +node_xfrm_in_tmpl_mismatch_packets_total 51 +# HELP node_xfrm_out_bundle_check_error_packets_total Bundle check error +# TYPE node_xfrm_out_bundle_check_error_packets_total counter +node_xfrm_out_bundle_check_error_packets_total 555 +# HELP node_xfrm_out_bundle_gen_error_packets_total Bundle generation error +# TYPE node_xfrm_out_bundle_gen_error_packets_total counter +node_xfrm_out_bundle_gen_error_packets_total 43321 +# HELP node_xfrm_out_error_packets_total All errors which is not matched others +# TYPE node_xfrm_out_error_packets_total counter +node_xfrm_out_error_packets_total 1e+06 +# HELP node_xfrm_out_no_states_packets_total No state is found +# TYPE node_xfrm_out_no_states_packets_total counter +node_xfrm_out_no_states_packets_total 869 +# HELP node_xfrm_out_pol_block_packets_total Policy discards +# TYPE node_xfrm_out_pol_block_packets_total counter +node_xfrm_out_pol_block_packets_total 43456 +# HELP node_xfrm_out_pol_dead_packets_total Policy is dead +# TYPE node_xfrm_out_pol_dead_packets_total counter +node_xfrm_out_pol_dead_packets_total 7656 +# HELP node_xfrm_out_pol_error_packets_total Policy error +# TYPE node_xfrm_out_pol_error_packets_total counter +node_xfrm_out_pol_error_packets_total 1454 +# HELP node_xfrm_out_state_expired_packets_total State is expired +# TYPE node_xfrm_out_state_expired_packets_total counter +node_xfrm_out_state_expired_packets_total 565 +# HELP node_xfrm_out_state_invalid_packets_total State is invalid, perhaps expired +# TYPE node_xfrm_out_state_invalid_packets_total counter +node_xfrm_out_state_invalid_packets_total 28765 +# HELP node_xfrm_out_state_mode_error_packets_total Transformation mode specific error +# TYPE node_xfrm_out_state_mode_error_packets_total counter +node_xfrm_out_state_mode_error_packets_total 8 +# HELP node_xfrm_out_state_proto_error_packets_total Transformation protocol specific error +# TYPE node_xfrm_out_state_proto_error_packets_total counter +node_xfrm_out_state_proto_error_packets_total 4542 +# HELP node_xfrm_out_state_seq_error_packets_total Sequence error i.e. Sequence number overflow +# TYPE node_xfrm_out_state_seq_error_packets_total counter +node_xfrm_out_state_seq_error_packets_total 543 # HELP node_xfs_allocation_btree_compares_total Number of allocation B-tree compares for a filesystem. # TYPE node_xfs_allocation_btree_compares_total counter node_xfs_allocation_btree_compares_total{device="sda1"} 0 @@ -3657,193 +3828,193 @@ node_zfs_arc_prefetch_metadata_misses 16071 # HELP node_zfs_arc_size kstat.zfs.misc.arcstats.size # TYPE node_zfs_arc_size untyped node_zfs_arc_size 1.603939792e+09 -# HELP node_zfs_dbuf_dbuf_cache_count kstat.zfs.misc.dbuf_stats.dbuf_cache_count +# HELP node_zfs_dbuf_dbuf_cache_count kstat.zfs.misc.dbufstats.dbuf_cache_count # TYPE node_zfs_dbuf_dbuf_cache_count untyped node_zfs_dbuf_dbuf_cache_count 27 -# HELP node_zfs_dbuf_dbuf_cache_hiwater_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_hiwater_bytes +# HELP node_zfs_dbuf_dbuf_cache_hiwater_bytes kstat.zfs.misc.dbufstats.dbuf_cache_hiwater_bytes # TYPE node_zfs_dbuf_dbuf_cache_hiwater_bytes untyped node_zfs_dbuf_dbuf_cache_hiwater_bytes 6.9117804e+07 -# HELP node_zfs_dbuf_dbuf_cache_level_0 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_0 +# HELP node_zfs_dbuf_dbuf_cache_level_0 kstat.zfs.misc.dbufstats.dbuf_cache_level_0 # TYPE node_zfs_dbuf_dbuf_cache_level_0 untyped node_zfs_dbuf_dbuf_cache_level_0 27 -# HELP node_zfs_dbuf_dbuf_cache_level_0_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_0_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_0_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_0_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_0_bytes untyped node_zfs_dbuf_dbuf_cache_level_0_bytes 302080 -# HELP node_zfs_dbuf_dbuf_cache_level_1 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_1 +# HELP node_zfs_dbuf_dbuf_cache_level_1 kstat.zfs.misc.dbufstats.dbuf_cache_level_1 # TYPE node_zfs_dbuf_dbuf_cache_level_1 untyped node_zfs_dbuf_dbuf_cache_level_1 0 -# HELP node_zfs_dbuf_dbuf_cache_level_10 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_10 +# HELP node_zfs_dbuf_dbuf_cache_level_10 kstat.zfs.misc.dbufstats.dbuf_cache_level_10 # TYPE node_zfs_dbuf_dbuf_cache_level_10 untyped node_zfs_dbuf_dbuf_cache_level_10 0 -# HELP node_zfs_dbuf_dbuf_cache_level_10_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_10_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_10_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_10_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_10_bytes untyped node_zfs_dbuf_dbuf_cache_level_10_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_11 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_11 +# HELP node_zfs_dbuf_dbuf_cache_level_11 kstat.zfs.misc.dbufstats.dbuf_cache_level_11 # TYPE node_zfs_dbuf_dbuf_cache_level_11 untyped node_zfs_dbuf_dbuf_cache_level_11 0 -# HELP node_zfs_dbuf_dbuf_cache_level_11_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_11_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_11_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_11_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_11_bytes untyped node_zfs_dbuf_dbuf_cache_level_11_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_1_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_1_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_1_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_1_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_1_bytes untyped node_zfs_dbuf_dbuf_cache_level_1_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_2 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_2 +# HELP node_zfs_dbuf_dbuf_cache_level_2 kstat.zfs.misc.dbufstats.dbuf_cache_level_2 # TYPE node_zfs_dbuf_dbuf_cache_level_2 untyped node_zfs_dbuf_dbuf_cache_level_2 0 -# HELP node_zfs_dbuf_dbuf_cache_level_2_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_2_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_2_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_2_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_2_bytes untyped node_zfs_dbuf_dbuf_cache_level_2_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_3 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_3 +# HELP node_zfs_dbuf_dbuf_cache_level_3 kstat.zfs.misc.dbufstats.dbuf_cache_level_3 # TYPE node_zfs_dbuf_dbuf_cache_level_3 untyped node_zfs_dbuf_dbuf_cache_level_3 0 -# HELP node_zfs_dbuf_dbuf_cache_level_3_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_3_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_3_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_3_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_3_bytes untyped node_zfs_dbuf_dbuf_cache_level_3_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_4 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_4 +# HELP node_zfs_dbuf_dbuf_cache_level_4 kstat.zfs.misc.dbufstats.dbuf_cache_level_4 # TYPE node_zfs_dbuf_dbuf_cache_level_4 untyped node_zfs_dbuf_dbuf_cache_level_4 0 -# HELP node_zfs_dbuf_dbuf_cache_level_4_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_4_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_4_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_4_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_4_bytes untyped node_zfs_dbuf_dbuf_cache_level_4_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_5 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_5 +# HELP node_zfs_dbuf_dbuf_cache_level_5 kstat.zfs.misc.dbufstats.dbuf_cache_level_5 # TYPE node_zfs_dbuf_dbuf_cache_level_5 untyped node_zfs_dbuf_dbuf_cache_level_5 0 -# HELP node_zfs_dbuf_dbuf_cache_level_5_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_5_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_5_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_5_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_5_bytes untyped node_zfs_dbuf_dbuf_cache_level_5_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_6 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_6 +# HELP node_zfs_dbuf_dbuf_cache_level_6 kstat.zfs.misc.dbufstats.dbuf_cache_level_6 # TYPE node_zfs_dbuf_dbuf_cache_level_6 untyped node_zfs_dbuf_dbuf_cache_level_6 0 -# HELP node_zfs_dbuf_dbuf_cache_level_6_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_6_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_6_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_6_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_6_bytes untyped node_zfs_dbuf_dbuf_cache_level_6_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_7 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_7 +# HELP node_zfs_dbuf_dbuf_cache_level_7 kstat.zfs.misc.dbufstats.dbuf_cache_level_7 # TYPE node_zfs_dbuf_dbuf_cache_level_7 untyped node_zfs_dbuf_dbuf_cache_level_7 0 -# HELP node_zfs_dbuf_dbuf_cache_level_7_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_7_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_7_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_7_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_7_bytes untyped node_zfs_dbuf_dbuf_cache_level_7_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_8 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_8 +# HELP node_zfs_dbuf_dbuf_cache_level_8 kstat.zfs.misc.dbufstats.dbuf_cache_level_8 # TYPE node_zfs_dbuf_dbuf_cache_level_8 untyped node_zfs_dbuf_dbuf_cache_level_8 0 -# HELP node_zfs_dbuf_dbuf_cache_level_8_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_8_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_8_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_8_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_8_bytes untyped node_zfs_dbuf_dbuf_cache_level_8_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_level_9 kstat.zfs.misc.dbuf_stats.dbuf_cache_level_9 +# HELP node_zfs_dbuf_dbuf_cache_level_9 kstat.zfs.misc.dbufstats.dbuf_cache_level_9 # TYPE node_zfs_dbuf_dbuf_cache_level_9 untyped node_zfs_dbuf_dbuf_cache_level_9 0 -# HELP node_zfs_dbuf_dbuf_cache_level_9_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_level_9_bytes +# HELP node_zfs_dbuf_dbuf_cache_level_9_bytes kstat.zfs.misc.dbufstats.dbuf_cache_level_9_bytes # TYPE node_zfs_dbuf_dbuf_cache_level_9_bytes untyped node_zfs_dbuf_dbuf_cache_level_9_bytes 0 -# HELP node_zfs_dbuf_dbuf_cache_lowater_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_lowater_bytes +# HELP node_zfs_dbuf_dbuf_cache_lowater_bytes kstat.zfs.misc.dbufstats.dbuf_cache_lowater_bytes # TYPE node_zfs_dbuf_dbuf_cache_lowater_bytes untyped node_zfs_dbuf_dbuf_cache_lowater_bytes 5.6550932e+07 -# HELP node_zfs_dbuf_dbuf_cache_max_bytes kstat.zfs.misc.dbuf_stats.dbuf_cache_max_bytes +# HELP node_zfs_dbuf_dbuf_cache_max_bytes kstat.zfs.misc.dbufstats.dbuf_cache_max_bytes # TYPE node_zfs_dbuf_dbuf_cache_max_bytes untyped node_zfs_dbuf_dbuf_cache_max_bytes 6.2834368e+07 -# HELP node_zfs_dbuf_dbuf_cache_size kstat.zfs.misc.dbuf_stats.dbuf_cache_size +# HELP node_zfs_dbuf_dbuf_cache_size kstat.zfs.misc.dbufstats.dbuf_cache_size # TYPE node_zfs_dbuf_dbuf_cache_size untyped node_zfs_dbuf_dbuf_cache_size 302080 -# HELP node_zfs_dbuf_dbuf_cache_size_max kstat.zfs.misc.dbuf_stats.dbuf_cache_size_max +# HELP node_zfs_dbuf_dbuf_cache_size_max kstat.zfs.misc.dbufstats.dbuf_cache_size_max # TYPE node_zfs_dbuf_dbuf_cache_size_max untyped node_zfs_dbuf_dbuf_cache_size_max 394240 -# HELP node_zfs_dbuf_dbuf_cache_total_evicts kstat.zfs.misc.dbuf_stats.dbuf_cache_total_evicts +# HELP node_zfs_dbuf_dbuf_cache_total_evicts kstat.zfs.misc.dbufstats.dbuf_cache_total_evicts # TYPE node_zfs_dbuf_dbuf_cache_total_evicts untyped node_zfs_dbuf_dbuf_cache_total_evicts 0 -# HELP node_zfs_dbuf_hash_chain_max kstat.zfs.misc.dbuf_stats.hash_chain_max +# HELP node_zfs_dbuf_hash_chain_max kstat.zfs.misc.dbufstats.hash_chain_max # TYPE node_zfs_dbuf_hash_chain_max untyped node_zfs_dbuf_hash_chain_max 0 -# HELP node_zfs_dbuf_hash_chains kstat.zfs.misc.dbuf_stats.hash_chains +# HELP node_zfs_dbuf_hash_chains kstat.zfs.misc.dbufstats.hash_chains # TYPE node_zfs_dbuf_hash_chains untyped node_zfs_dbuf_hash_chains 0 -# HELP node_zfs_dbuf_hash_collisions kstat.zfs.misc.dbuf_stats.hash_collisions +# HELP node_zfs_dbuf_hash_collisions kstat.zfs.misc.dbufstats.hash_collisions # TYPE node_zfs_dbuf_hash_collisions untyped node_zfs_dbuf_hash_collisions 0 -# HELP node_zfs_dbuf_hash_dbuf_level_0 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_0 +# HELP node_zfs_dbuf_hash_dbuf_level_0 kstat.zfs.misc.dbufstats.hash_dbuf_level_0 # TYPE node_zfs_dbuf_hash_dbuf_level_0 untyped node_zfs_dbuf_hash_dbuf_level_0 37 -# HELP node_zfs_dbuf_hash_dbuf_level_0_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_0_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_0_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_0_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_0_bytes untyped node_zfs_dbuf_hash_dbuf_level_0_bytes 465920 -# HELP node_zfs_dbuf_hash_dbuf_level_1 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_1 +# HELP node_zfs_dbuf_hash_dbuf_level_1 kstat.zfs.misc.dbufstats.hash_dbuf_level_1 # TYPE node_zfs_dbuf_hash_dbuf_level_1 untyped node_zfs_dbuf_hash_dbuf_level_1 10 -# HELP node_zfs_dbuf_hash_dbuf_level_10 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_10 +# HELP node_zfs_dbuf_hash_dbuf_level_10 kstat.zfs.misc.dbufstats.hash_dbuf_level_10 # TYPE node_zfs_dbuf_hash_dbuf_level_10 untyped node_zfs_dbuf_hash_dbuf_level_10 0 -# HELP node_zfs_dbuf_hash_dbuf_level_10_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_10_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_10_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_10_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_10_bytes untyped node_zfs_dbuf_hash_dbuf_level_10_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_11 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_11 +# HELP node_zfs_dbuf_hash_dbuf_level_11 kstat.zfs.misc.dbufstats.hash_dbuf_level_11 # TYPE node_zfs_dbuf_hash_dbuf_level_11 untyped node_zfs_dbuf_hash_dbuf_level_11 0 -# HELP node_zfs_dbuf_hash_dbuf_level_11_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_11_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_11_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_11_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_11_bytes untyped node_zfs_dbuf_hash_dbuf_level_11_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_1_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_1_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_1_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_1_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_1_bytes untyped node_zfs_dbuf_hash_dbuf_level_1_bytes 1.31072e+06 -# HELP node_zfs_dbuf_hash_dbuf_level_2 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_2 +# HELP node_zfs_dbuf_hash_dbuf_level_2 kstat.zfs.misc.dbufstats.hash_dbuf_level_2 # TYPE node_zfs_dbuf_hash_dbuf_level_2 untyped node_zfs_dbuf_hash_dbuf_level_2 2 -# HELP node_zfs_dbuf_hash_dbuf_level_2_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_2_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_2_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_2_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_2_bytes untyped node_zfs_dbuf_hash_dbuf_level_2_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_3 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_3 +# HELP node_zfs_dbuf_hash_dbuf_level_3 kstat.zfs.misc.dbufstats.hash_dbuf_level_3 # TYPE node_zfs_dbuf_hash_dbuf_level_3 untyped node_zfs_dbuf_hash_dbuf_level_3 2 -# HELP node_zfs_dbuf_hash_dbuf_level_3_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_3_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_3_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_3_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_3_bytes untyped node_zfs_dbuf_hash_dbuf_level_3_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_4 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_4 +# HELP node_zfs_dbuf_hash_dbuf_level_4 kstat.zfs.misc.dbufstats.hash_dbuf_level_4 # TYPE node_zfs_dbuf_hash_dbuf_level_4 untyped node_zfs_dbuf_hash_dbuf_level_4 2 -# HELP node_zfs_dbuf_hash_dbuf_level_4_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_4_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_4_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_4_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_4_bytes untyped node_zfs_dbuf_hash_dbuf_level_4_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_5 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_5 +# HELP node_zfs_dbuf_hash_dbuf_level_5 kstat.zfs.misc.dbufstats.hash_dbuf_level_5 # TYPE node_zfs_dbuf_hash_dbuf_level_5 untyped node_zfs_dbuf_hash_dbuf_level_5 2 -# HELP node_zfs_dbuf_hash_dbuf_level_5_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_5_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_5_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_5_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_5_bytes untyped node_zfs_dbuf_hash_dbuf_level_5_bytes 262144 -# HELP node_zfs_dbuf_hash_dbuf_level_6 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_6 +# HELP node_zfs_dbuf_hash_dbuf_level_6 kstat.zfs.misc.dbufstats.hash_dbuf_level_6 # TYPE node_zfs_dbuf_hash_dbuf_level_6 untyped node_zfs_dbuf_hash_dbuf_level_6 0 -# HELP node_zfs_dbuf_hash_dbuf_level_6_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_6_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_6_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_6_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_6_bytes untyped node_zfs_dbuf_hash_dbuf_level_6_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_7 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_7 +# HELP node_zfs_dbuf_hash_dbuf_level_7 kstat.zfs.misc.dbufstats.hash_dbuf_level_7 # TYPE node_zfs_dbuf_hash_dbuf_level_7 untyped node_zfs_dbuf_hash_dbuf_level_7 0 -# HELP node_zfs_dbuf_hash_dbuf_level_7_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_7_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_7_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_7_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_7_bytes untyped node_zfs_dbuf_hash_dbuf_level_7_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_8 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_8 +# HELP node_zfs_dbuf_hash_dbuf_level_8 kstat.zfs.misc.dbufstats.hash_dbuf_level_8 # TYPE node_zfs_dbuf_hash_dbuf_level_8 untyped node_zfs_dbuf_hash_dbuf_level_8 0 -# HELP node_zfs_dbuf_hash_dbuf_level_8_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_8_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_8_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_8_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_8_bytes untyped node_zfs_dbuf_hash_dbuf_level_8_bytes 0 -# HELP node_zfs_dbuf_hash_dbuf_level_9 kstat.zfs.misc.dbuf_stats.hash_dbuf_level_9 +# HELP node_zfs_dbuf_hash_dbuf_level_9 kstat.zfs.misc.dbufstats.hash_dbuf_level_9 # TYPE node_zfs_dbuf_hash_dbuf_level_9 untyped node_zfs_dbuf_hash_dbuf_level_9 0 -# HELP node_zfs_dbuf_hash_dbuf_level_9_bytes kstat.zfs.misc.dbuf_stats.hash_dbuf_level_9_bytes +# HELP node_zfs_dbuf_hash_dbuf_level_9_bytes kstat.zfs.misc.dbufstats.hash_dbuf_level_9_bytes # TYPE node_zfs_dbuf_hash_dbuf_level_9_bytes untyped node_zfs_dbuf_hash_dbuf_level_9_bytes 0 -# HELP node_zfs_dbuf_hash_elements kstat.zfs.misc.dbuf_stats.hash_elements +# HELP node_zfs_dbuf_hash_elements kstat.zfs.misc.dbufstats.hash_elements # TYPE node_zfs_dbuf_hash_elements untyped node_zfs_dbuf_hash_elements 55 -# HELP node_zfs_dbuf_hash_elements_max kstat.zfs.misc.dbuf_stats.hash_elements_max +# HELP node_zfs_dbuf_hash_elements_max kstat.zfs.misc.dbufstats.hash_elements_max # TYPE node_zfs_dbuf_hash_elements_max untyped node_zfs_dbuf_hash_elements_max 55 -# HELP node_zfs_dbuf_hash_hits kstat.zfs.misc.dbuf_stats.hash_hits +# HELP node_zfs_dbuf_hash_hits kstat.zfs.misc.dbufstats.hash_hits # TYPE node_zfs_dbuf_hash_hits untyped node_zfs_dbuf_hash_hits 108807 -# HELP node_zfs_dbuf_hash_insert_race kstat.zfs.misc.dbuf_stats.hash_insert_race +# HELP node_zfs_dbuf_hash_insert_race kstat.zfs.misc.dbufstats.hash_insert_race # TYPE node_zfs_dbuf_hash_insert_race untyped node_zfs_dbuf_hash_insert_race 0 -# HELP node_zfs_dbuf_hash_misses kstat.zfs.misc.dbuf_stats.hash_misses +# HELP node_zfs_dbuf_hash_misses kstat.zfs.misc.dbufstats.hash_misses # TYPE node_zfs_dbuf_hash_misses untyped node_zfs_dbuf_hash_misses 1851 # HELP node_zfs_dmu_tx_dmu_tx_assigned kstat.zfs.misc.dmu_tx.dmu_tx_assigned @@ -4162,16 +4333,25 @@ node_zfs_zpool_rupdate{zpool="poolz1"} 1.10734831944501e+14 # HELP node_zfs_zpool_state kstat.zfs.misc.state # TYPE node_zfs_zpool_state gauge node_zfs_zpool_state{state="degraded",zpool="pool1"} 0 +node_zfs_zpool_state{state="degraded",zpool="pool2"} 0 node_zfs_zpool_state{state="degraded",zpool="poolz1"} 1 node_zfs_zpool_state{state="faulted",zpool="pool1"} 0 +node_zfs_zpool_state{state="faulted",zpool="pool2"} 0 node_zfs_zpool_state{state="faulted",zpool="poolz1"} 0 node_zfs_zpool_state{state="offline",zpool="pool1"} 0 +node_zfs_zpool_state{state="offline",zpool="pool2"} 0 node_zfs_zpool_state{state="offline",zpool="poolz1"} 0 node_zfs_zpool_state{state="online",zpool="pool1"} 1 +node_zfs_zpool_state{state="online",zpool="pool2"} 0 node_zfs_zpool_state{state="online",zpool="poolz1"} 0 node_zfs_zpool_state{state="removed",zpool="pool1"} 0 +node_zfs_zpool_state{state="removed",zpool="pool2"} 0 node_zfs_zpool_state{state="removed",zpool="poolz1"} 0 +node_zfs_zpool_state{state="suspended",zpool="pool1"} 0 +node_zfs_zpool_state{state="suspended",zpool="pool2"} 1 +node_zfs_zpool_state{state="suspended",zpool="poolz1"} 0 node_zfs_zpool_state{state="unavail",zpool="pool1"} 0 +node_zfs_zpool_state{state="unavail",zpool="pool2"} 0 node_zfs_zpool_state{state="unavail",zpool="poolz1"} 0 # HELP node_zfs_zpool_wcnt kstat.zfs.misc.io.wcnt # TYPE node_zfs_zpool_wcnt untyped diff --git a/collector/fixtures/ethtool/eth0/statistics b/collector/fixtures/ethtool/eth0/statistics index 9ce7e015e5..80423bd6c3 100644 --- a/collector/fixtures/ethtool/eth0/statistics +++ b/collector/fixtures/ethtool/eth0/statistics @@ -13,3 +13,5 @@ NIC statistics: rx_multicast: 23973 tx_aborted: 0 tx_underrun: 0 + duplicate metric: 1 + duplicate_metric: 2 diff --git a/collector/fixtures/proc/cgroups b/collector/fixtures/proc/cgroups new file mode 100644 index 0000000000..99382e312e --- /dev/null +++ b/collector/fixtures/proc/cgroups @@ -0,0 +1,13 @@ +#subsys_name hierarchy num_cgroups enabled +cpuset 5 47 1 +cpu 3 172 1 +cpuacct 3 172 1 +blkio 6 170 1 +memory 7 234 1 +devices 11 170 1 +freezer 9 47 1 +net_cls 2 47 1 +perf_event 8 47 1 +hugetlb 12 47 1 +pids 10 170 1 +rdma 4 1 1 \ No newline at end of file diff --git a/collector/fixtures/proc/diskstats b/collector/fixtures/proc/diskstats index 3a75de515b..0fb024e537 100644 --- a/collector/fixtures/proc/diskstats +++ b/collector/fixtures/proc/diskstats @@ -44,8 +44,8 @@ 259 0 nvme0n1 47114 4 4643973 21650 1078320 43950 39451633 1011053 0 222766 1032546 259 1 nvme0n1p1 1140 0 9370 16 1 0 1 0 0 16 16 259 2 nvme0n1p2 45914 4 4631243 21626 1036885 43950 39451632 919480 0 131580 940970 - 8 0 sdb 326552 841 9657779 84 41822 2895 1972905 5007 0 60730 67070 68851 0 1925173784 11130 - 8 1 sdb1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0 - 8 2 sdb2 326310 838 9622281 67 40726 2872 1972799 4924 0 58250 64567 68851 0 1925173784 11130 - 8 0 sdc 126552 141 1657779 14 11822 1895 172905 1007 0 10730 17070 18851 0 125173784 11130 1555 1944 - 8 1 sdc1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0 0 0 + 8 16 sdb 326552 841 9657779 84 41822 2895 1972905 5007 0 60730 67070 68851 0 1925173784 11130 + 8 17 sdb1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0 + 8 18 sdb2 326310 838 9622281 67 40726 2872 1972799 4924 0 58250 64567 68851 0 1925173784 11130 + 8 32 sdc 126552 141 1657779 14 11822 1895 172905 1007 0 10730 17070 18851 0 125173784 11130 1555 1944 + 8 33 sdc1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0 0 0 diff --git a/collector/fixtures/proc/interrupts_aarch64 b/collector/fixtures/proc/interrupts_aarch64 new file mode 100644 index 0000000000..88f2dea7e2 --- /dev/null +++ b/collector/fixtures/proc/interrupts_aarch64 @@ -0,0 +1,61 @@ + CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7 + 10: 3287008667 3310445093 3301386305 3273132897 3368262064 3641875466 3360412019 3225020442 GICv3 27 Level arch_timer + 14: 7815 0 0 4 0 0 0 0 GICv3 37 Level ttyS0 + 17: 0 0 0 0 0 0 0 0 GICv3 48 Edge ACPI:Ged + 18: 0 0 0 0 0 0 0 0 GICv3 49 Edge ACPI:Ged + 19: 0 0 0 0 0 0 0 0 GICv3 50 Edge ACPI:Ged + 20: 0 0 0 0 0 0 0 0 GICv3 51 Edge ACPI:Ged + 21: 0 0 0 0 0 0 0 0 GICv3 52 Edge ACPI:Ged + 22: 0 0 0 0 0 0 0 0 GICv3 53 Edge ACPI:Ged + 23: 0 0 0 0 0 0 0 0 GICv3 54 Edge ACPI:Ged + 24: 0 0 0 0 0 0 0 0 GICv3 55 Edge ACPI:Ged + 25: 0 0 0 0 0 0 0 0 GICv3 56 Edge ACPI:Ged + 26: 0 0 0 0 0 0 0 0 GICv3 57 Edge ACPI:Ged + 27: 0 0 0 0 0 0 0 0 GICv3 58 Edge ACPI:Ged + 28: 0 0 0 0 0 0 0 0 GICv3 59 Edge ACPI:Ged + 29: 0 0 0 0 0 0 0 0 GICv3 60 Edge ACPI:Ged + 30: 0 0 0 0 0 0 0 0 GICv3 61 Edge ACPI:Ged + 31: 0 0 0 0 0 0 0 0 GICv3 62 Edge ACPI:Ged + 32: 0 0 0 0 0 0 0 0 GICv3 63 Edge ACPI:Ged + 33: 0 0 0 0 0 0 0 0 GICv3 64 Edge ACPI:Ged + 34: 0 0 0 0 0 0 0 0 GICv3 65 Edge ACPI:Ged + 35: 0 0 0 0 0 0 0 0 GICv3 66 Edge ACPI:Ged + 36: 0 0 0 0 0 0 0 0 GICv3 67 Edge ACPI:Ged + 37: 0 0 0 0 0 0 0 0 GICv3 68 Edge ACPI:Ged + 38: 0 0 0 0 0 0 0 0 GICv3 69 Edge ACPI:Ged + 39: 0 0 0 0 0 0 0 0 GICv3 70 Edge ACPI:Ged + 40: 0 0 0 0 0 0 0 0 GICv3 71 Edge ACPI:Ged + 41: 0 0 0 0 0 0 0 0 GICv3 72 Edge ACPI:Ged + 42: 0 0 0 0 0 0 0 0 GICv3 73 Edge ACPI:Ged + 43: 0 0 0 0 0 0 0 0 GICv3 74 Edge ACPI:Ged + 44: 0 0 0 0 0 0 0 0 GICv3 75 Edge ACPI:Ged + 45: 0 0 0 0 0 0 0 0 GICv3 76 Edge ACPI:Ged + 46: 0 0 0 0 0 0 0 0 GICv3 77 Edge ACPI:Ged + 47: 0 0 0 0 0 0 0 0 GICv3 78 Edge ACPI:Ged + 48: 0 0 0 0 0 0 0 0 GICv3 79 Edge ACPI:Ged + 49: 0 0 0 0 0 0 0 0 GICv3 23 Level arm-pmu + 50: 0 0 0 0 0 0 0 0 ARMH0061:00 3 Edge ACPI:Event + 51: 13 0 0 20 4 0 0 0 ITS-MSI 65536 Edge nvme0q0 + 52: 0 9 0 0 0 5 20 0 ITS-MSI 507904 Edge nvme1q0 + 53: 129969327 0 0 0 0 0 0 0 ITS-MSI 65537 Edge nvme0q1 + 54: 0 0 0 0 126913956 0 0 0 ITS-MSI 65538 Edge nvme0q2 + 55: 0 199619844 0 0 0 0 0 0 ITS-MSI 507905 Edge nvme1q1 + 56: 0 0 0 0 0 198494086 0 0 ITS-MSI 507906 Edge nvme1q2 + 57: 0 0 51 0 0 32479308 0 0 ITS-MSI 81920 Edge ena-mgmnt@pci:0000:00:05.0 + 58: 0 0 1195697946 437 0 0 0 0 ITS-MSI 81921 Edge eth0-Tx-Rx-0 + 59: 0 0 0 2709937608 1619 0 0 0 ITS-MSI 81922 Edge eth0-Tx-Rx-1 + 60: 0 1457922109 0 0 0 71 0 0 ITS-MSI 81923 Edge eth0-Tx-Rx-2 + 61: 2052879736 0 0 0 0 0 124 0 ITS-MSI 81924 Edge eth0-Tx-Rx-3 + 62: 0 0 0 0 0 0 2268695629 1530 ITS-MSI 81925 Edge eth0-Tx-Rx-4 + 63: 50 0 0 0 0 0 0 1997799253 ITS-MSI 81926 Edge eth0-Tx-Rx-5 + 64: 0 48 0 0 1238622585 0 0 0 ITS-MSI 81927 Edge eth0-Tx-Rx-6 + 65: 0 0 47 0 0 0 0 1574978449 ITS-MSI 81928 Edge eth0-Tx-Rx-7 +IPI0:2768808080 2844211768 2878602432 2730576120 2723524623 3349096412 2717389879 2154252810 Rescheduling interrupts +IPI1: 357815098 213258177 153713187 132890624 124746406 123498004 122386326 120728639 Function call interrupts +IPI2: 0 0 0 0 0 0 0 0 CPU stop interrupts +IPI3: 0 0 0 0 0 0 0 0 CPU stop (for crash dump) interrupts +IPI4: 0 0 0 0 0 0 0 0 Timer broadcast interrupts +IPI5: 0 0 0 0 0 0 0 0 IRQ work interrupts +IPI6: 0 0 0 0 0 0 0 0 CPU wake-up interrupts +Err: 0 + diff --git a/collector/fixtures/proc/net/arp b/collector/fixtures/proc/net/arp index 84c67f8c00..3b9e4e7661 100644 --- a/collector/fixtures/proc/net/arp +++ b/collector/fixtures/proc/net/arp @@ -5,3 +5,4 @@ IP address HW type Flags HW address Mask Device 192.168.1.4 0x1 0x2 dd:ee:ff:aa:bb:cc * eth1 192.168.1.5 0x1 0x2 ee:ff:aa:bb:cc:dd * eth1 192.168.1.6 0x1 0x2 ff:aa:bb:cc:dd:ee * eth1 +10.0.0.1 0x1 0x2 de:ad:be:ef:00:00 * nope diff --git a/collector/fixtures/proc/net/dev b/collector/fixtures/proc/net/dev deleted file mode 100644 index a3534c1309..0000000000 --- a/collector/fixtures/proc/net/dev +++ /dev/null @@ -1,12 +0,0 @@ -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed - tun0: 1888 24 0 0 0 0 0 0 67120 934 0 0 0 0 0 0 -veth4B09XN: 648 8 0 0 0 0 0 0 1943284 10640 0 0 0 0 0 0 - lo: 435303245 1832522 0 0 0 0 0 0 435303245 1832522 0 0 0 0 0 0 - eth0:68210035552 520993275 0 0 0 0 0 0 9315587528 43451486 0 0 0 0 0 0 -lxcbr0: 0 0 0 0 0 0 0 0 2630299 28339 0 0 0 0 0 0 - wlan0: 10437182923 13899359 0 0 0 0 0 0 2851649360 11726200 0 0 0 0 0 0 -docker0: 64910168 1065585 0 0 0 0 0 0 2681662018 1929779 0 0 0 0 0 0 -ibr10:30: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -flannel.1: 18144009813 228499337 0 0 0 0 0 0 20758990068 258369223 0 64 0 0 0 0 - 💩0: 57750104 105557 0 0 0 0 0 72 404570255 304261 0 0 0 0 0 0 diff --git a/collector/fixtures/proc/net/netstat b/collector/fixtures/proc/net/netstat index 811f623273..de88470bdd 100644 --- a/collector/fixtures/proc/net/netstat +++ b/collector/fixtures/proc/net/netstat @@ -1,4 +1,4 @@ -TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSPassive PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPPrequeued TCPDirectCopyFromBacklog TCPDirectCopyFromPrequeue TCPPrequeueDropped TCPHPHits TCPHPHitsToUser TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLoss TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans TCPTimeouts TCPRenoRecoveryFail TCPSackRecoveryFail TCPSchedulerFailed TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures TCPSACKDiscard TCPDSACKIgnoredOld TCPDSACKIgnoredNoUndo TCPSpuriousRTOs TCPMD5NotFound TCPMD5Unexpected TCPSackShifted TCPSackMerged TCPSackShiftFallback TCPBacklogDrop TCPMinTTLDrop TCPDeferAcceptDrop IPReversePathFilter TCPTimeWaitOverflow TCPReqQFullDoCookies TCPReqQFullDrop TCPChallengeACK TCPSYNChallenge -TcpExt: 0 0 2 0 0 0 0 0 0 0 388812 0 0 0 0 6 102471 17 9 0 0 80568 0 168808 0 4471289 26 1433940 3744565 0 1 0 0 0 0 0 0 0 0 48 0 0 0 1 0 1 0 1 115 0 0 0 0 9 0 5 0 41 4 0 0 0 0 0 0 0 1 0 0 0 0 2 5 0 0 0 0 0 0 0 2 2 +TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSPassive PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPPrequeued TCPDirectCopyFromBacklog TCPDirectCopyFromPrequeue TCPPrequeueDropped TCPHPHits TCPHPHitsToUser TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLoss TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans TCPTimeouts TCPRenoRecoveryFail TCPSackRecoveryFail TCPSchedulerFailed TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures TCPSACKDiscard TCPDSACKIgnoredOld TCPDSACKIgnoredNoUndo TCPSpuriousRTOs TCPMD5NotFound TCPMD5Unexpected TCPSackShifted TCPSackMerged TCPSackShiftFallback TCPBacklogDrop TCPMinTTLDrop TCPDeferAcceptDrop IPReversePathFilter TCPTimeWaitOverflow TCPReqQFullDoCookies TCPReqQFullDrop TCPChallengeACK TCPSYNChallenge TCPOFOQueue +TcpExt: 0 0 2 0 0 0 0 0 0 0 388812 0 0 0 0 6 102471 17 9 0 0 80568 0 168808 0 4471289 26 1433940 3744565 0 1 0 0 0 0 0 0 0 0 48 0 0 0 1 0 1 0 1 115 0 0 0 0 9 0 5 0 41 4 0 0 0 0 0 0 0 1 0 0 0 0 2 5 0 0 0 0 0 0 0 2 2 42 IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets IpExt: 0 0 0 0 0 0 6286396970 2786264347 0 0 0 0 diff --git a/collector/fixtures/proc/net/rpc/nfsd b/collector/fixtures/proc/net/rpc/nfsd index 754f19d9d5..6a092bfd30 100644 --- a/collector/fixtures/proc/net/rpc/nfsd +++ b/collector/fixtures/proc/net/rpc/nfsd @@ -9,3 +9,4 @@ proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 proc4 2 2 10853 proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +wdeleg_getattr 15 diff --git a/collector/fixtures/proc/net/tcpstat b/collector/fixtures/proc/net/tcpstat deleted file mode 100644 index 352c00bbf3..0000000000 --- a/collector/fixtures/proc/net/tcpstat +++ /dev/null @@ -1,3 +0,0 @@ - sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - 0: 00000000:0016 00000000:0000 0A 00000015:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 1: 0F02000A:0016 0202000A:8B6B 01 00000015:00000001 02:000AC99B 00000000 0 0 3652 4 ffff88003d3ae040 21 4 31 47 46 diff --git a/collector/fixtures/proc/net/xfrm_stat b/collector/fixtures/proc/net/xfrm_stat new file mode 100644 index 0000000000..970c3e4ded --- /dev/null +++ b/collector/fixtures/proc/net/xfrm_stat @@ -0,0 +1,28 @@ +XfrmInError 1 +XfrmInBufferError 2 +XfrmInHdrError 4 +XfrmInNoStates 3 +XfrmInStateProtoError 40 +XfrmInStateModeError 100 +XfrmInStateSeqError 6000 +XfrmInStateExpired 7 +XfrmInStateMismatch 23451 +XfrmInStateInvalid 55555 +XfrmInTmplMismatch 51 +XfrmInNoPols 65432 +XfrmInPolBlock 100 +XfrmInPolError 10000 +XfrmOutError 1000000 +XfrmOutBundleGenError 43321 +XfrmOutBundleCheckError 555 +XfrmOutNoStates 869 +XfrmOutStateProtoError 4542 +XfrmOutStateModeError 8 +XfrmOutStateSeqError 543 +XfrmOutStateExpired 565 +XfrmOutPolBlock 43456 +XfrmOutPolDead 7656 +XfrmOutPolError 1454 +XfrmFwdHdrError 6654 +XfrmOutStateInvalid 28765 +XfrmAcquireError 24532 \ No newline at end of file diff --git a/collector/fixtures/proc/slabinfo b/collector/fixtures/proc/slabinfo new file mode 100644 index 0000000000..8f2de4ba11 --- /dev/null +++ b/collector/fixtures/proc/slabinfo @@ -0,0 +1,6 @@ +slabinfo - version: 2.1 +# name : tunables : slabdata +tw_sock_TCP 704 864 256 32 2 : tunables 0 0 0 : slabdata 27 27 0 +dmaengine-unmap-128 1206 1320 1088 30 8 : tunables 0 0 0 : slabdata 44 44 0 +kmalloc-8192 132 148 8192 4 8 : tunables 0 0 0 : slabdata 37 37 0 +kmem_cache 320 320 256 32 2 : tunables 0 0 0 : slabdata 10 10 0 diff --git a/collector/fixtures/proc/softirqs b/collector/fixtures/proc/softirqs new file mode 100644 index 0000000000..a1dfef5ffe --- /dev/null +++ b/collector/fixtures/proc/softirqs @@ -0,0 +1,11 @@ + CPU0 CPU1 + HI: 7 1 + TIMER: 424191 108342 + NET_TX: 2301 2430 + NET_RX: 43066 104508 + BLOCK: 23776 24115 + IRQ_POLL: 0 0 + TASKLET: 372 1899 + SCHED: 378895 152852 + HRTIMER: 40 346 + RCU: 155929 146631 diff --git a/collector/fixtures/proc/spl/kstat/zfs/dbuf_stats b/collector/fixtures/proc/spl/kstat/zfs/dbufstats similarity index 100% rename from collector/fixtures/proc/spl/kstat/zfs/dbuf_stats rename to collector/fixtures/proc/spl/kstat/zfs/dbufstats diff --git a/collector/fixtures/proc/spl/kstat/zfs/pool2/state b/collector/fixtures/proc/spl/kstat/zfs/pool2/state new file mode 100644 index 0000000000..c3ddd0e661 --- /dev/null +++ b/collector/fixtures/proc/spl/kstat/zfs/pool2/state @@ -0,0 +1 @@ +SUSPENDED diff --git a/collector/fixtures/proc/sys/kernel/seccomp/actions_avail b/collector/fixtures/proc/sys/kernel/seccomp/actions_avail new file mode 100644 index 0000000000..a608f9fd07 --- /dev/null +++ b/collector/fixtures/proc/sys/kernel/seccomp/actions_avail @@ -0,0 +1 @@ +kill_process kill_thread trap errno user_notif trace log allow diff --git a/collector/fixtures/sys.ttar b/collector/fixtures/sys.ttar index 6e9ebe51ef..213c8b3867 100644 --- a/collector/fixtures/sys.ttar +++ b/collector/fixtures/sys.ttar @@ -141,7 +141,7 @@ Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/class/dmi/id/product_version Lines: 1 - +�[� Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/class/dmi/id/sys_vendor @@ -356,6 +356,9 @@ Lines: 1 100000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/hwmon/hwmon5 +SymlinkTo: ../../devices/platform/bogus.0/hwmon/hwmon5/ +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/class/infiniband Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1440,7 +1443,7 @@ Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/class/power_supply/BAT0/model_name Lines: 1 -LNV-45N1ÀÀ +LNV-45N1�� Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/class/power_supply/BAT0/power @@ -2396,7 +2399,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute @@ -2439,7 +2442,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour @@ -2482,7 +2485,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total @@ -2525,7 +2528,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/writeback_rate_debug @@ -2672,6 +2675,45 @@ Lines: 1 applesmc Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/devices/platform/bogus.0 +Mode: 775 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/devices/platform/bogus.0/hwmon +Mode: 775 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/devices/platform/bogus.0/hwmon/hwmon5 +Mode: 775 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/platform/bogus.0/hwmon/hwmon5/bogus1_crit +Lines: 1 +100000 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/platform/bogus.0/hwmon/hwmon5/bogus1_crit_alarm +Lines: 1 +0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/platform/bogus.0/hwmon/hwmon5/bogus1_input +Lines: 1 +55000 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/platform/bogus.0/hwmon/hwmon5/bogus1_label +Lines: 1 +Physical id 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/platform/bogus.0/hwmon/hwmon5/bogus1_max +Lines: 1 +84000 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/platform/bogus.0/hwmon/hwmon5/name +Lines: 1 +bogus +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/devices/platform/coretemp.0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3213,6 +3255,22 @@ Mode: 644 Directory: sys/devices/system Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/devices/system/clocksource +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/devices/system/clocksource/clocksource0 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/clocksource/clocksource0/available_clocksource +Lines: 1 +tsc hpet acpi_pm +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/clocksource/clocksource0/current_clocksource +Lines: 1 +tsc +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/devices/system/cpu Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3524,6 +3582,49 @@ Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/isolated +Lines: 1 +1,3-5,9 +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/offline +Lines: 1 + +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/online +Lines: 1 +0-3 +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/devices/system/cpu/vulnerabilities +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/itlb_multihit +Lines: 1 +Not affected +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/mds +Lines: 1 +Vulnerable +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/retbleed +Lines: 1 +Mitigation: untrained return thunk; SMT enabled with STIBP protection +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/spectre_v1 +Lines: 1 +Mitigation: usercopy/swapgs barriers and __user pointer sanitization +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/spectre_v2 +Lines: 1 +Mitigation: Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/devices/system/edac Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3879,7 +3980,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute @@ -3922,7 +4023,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour @@ -3965,7 +4066,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total @@ -4008,7 +4109,7 @@ Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_readaheads Lines: 1 -0 +13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/tree_depth @@ -4702,7 +4803,3 @@ Lines: 1 20 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: sys/.unpacked -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/collector/fixtures/textfile/metrics_merge_different_help.out b/collector/fixtures/textfile/metrics_merge_different_help.out new file mode 100644 index 0000000000..ba161f0779 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_different_help.out @@ -0,0 +1,11 @@ +# HELP events_total A nice help message. +# TYPE events_total counter +events_total{file="a",foo="bar"} 10 +events_total{file="a",foo="baz"} 20 +# HELP node_textfile_mtime_seconds Unixtime mtime of textfiles successfully read. +# TYPE node_textfile_mtime_seconds gauge +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_different_help/a.prom"} 1 +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_different_help/b.prom"} 1 +# HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise +# TYPE node_textfile_scrape_error gauge +node_textfile_scrape_error 0 diff --git a/collector/fixtures/textfile/metrics_merge_different_help/a.prom b/collector/fixtures/textfile/metrics_merge_different_help/a.prom new file mode 100644 index 0000000000..9188bbdeec --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_different_help/a.prom @@ -0,0 +1,5 @@ +# HELP events_total A nice help message. +# TYPE events_total counter +events_total{foo="bar",file="a"} 10 +events_total{foo="baz",file="a"} 20 + diff --git a/collector/fixtures/textfile/metrics_merge_different_help/b.prom b/collector/fixtures/textfile/metrics_merge_different_help/b.prom new file mode 100644 index 0000000000..259d43d0a5 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_different_help/b.prom @@ -0,0 +1,5 @@ +# HELP events_total A different help message. +# TYPE events_total counter +events_total{foo="bar",file="b"} 30 +events_total{foo="baz",file="b"} 40 + diff --git a/collector/fixtures/textfile/metrics_merge_empty_help.out b/collector/fixtures/textfile/metrics_merge_empty_help.out new file mode 100644 index 0000000000..2abe2cea9f --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_empty_help.out @@ -0,0 +1,13 @@ +# HELP events_total Metric read from fixtures/textfile/metrics_merge_empty_help/a.prom, fixtures/textfile/metrics_merge_empty_help/b.prom +# TYPE events_total counter +events_total{file="a",foo="bar"} 10 +events_total{file="a",foo="baz"} 20 +events_total{file="b",foo="bar"} 30 +events_total{file="b",foo="baz"} 40 +# HELP node_textfile_mtime_seconds Unixtime mtime of textfiles successfully read. +# TYPE node_textfile_mtime_seconds gauge +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_empty_help/a.prom"} 1 +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_empty_help/b.prom"} 1 +# HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise +# TYPE node_textfile_scrape_error gauge +node_textfile_scrape_error 0 diff --git a/collector/fixtures/textfile/metrics_merge_empty_help/a.prom b/collector/fixtures/textfile/metrics_merge_empty_help/a.prom new file mode 100644 index 0000000000..3036448d0c --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_empty_help/a.prom @@ -0,0 +1,5 @@ +# HELP events_total +# TYPE events_total counter +events_total{foo="bar",file="a"} 10 +events_total{foo="baz",file="a"} 20 + diff --git a/collector/fixtures/textfile/metrics_merge_empty_help/b.prom b/collector/fixtures/textfile/metrics_merge_empty_help/b.prom new file mode 100644 index 0000000000..efe9505a9a --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_empty_help/b.prom @@ -0,0 +1,5 @@ +# HELP events_total +# TYPE events_total counter +events_total{foo="bar",file="b"} 30 +events_total{foo="baz",file="b"} 40 + diff --git a/collector/fixtures/textfile/metrics_merge_no_help.out b/collector/fixtures/textfile/metrics_merge_no_help.out new file mode 100644 index 0000000000..268e3c4806 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_no_help.out @@ -0,0 +1,13 @@ +# HELP events_total Metric read from fixtures/textfile/metrics_merge_no_help/a.prom, fixtures/textfile/metrics_merge_no_help/b.prom +# TYPE events_total counter +events_total{file="a",foo="bar"} 10 +events_total{file="a",foo="baz"} 20 +events_total{file="b",foo="bar"} 30 +events_total{file="b",foo="baz"} 40 +# HELP node_textfile_mtime_seconds Unixtime mtime of textfiles successfully read. +# TYPE node_textfile_mtime_seconds gauge +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_no_help/a.prom"} 1 +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_no_help/b.prom"} 1 +# HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise +# TYPE node_textfile_scrape_error gauge +node_textfile_scrape_error 0 diff --git a/collector/fixtures/textfile/metrics_merge_no_help/a.prom b/collector/fixtures/textfile/metrics_merge_no_help/a.prom new file mode 100644 index 0000000000..e11c618bf0 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_no_help/a.prom @@ -0,0 +1,4 @@ +# TYPE events_total counter +events_total{foo="bar",file="a"} 10 +events_total{foo="baz",file="a"} 20 + diff --git a/collector/fixtures/textfile/metrics_merge_no_help/b.prom b/collector/fixtures/textfile/metrics_merge_no_help/b.prom new file mode 100644 index 0000000000..984fbf46a4 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_no_help/b.prom @@ -0,0 +1,4 @@ +# TYPE events_total counter +events_total{foo="bar",file="b"} 30 +events_total{foo="baz",file="b"} 40 + diff --git a/collector/fixtures/textfile/metrics_merge_same_help.out b/collector/fixtures/textfile/metrics_merge_same_help.out new file mode 100644 index 0000000000..5fddae3d77 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_same_help.out @@ -0,0 +1,13 @@ +# HELP events_total The same help. +# TYPE events_total counter +events_total{file="a",foo="bar"} 10 +events_total{file="a",foo="baz"} 20 +events_total{file="b",foo="bar"} 30 +events_total{file="b",foo="baz"} 40 +# HELP node_textfile_mtime_seconds Unixtime mtime of textfiles successfully read. +# TYPE node_textfile_mtime_seconds gauge +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_same_help/a.prom"} 1 +node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_same_help/b.prom"} 1 +# HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise +# TYPE node_textfile_scrape_error gauge +node_textfile_scrape_error 0 diff --git a/collector/fixtures/textfile/metrics_merge_same_help/a.prom b/collector/fixtures/textfile/metrics_merge_same_help/a.prom new file mode 100644 index 0000000000..a40cd6e627 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_same_help/a.prom @@ -0,0 +1,5 @@ +# HELP events_total The same help. +# TYPE events_total counter +events_total{foo="bar",file="a"} 10 +events_total{foo="baz",file="a"} 20 + diff --git a/collector/fixtures/textfile/metrics_merge_same_help/b.prom b/collector/fixtures/textfile/metrics_merge_same_help/b.prom new file mode 100644 index 0000000000..77728727b4 --- /dev/null +++ b/collector/fixtures/textfile/metrics_merge_same_help/b.prom @@ -0,0 +1,5 @@ +# HELP events_total The same help. +# TYPE events_total counter +events_total{foo="bar",file="b"} 30 +events_total{foo="baz",file="b"} 40 + diff --git a/collector/fixtures/udev.ttar b/collector/fixtures/udev.ttar new file mode 100644 index 0000000000..f4db1d901c --- /dev/null +++ b/collector/fixtures/udev.ttar @@ -0,0 +1,529 @@ +# Archive created by ttar -C collector/fixtures -c -f collector/fixtures/udev.ttar udev +Directory: udev +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: udev/data +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b11:0 +Lines: 38 +S:disk/by-id/usb-AMI_Virtual_CDROM0_AAAABBBBCCCC1-0:0 +S:disk/by-path/pci-0000:00:14.0-usb-0:1.1:1.0-scsi-0:0:0:0 +S:cdrom +L:-100 +I:83543243 +E:ID_CDROM=1 +E:SYSTEMD_MOUNT_DEVICE_BOUND=1 +E:ID_VENDOR=AMI +E:ID_VENDOR_ENC=AMI\x20\x20\x20\x20\x20 +E:ID_VENDOR_ID=c096 +E:ID_MODEL=Virtual_CDROM0 +E:ID_MODEL_ENC=Virtual\x20CDROM0\x20\x20 +E:ID_MODEL_ID=ee31 +E:ID_REVISION=1.00 +E:ID_SERIAL=AMI_Virtual_CDROM0_AAAABBBBCCCC1-0:0 +E:ID_SERIAL_SHORT=AAAABBBBCCCC1 +E:ID_TYPE=cd/dvd +E:ID_INSTANCE=0:0 +E:ID_BUS=usb +E:ID_USB_INTERFACES=:905639: +E:ID_USB_INTERFACE_NUM=00 +E:ID_USB_DRIVER=usb-storage +E:ID_PATH=pci-0000:00:14.0-usb-0:1.1:1.0-scsi-0:0:0:0 +E:ID_PATH_TAG=pci-0000_00_14_0-usb-0_1_1_1_0-scsi-0_0_0_0 +E:SCSI_TPGS=0 +E:SCSI_TYPE=cd/dvd +E:SCSI_VENDOR=AMI +E:SCSI_VENDOR_ENC=AMI\x20\x20\x20\x20\x20 +E:SCSI_MODEL=Virtual_CDROM0 +E:SCSI_MODEL_ENC=Virtual\x20CDROM0\x20\x20 +E:SCSI_REVISION=1.00 +E:ID_SCSI=1 +E:ID_SCSI_INQUIRY=1 +E:ID_FS_TYPE= +E:ID_FOR_SEAT=block-pci-0000_00_14_0-usb-0_1_1_1_0-scsi-0_0_0_0 +G:uaccess +G:systemd +G:seat +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b179:0 +Lines: 13 +S:disk/by-path/platform-df2969f3.mmc +S:disk/by-id/mmc-SC64G_0x83e36d93 +W:1 +I:7679747 +E:ID_NAME=SC64G +E:ID_SERIAL=0x83e36d93 +E:ID_PATH=platform-df2969f3.mmc +E:ID_PATH_TAG=platform-df2969f3_mmc +E:ID_PART_TABLE_UUID=1954c9df +E:ID_PART_TABLE_TYPE=dos +E:ID_DRIVE_FLASH_SD=1 +E:ID_DRIVE_MEDIA_FLASH_SD=1 +G:systemd +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b179:1 +Lines: 30 +S:disk/by-id/mmc-SC64G_0x83e36d93-part1 +S:disk/by-path/platform-df2969f3.mmc-part1 +S:disk/by-label/boot +S:disk/by-uuid/6284-658D +S:disk/by-partuuid/1954c9df-01 +W:12 +I:8463403 +E:ID_NAME=SC64G +E:ID_SERIAL=0x83e36d93 +E:ID_PATH=platform-df2969f3.mmc +E:ID_PATH_TAG=platform-df2969f3_mmc +E:ID_PART_TABLE_UUID=1954c9df +E:ID_PART_TABLE_TYPE=dos +E:ID_DRIVE_FLASH_SD=1 +E:ID_DRIVE_MEDIA_FLASH_SD=1 +E:ID_FS_LABEL=boot +E:ID_FS_LABEL_ENC=boot +E:ID_FS_UUID=6284-658D +E:ID_FS_UUID_ENC=6284-658D +E:ID_FS_VERSION=FAT32 +E:ID_FS_TYPE=vfat +E:ID_FS_USAGE=filesystem +E:ID_PART_ENTRY_SCHEME=dos +E:ID_PART_ENTRY_UUID=1954c9df-01 +E:ID_PART_ENTRY_TYPE=0xc +E:ID_PART_ENTRY_NUMBER=1 +E:ID_PART_ENTRY_OFFSET=8192 +E:ID_PART_ENTRY_SIZE=524288 +E:ID_PART_ENTRY_DISK=179:0 +G:systemd +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b179:2 +Lines: 30 +S:disk/by-id/mmc-SC64G_0x83e36d93-part2 +S:disk/by-path/platform-df2969f3.mmc-part2 +S:disk/by-label/rootfs +S:disk/by-uuid/83324ce8-a6f3-4e35-ad64-dbb3d6b87a32 +S:disk/by-partuuid/1954c9df-02 +W:2 +I:7676649 +E:ID_NAME=SC64G +E:ID_SERIAL=0x83e36d93 +E:ID_PATH=platform-df2969f3.mmc +E:ID_PATH_TAG=platform-df2969f3_mmc +E:ID_PART_TABLE_UUID=1954c9df +E:ID_PART_TABLE_TYPE=dos +E:ID_DRIVE_FLASH_SD=1 +E:ID_DRIVE_MEDIA_FLASH_SD=1 +E:ID_FS_LABEL=rootfs +E:ID_FS_LABEL_ENC=rootfs +E:ID_FS_UUID=83324ce8-a6f3-4e35-ad64-dbb3d6b87a32 +E:ID_FS_UUID_ENC=83324ce8-a6f3-4e35-ad64-dbb3d6b87a32 +E:ID_FS_VERSION=1.0 +E:ID_FS_TYPE=ext4 +E:ID_FS_USAGE=filesystem +E:ID_PART_ENTRY_SCHEME=dos +E:ID_PART_ENTRY_UUID=1954c9df-02 +E:ID_PART_ENTRY_TYPE=0x83 +E:ID_PART_ENTRY_NUMBER=2 +E:ID_PART_ENTRY_OFFSET=532480 +E:ID_PART_ENTRY_SIZE=124203008 +E:ID_PART_ENTRY_DISK=179:0 +G:systemd +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b252:0 +Lines: 20 +S:disk/by-id/dm-name-nvme0n1_crypt +S:mapper/nvme0n1_crypt +S:disk/by-id/lvm-pv-uuid-c3C3uW-gD96-Yw69-c1CJ-5MwT-6ysM-mST0vB +S:disk/by-id/dm-uuid-CRYPT-LUKS2-jolaulot80fy9zsiobkxyxo7y2dqeho2-nvme0n1_crypt +I:72859885 +E:DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG=1 +E:DM_UDEV_PRIMARY_SOURCE_FLAG=1 +E:DM_UDEV_RULES=1 +E:DM_UDEV_RULES_VSN=2 +E:DM_NAME=nvme0n1_crypt +E:DM_UUID=CRYPT-LUKS2-jolaulot80fy9zsiobkxyxo7y2dqeho2-nvme0n1_crypt +E:DM_SUSPENDED=0 +E:ID_FS_UUID=c3C3uW-gD96-Yw69-c1CJ-5MwT-6ysM-mST0vB +E:ID_FS_UUID_ENC=c3C3uW-gD96-Yw69-c1CJ-5MwT-6ysM-mST0vB +E:ID_FS_VERSION=LVM2 001 +E:ID_FS_TYPE=LVM2_member +E:ID_FS_USAGE=raid +G:systemd +Q:systemd +V:1 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b252:1 +Lines: 24 +S:disk/by-id/dm-uuid-LVM-wbGqQEBL9SxrW2DLntJwgg8fAv946hw3Tvjqh0v31fWgxEtD4BoHO0lROWFUY65T +S:mapper/system-swap_1 +S:disk/by-id/dm-name-system-swap_1 +S:disk/by-uuid/5272bb60-04b5-49cd-b730-be57c7604450 +S:system/swap_1 +I:78705530 +E:DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG=1 +E:DM_UDEV_PRIMARY_SOURCE_FLAG=1 +E:DM_UDEV_RULES=1 +E:DM_UDEV_RULES_VSN=2 +E:DM_NAME=system-swap_1 +E:DM_UUID=LVM-wbGqQEBL9SxrW2DLntJwgg8fAv946hw3Tvjqh0v31fWgxEtD4BoHO0lROWFUY65T +E:DM_SUSPENDED=0 +E:DM_VG_NAME=system +E:DM_LV_NAME=swap_1 +E:DM_LV_LAYER= +E:ID_FS_UUID=5272bb60-04b5-49cd-b730-be57c7604450 +E:ID_FS_UUID_ENC=5272bb60-04b5-49cd-b730-be57c7604450 +E:ID_FS_VERSION=1 +E:ID_FS_TYPE=swap +E:ID_FS_USAGE=other +G:systemd +Q:systemd +V:1 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b252:2 +Lines: 24 +S:disk/by-id/dm-name-system-root +S:disk/by-id/dm-uuid-LVM-NWEDo8q5ABDyJuC3F8veKNyWfYmeIBfFMS4MF3HakzUhkk7ekDm6fJTHkl2fYHe7 +S:mapper/system-root +S:disk/by-uuid/3deafd0d-faff-4695-8d15-51061ae1f51b +S:system/root +I:77655410 +E:DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG=1 +E:DM_UDEV_PRIMARY_SOURCE_FLAG=1 +E:DM_UDEV_RULES=1 +E:DM_UDEV_RULES_VSN=2 +E:DM_NAME=system-root +E:DM_UUID=LVM-NWEDo8q5ABDyJuC3F8veKNyWfYmeIBfFMS4MF3HakzUhkk7ekDm6fJTHkl2fYHe7 +E:DM_SUSPENDED=0 +E:DM_VG_NAME=system +E:DM_LV_NAME=root +E:DM_LV_LAYER= +E:ID_FS_UUID=3deafd0d-faff-4695-8d15-51061ae1f51b +E:ID_FS_UUID_ENC=3deafd0d-faff-4695-8d15-51061ae1f51b +E:ID_FS_VERSION=1.0 +E:ID_FS_TYPE=ext4 +E:ID_FS_USAGE=filesystem +G:systemd +Q:systemd +V:1 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b252:3 +Lines: 24 +S:disk/by-id/dm-name-system-var +S:disk/by-id/dm-uuid-LVM-hrxHo0rlZ6U95ku5841Lpd17bS1Z7V7lrtEE60DVgE6YEOCdS9gcDGyonWim4hGP +S:mapper/system-var +S:disk/by-uuid/5c772222-f7d4-4c8e-87e8-e97df6b7a45e +S:system/var +I:79395348 +E:DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG=1 +E:DM_UDEV_PRIMARY_SOURCE_FLAG=1 +E:DM_UDEV_RULES=1 +E:DM_UDEV_RULES_VSN=2 +E:DM_NAME=system-var +E:DM_UUID=LVM-hrxHo0rlZ6U95ku5841Lpd17bS1Z7V7lrtEE60DVgE6YEOCdS9gcDGyonWim4hGP +E:DM_SUSPENDED=0 +E:DM_VG_NAME=system +E:DM_LV_NAME=var +E:DM_LV_LAYER= +E:ID_FS_UUID=5c772222-f7d4-4c8e-87e8-e97df6b7a45e +E:ID_FS_UUID_ENC=5c772222-f7d4-4c8e-87e8-e97df6b7a45e +E:ID_FS_VERSION=1.0 +E:ID_FS_TYPE=ext4 +E:ID_FS_USAGE=filesystem +G:systemd +Q:systemd +V:1 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b252:4 +Lines: 24 +S:system/tmp +S:disk/by-uuid/a9479d44-60e1-4015-a1e5-bb065e6dd11b +S:disk/by-id/dm-uuid-LVM-XTNGOHjPWLHcxmJmVu5cWTXEtuzqDeBkdEHAZW5q9LxWQ2d4mb5CchUQzUPJpl8H +S:mapper/system-tmp +S:disk/by-id/dm-name-system-tmp +I:75852450 +E:DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG=1 +E:DM_UDEV_PRIMARY_SOURCE_FLAG=1 +E:DM_UDEV_RULES=1 +E:DM_UDEV_RULES_VSN=2 +E:DM_NAME=system-tmp +E:DM_UUID=LVM-XTNGOHjPWLHcxmJmVu5cWTXEtuzqDeBkdEHAZW5q9LxWQ2d4mb5CchUQzUPJpl8H +E:DM_SUSPENDED=0 +E:DM_VG_NAME=system +E:DM_LV_NAME=tmp +E:DM_LV_LAYER= +E:ID_FS_UUID=a9479d44-60e1-4015-a1e5-bb065e6dd11b +E:ID_FS_UUID_ENC=a9479d44-60e1-4015-a1e5-bb065e6dd11b +E:ID_FS_VERSION=1.0 +E:ID_FS_TYPE=ext4 +E:ID_FS_USAGE=filesystem +G:systemd +Q:systemd +V:1 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b252:5 +Lines: 24 +S:disk/by-uuid/b05b726a-c718-4c4d-8641-7c73a7696d83 +S:mapper/system-home +S:system/home +S:disk/by-id/dm-name-system-home +S:disk/by-id/dm-uuid-LVM-MtoJaWTpjWRXlUnNFlpxZauTEuYlMvGFutigEzCCrfj8CNh6jCRi5LQJXZCpLjPf +I:72604009 +E:DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG=1 +E:DM_UDEV_PRIMARY_SOURCE_FLAG=1 +E:DM_UDEV_RULES=1 +E:DM_UDEV_RULES_VSN=2 +E:DM_NAME=system-home +E:DM_UUID=LVM-MtoJaWTpjWRXlUnNFlpxZauTEuYlMvGFutigEzCCrfj8CNh6jCRi5LQJXZCpLjPf +E:DM_SUSPENDED=0 +E:DM_VG_NAME=system +E:DM_LV_NAME=home +E:DM_LV_LAYER= +E:ID_FS_UUID=b05b726a-c718-4c4d-8641-7c73a7696d83 +E:ID_FS_UUID_ENC=b05b726a-c718-4c4d-8641-7c73a7696d83 +E:ID_FS_VERSION=1.0 +E:ID_FS_TYPE=ext4 +E:ID_FS_USAGE=filesystem +G:systemd +Q:systemd +V:1 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b254:0 +Lines: 10 +S:disk/by-path/pci-0000:00:06.0 +S:disk/by-path/virtio-pci-0000:00:06.0 +W:1 +I:8524171 +E:ID_PATH=pci-0000:00:06.0 +E:ID_PATH_TAG=pci-0000_00_06_0 +E:ID_PART_TABLE_UUID=653b59fd +E:ID_PART_TABLE_TYPE=dos +E:ID_FS_TYPE= +G:systemd +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b259:0 +Lines: 17 +S:disk/by-path/pci-0000:02:00.0-nvme-1 +S:disk/by-id/nvme-eui.p3vbbiejx5aae2r3 +S:disk/by-id/nvme-SAMSUNG_EHFTF55LURSY-000Y9_S252B6CU1HG3M1 +I:79621327 +E:ID_SERIAL_SHORT=S252B6CU1HG3M1 +E:ID_WWN=eui.p3vbbiejx5aae2r3 +E:ID_MODEL=SAMSUNG EHFTF55LURSY-000Y9 +E:ID_REVISION=4NBTUY95 +E:ID_SERIAL=SAMSUNG_EHFTF55LURSY-000Y9_S252B6CU1HG3M1 +E:ID_PATH=pci-0000:02:00.0-nvme-1 +E:ID_PATH_TAG=pci-0000_02_00_0-nvme-1 +E:ID_PART_TABLE_UUID=f301fdbd-fd1f-46d4-9fb8-c9aeb757f050 +E:ID_PART_TABLE_TYPE=gpt +E:ID_FS_TYPE= +G:systemd +Q:systemd +V:1 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b8:0 +Lines: 60 +S:disk/by-id/lvm-pv-uuid-cVVv6j-HSA2-IY33-1Jmj-dO2H-YL7w-b4Oxqw +S:disk/by-id/scsi-SATA_TOSHIBA_KSDB4U86_2160A0D5FVGG +S:disk/by-id/ata-TOSHIBA_KSDB4U866TE_2160A0D5FVGG +S:disk/by-path/pci-0000:3b:00.0-sas-phy7-lun-0 +S:disk/by-id/scsi-37c72382b8de36a64 +S:disk/by-id/wwn-0x7c72382b8de36a64 +W:702 +I:73815117 +E:ID_ATA=1 +E:ID_TYPE=disk +E:ID_BUS=ata +E:ID_MODEL=TOSHIBA_KSDB4U86 +E:ID_MODEL_ENC=TOSHIBA\x20KSDB4U86 +E:ID_REVISION=0102 +E:ID_SERIAL=TOSHIBA_KSDB4U866TE_DTB0QRJR2EIG +E:ID_SERIAL_SHORT=2160A0D5FVGG +E:ID_ATA_WRITE_CACHE=1 +E:ID_ATA_WRITE_CACHE_ENABLED=0 +E:ID_ATA_FEATURE_SET_PM=1 +E:ID_ATA_FEATURE_SET_PM_ENABLED=1 +E:ID_ATA_FEATURE_SET_SECURITY=1 +E:ID_ATA_FEATURE_SET_SECURITY_ENABLED=0 +E:ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=66892 +E:ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=66892 +E:ID_ATA_FEATURE_SET_SMART=1 +E:ID_ATA_FEATURE_SET_SMART_ENABLED=1 +E:ID_ATA_FEATURE_SET_APM=1 +E:ID_ATA_FEATURE_SET_APM_ENABLED=1 +E:ID_ATA_FEATURE_SET_APM_CURRENT_VALUE=128 +E:ID_ATA_DOWNLOAD_MICROCODE=1 +E:ID_ATA_SATA=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN2=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN1=1 +E:ID_ATA_ROTATION_RATE_RPM=7200 +E:ID_WWN=0x7c72382b8de36a64 +E:ID_WWN_WITH_EXTENSION=0x7c72382b8de36a64 +E:ID_PATH=pci-0000:3b:00.0-sas-phy7-lun-0 +E:ID_PATH_TAG=pci-0000_3b_00_0-sas-phy7-lun-0 +E:ID_FS_UUID=cVVv6j-HSA2-IY33-1Jmj-dO2H-YL7w-b4Oxqw +E:ID_FS_UUID_ENC=cVVv6j-HSA2-IY33-1Jmj-dO2H-YL7w-b4Oxqw +E:ID_FS_VERSION=LVM2 001 +E:ID_FS_TYPE=LVM2_member +E:ID_FS_USAGE=raid +E:SCSI_TPGS=0 +E:SCSI_TYPE=disk +E:SCSI_VENDOR=ATA +E:SCSI_VENDOR_ENC=ATA\x20\x20\x20\x20\x20 +E:SCSI_MODEL=TOSHIBA_KSDB4U86 +E:SCSI_MODEL_ENC=TOSHIBA\x20KSDB4U86 +E:SCSI_REVISION=0102 +E:ID_SCSI=1 +E:ID_SCSI_INQUIRY=1 +E:ID_VENDOR=ATA +E:ID_VENDOR_ENC=ATA\x20\x20\x20\x20\x20 +E:SCSI_IDENT_SERIAL=2160A0D5FVGG +E:SCSI_IDENT_LUN_NAA_REG=7c72382b8de36a64 +E:SYSTEMD_READY=1 +E:SYSTEMD_ALIAS=/dev/block/8:0 +E:SYSTEMD_WANTS=lvm2-pvscan@8:0.service +G:systemd +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b8:16 +Lines: 62 +S:disk/by-id/scsi-3e1b87abbb16bd84e +S:disk/by-id/wwn-0xe1b87abbb16bd84e +S:disk/by-path/pci-0000:00:1f.2-ata-1 +S:disk/by-id/scsi-0ATA_SuperMicro_SSD_SMC0E1B87ABBB16BD84E +S:disk/by-id/scsi-SATA_SuperMicro_SSD_SMC0E1B87ABBB16BD84E +S:disk/by-id/scsi-1ATA_SuperMicro_SSD_SMC0E1B87ABBB16BD84E +S:disk/by-id/ata-SuperMicro_SSD_SMC0E1B87ABBB16BD84E +W:58 +I:147686920 +E:ID_ATA=1 +E:ID_TYPE=disk +E:ID_BUS=ata +E:ID_MODEL=SuperMicro_SSD +E:ID_MODEL_ENC=SuperMicro\x20SSD\x20\x20 +E:ID_REVISION=0R +E:ID_SERIAL=SuperMicro_SSD_SMC0E1B87ABBB16BD84E +E:ID_SERIAL_SHORT=SMC0E1B87ABBB16BD84E +E:ID_ATA_WRITE_CACHE=1 +E:ID_ATA_WRITE_CACHE_ENABLED=1 +E:ID_ATA_FEATURE_SET_HPA=1 +E:ID_ATA_FEATURE_SET_HPA_ENABLED=1 +E:ID_ATA_FEATURE_SET_PM=1 +E:ID_ATA_FEATURE_SET_PM_ENABLED=1 +E:ID_ATA_FEATURE_SET_SECURITY=1 +E:ID_ATA_FEATURE_SET_SECURITY_ENABLED=0 +E:ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=4 +E:ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=4 +E:ID_ATA_FEATURE_SET_SMART=1 +E:ID_ATA_FEATURE_SET_SMART_ENABLED=1 +E:ID_ATA_FEATURE_SET_AAM=1 +E:ID_ATA_FEATURE_SET_AAM_ENABLED=0 +E:ID_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE=0 +E:ID_ATA_FEATURE_SET_AAM_CURRENT_VALUE=0 +E:ID_ATA_DOWNLOAD_MICROCODE=1 +E:ID_ATA_SATA=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN2=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN1=1 +E:ID_ATA_ROTATION_RATE_RPM=0 +E:ID_WWN=0xe1b87abbb16bd84e +E:ID_WWN_WITH_EXTENSION=0xe1b87abbb16bd84e +E:ID_PATH=pci-0000:00:1f.2-ata-1 +E:ID_PATH_TAG=pci-0000_00_1f_2-ata-1 +E:ID_PART_TABLE_UUID=45980145-24e2-4302-a7f0-364c68cfaf59 +E:ID_PART_TABLE_TYPE=gpt +E:SCSI_TPGS=0 +E:SCSI_TYPE=disk +E:SCSI_VENDOR=ATA +E:SCSI_VENDOR_ENC=ATA\x20\x20\x20\x20\x20 +E:SCSI_MODEL=SuperMicro_SSD +E:SCSI_MODEL_ENC=SuperMicro\x20SSD\x20\x20 +E:SCSI_REVISION=0R +E:ID_SCSI=1 +E:ID_SCSI_INQUIRY=1 +E:ID_VENDOR=ATA +E:ID_VENDOR_ENC=ATA\x20\x20\x20\x20\x20 +E:SCSI_IDENT_SERIAL=SMC0E1B87ABBB16BD84E +E:SCSI_IDENT_LUN_VENDOR=SMC0E1B87ABBB16BD84E +E:SCSI_IDENT_LUN_T10=ATA_SuperMicro_SSD_SMC0E1B87ABBB16BD84E +E:SCSI_IDENT_LUN_ATA=SuperMicro_SSD_SMC0E1B87ABBB16BD84E +E:SCSI_IDENT_LUN_NAA_REG=e1b87abbb16bd84e +E:ID_FS_TYPE= +G:systemd +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: udev/data/b8:32 +Lines: 62 +S:disk/by-path/pci-0000:00:1f.2-ata-4 +S:disk/by-id/scsi-SATA_INTEL_SSDS9X9SI0_3EWB5Y25CWQWA7EH1U +S:disk/by-id/scsi-0ATA_INTEL_SSDS9X9SI0_3EWB5Y25CWQWA7EH1U +S:disk/by-id/scsi-1ATA_INTEL_SSDS9X9SI00G8_3EWB5Y25CWQWA7EH1U +S:disk/by-id/lvm-pv-uuid-QFy9W7-Brj3-hQ6v-AF8i-3Zqg-n3Vs-kGY4vb +S:disk/by-id/ata-INTEL_SSDS9X9SI00G8_3EWB5Y25CWQWA7EH1U +S:disk/by-id/scsi-358907ddc573a5de +S:disk/by-id/wwn-0x58907ddc573a5de +W:10 +I:145572852 +E:ID_ATA=1 +E:ID_TYPE=disk +E:ID_BUS=ata +E:ID_MODEL=INTEL_SSDS9X9SI0 +E:ID_MODEL_ENC=INTEL\x20SSDS9X9SI0 +E:ID_REVISION=0100 +E:ID_SERIAL=INTEL_SSDS9X9SI00G8_3EWB5Y25CWQWA7EH1U +E:ID_SERIAL_SHORT=3EWB5Y25CWQWA7EH1U +E:ID_ATA_WRITE_CACHE=1 +E:ID_ATA_WRITE_CACHE_ENABLED=0 +E:ID_ATA_FEATURE_SET_PM=1 +E:ID_ATA_FEATURE_SET_PM_ENABLED=1 +E:ID_ATA_FEATURE_SET_SECURITY=1 +E:ID_ATA_FEATURE_SET_SECURITY_ENABLED=0 +E:ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=4 +E:ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=4 +E:ID_ATA_FEATURE_SET_SMART=1 +E:ID_ATA_FEATURE_SET_SMART_ENABLED=1 +E:ID_ATA_DOWNLOAD_MICROCODE=1 +E:ID_ATA_SATA=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN2=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN1=1 +E:ID_ATA_ROTATION_RATE_RPM=0 +E:ID_WWN=0x58907ddc573a5de +E:ID_WWN_WITH_EXTENSION=0x58907ddc573a5de +E:ID_PATH=pci-0000:00:1f.2-ata-4 +E:ID_PATH_TAG=pci-0000_00_1f_2-ata-4 +E:ID_FS_UUID=QFy9W7-Brj3-hQ6v-AF8i-3Zqg-n3Vs-kGY4vb +E:ID_FS_UUID_ENC=QFy9W7-Brj3-hQ6v-AF8i-3Zqg-n3Vs-kGY4vb +E:ID_FS_VERSION=LVM2 001 +E:ID_FS_TYPE=LVM2_member +E:ID_FS_USAGE=raid +E:SCSI_TPGS=0 +E:SCSI_TYPE=disk +E:SCSI_VENDOR=ATA +E:SCSI_VENDOR_ENC=ATA\x20\x20\x20\x20\x20 +E:SCSI_MODEL=INTEL_SSDS9X9SI0 +E:SCSI_MODEL_ENC=INTEL\x20SSDS9X9SI0 +E:SCSI_REVISION=0100 +E:ID_SCSI=1 +E:ID_SCSI_INQUIRY=1 +E:ID_VENDOR=ATA +E:ID_VENDOR_ENC=ATA\x20\x20\x20\x20\x20 +E:SCSI_IDENT_SERIAL=3EWB5Y25CWQWA7EH1U +E:SCSI_IDENT_LUN_VENDOR=3EWB5Y25CWQWA7EH1U +E:SCSI_IDENT_LUN_T10=ATA_INTEL_SSDS9X9SI00G8_3EWB5Y25CWQWA7EH1U +E:SCSI_IDENT_LUN_ATA=INTEL_SSDS9X9SI00G8_3EWB5Y25CWQWA7EH1U +E:SCSI_IDENT_LUN_NAA_REG=58907ddc573a5de +E:SYSTEMD_READY=1 +E:SYSTEMD_ALIAS=/dev/block/8:32 +E:SYSTEMD_WANTS=lvm2-pvscan@8:32.service +G:systemd +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/collector/helper.go b/collector/helper.go index 527fa74227..21dddf887c 100644 --- a/collector/helper.go +++ b/collector/helper.go @@ -14,15 +14,14 @@ package collector import ( - "bytes" - "io/ioutil" + "os" "regexp" "strconv" "strings" ) func readUintFromFile(path string) (uint64, error) { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return 0, err } @@ -33,22 +32,9 @@ func readUintFromFile(path string) (uint64, error) { return value, nil } -// Take a []byte{} and return a string based on null termination. -// This is useful for situations where the OS has returned a null terminated -// string to use. -// If this function happens to receive a byteArray that contains no nulls, we -// simply convert the array to a string with no bounding. -func bytesToString(byteArray []byte) string { - n := bytes.IndexByte(byteArray, 0) - if n < 0 { - return string(byteArray) - } - return string(byteArray[:n]) -} - var metricNameRegex = regexp.MustCompile(`_*[^0-9A-Za-z_]+_*`) -// Sanitize the given metric name by replacing invalid characters by underscores. +// SanitizeMetricName sanitize the given metric name by replacing invalid characters by underscores. // // OpenMetrics and the Prometheus exposition format require the metric name // to consist only of alphanumericals and "_", ":" and they must not start diff --git a/collector/helper_test.go b/collector/helper_test.go index 15fe5054c1..9c1296edda 100644 --- a/collector/helper_test.go +++ b/collector/helper_test.go @@ -17,51 +17,6 @@ import ( "testing" ) -func TestBytesToString(t *testing.T) { - tests := []struct { - name string - b []byte - expected string - }{ - { - "Single null byte", - []byte{0}, - "", - }, - { - "Empty byte array", - []byte{}, - "", - }, - { - "Not null terminated", - []byte{65, 66, 67}, - "ABC", - }, - { - "Null randomly in array", - []byte{65, 66, 67, 0, 65, 0, 65}, - "ABC", - }, - { - "Array starts with null and contains other valid bytes", - []byte{0, 65, 66, 67, 0}, - "", - }, - } - - for _, tt := range tests { - name := tt.name - b := tt.b - result := bytesToString(b) - expected := tt.expected - - if result != expected { - t.Errorf("bytesToString(%#v): Name: %s, expected %#v, got %#v)", b, name, expected, result) - } - } -} - func TestSanitizeMetricName(t *testing.T) { testcases := map[string]string{ "": "", diff --git a/collector/hwmon_linux.go b/collector/hwmon_linux.go index 3178b1ccce..a8086d309e 100644 --- a/collector/hwmon_linux.go +++ b/collector/hwmon_linux.go @@ -18,13 +18,13 @@ package collector import ( "errors" - "io/ioutil" "os" "path/filepath" "regexp" "strconv" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" @@ -32,6 +32,9 @@ import ( ) var ( + collectorHWmonChipInclude = kingpin.Flag("collector.hwmon.chip-include", "Regexp of hwmon chip to include (mutually exclusive to device-exclude).").String() + collectorHWmonChipExclude = kingpin.Flag("collector.hwmon.chip-exclude", "Regexp of hwmon chip to exclude (mutually exclusive to device-include).").String() + hwmonInvalidMetricChars = regexp.MustCompile("[^a-z0-9:_]") hwmonFilenameFormat = regexp.MustCompile(`^(?P[^0-9]+)(?P[0-9]*)?(_(?P.+))?$`) hwmonLabelDesc = []string{"chip", "sensor"} @@ -48,13 +51,18 @@ func init() { } type hwMonCollector struct { - logger log.Logger + deviceFilter deviceFilter + logger log.Logger } // NewHwMonCollector returns a new Collector exposing /sys/class/hwmon stats // (similar to lm-sensors). func NewHwMonCollector(logger log.Logger) (Collector, error) { - return &hwMonCollector{logger}, nil + + return &hwMonCollector{ + logger: logger, + deviceFilter: newDeviceFilter(*collectorHWmonChipExclude, *collectorHWmonChipInclude), + }, nil } func cleanMetricName(name string) string { @@ -78,7 +86,7 @@ func addValueFile(data map[string]map[string]string, sensor string, prop string, data[sensor][prop] = value } -// sysReadFile is a simplified ioutil.ReadFile that invokes syscall.Read directly. +// sysReadFile is a simplified os.ReadFile that invokes syscall.Read directly. func sysReadFile(file string) ([]byte, error) { f, err := os.Open(file) if err != nil { @@ -87,7 +95,7 @@ func sysReadFile(file string) ([]byte, error) { defer f.Close() // On some machines, hwmon drivers are broken and return EAGAIN. This causes - // Go's ioutil.ReadFile implementation to poll forever. + // Go's os.ReadFile implementation to poll forever. // // Since we either want to read data or bail immediately, do the simplest // possible read using system call directly. @@ -128,7 +136,7 @@ func explodeSensorFilename(filename string) (ok bool, sensorType string, sensorN } func collectSensorData(dir string, data map[string]map[string]string) error { - sensorFiles, dirError := ioutil.ReadDir(dir) + sensorFiles, dirError := os.ReadDir(dir) if dirError != nil { return dirError } @@ -155,6 +163,11 @@ func (c *hwMonCollector) updateHwmon(ch chan<- prometheus.Metric, dir string) er return err } + if c.deviceFilter.ignored(hwmonName) { + level.Debug(c.logger).Log("msg", "ignoring hwmon chip", "chip", hwmonName) + return nil + } + data := make(map[string]map[string]string) err = collectSensorData(dir, data) if err != nil { @@ -193,12 +206,10 @@ func (c *hwMonCollector) updateHwmon(ch chan<- prometheus.Metric, dir string) er labels := []string{hwmonName, sensor} if labelText, ok := sensorData["label"]; ok { - label := cleanMetricName(labelText) - if label != "" { - desc := prometheus.NewDesc("node_hwmon_sensor_label", "Label for given chip and sensor", - []string{"chip", "sensor", "label"}, nil) - ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, 1.0, hwmonName, sensor, label) - } + label := strings.ToValidUTF8(labelText, "�") + desc := prometheus.NewDesc("node_hwmon_sensor_label", "Label for given chip and sensor", + []string{"chip", "sensor", "label"}, nil) + ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, 1.0, hwmonName, sensor, label) } if sensorType == "beep_enable" { @@ -374,7 +385,7 @@ func (c *hwMonCollector) hwmonName(dir string) (string, error) { } // preference 2: is there a name file - sysnameRaw, nameErr := ioutil.ReadFile(filepath.Join(dir, "name")) + sysnameRaw, nameErr := os.ReadFile(filepath.Join(dir, "name")) if nameErr == nil && string(sysnameRaw) != "" { cleanName := cleanMetricName(string(sysnameRaw)) if cleanName != "" { @@ -402,7 +413,7 @@ func (c *hwMonCollector) hwmonName(dir string) (string, error) { // hwmonHumanReadableChipName is similar to the methods in hwmonName, but with // different precedences -- we can allow duplicates here. func (c *hwMonCollector) hwmonHumanReadableChipName(dir string) (string, error) { - sysnameRaw, nameErr := ioutil.ReadFile(filepath.Join(dir, "name")) + sysnameRaw, nameErr := os.ReadFile(filepath.Join(dir, "name")) if nameErr != nil { return "", nameErr } @@ -423,7 +434,7 @@ func (c *hwMonCollector) Update(ch chan<- prometheus.Metric) error { hwmonPathName := filepath.Join(sysFilePath("class"), "hwmon") - hwmonFiles, err := ioutil.ReadDir(hwmonPathName) + hwmonFiles, err := os.ReadDir(hwmonPathName) if err != nil { if errors.Is(err, os.ErrNotExist) { level.Debug(c.logger).Log("msg", "hwmon collector metrics are not available for this system") @@ -433,24 +444,29 @@ func (c *hwMonCollector) Update(ch chan<- prometheus.Metric) error { return err } + var lastErr error for _, hwDir := range hwmonFiles { hwmonXPathName := filepath.Join(hwmonPathName, hwDir.Name()) + fileInfo, err := os.Lstat(hwmonXPathName) + if err != nil { + continue + } - if hwDir.Mode()&os.ModeSymlink > 0 { - hwDir, err = os.Stat(hwmonXPathName) + if fileInfo.Mode()&os.ModeSymlink > 0 { + fileInfo, err = os.Stat(hwmonXPathName) if err != nil { continue } } - if !hwDir.IsDir() { + if !fileInfo.IsDir() { continue } - if lastErr := c.updateHwmon(ch, hwmonXPathName); lastErr != nil { - err = lastErr + if err = c.updateHwmon(ch, hwmonXPathName); err != nil { + lastErr = err } } - return err + return lastErr } diff --git a/collector/infiniband_linux.go b/collector/infiniband_linux.go index 3afb7c45b6..b0928da3cf 100644 --- a/collector/infiniband_linux.go +++ b/collector/infiniband_linux.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build linux && !noinfiniband -// +build linux,!noinfiniband +//go:build !noinfiniband +// +build !noinfiniband package collector diff --git a/collector/interrupts_linux.go b/collector/interrupts_linux.go index 4d74c536a6..ede7819111 100644 --- a/collector/interrupts_linux.go +++ b/collector/interrupts_linux.go @@ -77,22 +77,29 @@ func parseInterrupts(r io.Reader) (map[string]interrupt, error) { cpuNum := len(strings.Fields(scanner.Text())) // one header per cpu for scanner.Scan() { - parts := strings.Fields(scanner.Text()) - if len(parts) < cpuNum+2 { // irq + one column per cpu + details, - continue // we ignore ERR and MIS for now - } - intName := parts[0][:len(parts[0])-1] // remove trailing : - intr := interrupt{ - values: parts[1 : cpuNum+1], - } + // On aarch64 there can be zero space between the name/label + // and the values, so we need to split on `:` before using + // strings.Fields() to split on fields. + group := strings.SplitN(scanner.Text(), ":", 2) + if len(group) > 1 { + parts := strings.Fields(group[1]) + + if len(parts) < cpuNum+1 { // irq + one column per cpu + details, + continue // we ignore ERR and MIS for now + } + intName := strings.TrimLeft(group[0], " ") + intr := interrupt{ + values: parts[0:cpuNum], + } - if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt - intr.info = parts[cpuNum+1] - intr.devices = strings.Join(parts[cpuNum+2:], " ") - } else { - intr.info = strings.Join(parts[cpuNum+1:], " ") + if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt + intr.info = parts[cpuNum] + intr.devices = strings.Join(parts[cpuNum+1:], " ") + } else { + intr.info = strings.Join(parts[cpuNum:], " ") + } + interrupts[intName] = intr } - interrupts[intName] = intr } return interrupts, scanner.Err() diff --git a/collector/interrupts_linux_test.go b/collector/interrupts_linux_test.go index 02acb896a0..82e536e4e9 100644 --- a/collector/interrupts_linux_test.go +++ b/collector/interrupts_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nointerrupts +// +build !nointerrupts + package collector import ( @@ -31,10 +34,39 @@ func TestInterrupts(t *testing.T) { } if want, got := "5031", interrupts["NMI"].values[1]; want != got { - t.Errorf("want interrupts %s, got %s", want, got) + t.Errorf("want interrupts value %s, got %s", want, got) } if want, got := "4968", interrupts["NMI"].values[3]; want != got { - t.Errorf("want interrupts %s, got %s", want, got) + t.Errorf("want interrupts value %s, got %s", want, got) + } + + if want, got := "IR-IO-APIC-edge", interrupts["12"].info; want != got { + t.Errorf("want interrupts info %s, got %s", want, got) + } + + if want, got := "i8042", interrupts["12"].devices; want != got { + t.Errorf("want interrupts devices %s, got %s", want, got) + } + +} + +// https://github.com/prometheus/node_exporter/issues/2557 +// On aarch64 the interrupts file can have zero spaces between the label of +// the row and the first value if the value is large +func TestInterruptsArm(t *testing.T) { + file, err := os.Open("fixtures/proc/interrupts_aarch64") + if err != nil { + t.Fatal(err) + } + defer file.Close() + + interrupts, err := parseInterrupts(file) + if err != nil { + t.Fatal(err) + } + + if _, ok := interrupts["IPI0"]; !ok { + t.Errorf("IPI0 label not found in interrupts") } } diff --git a/collector/interrupts_openbsd.go b/collector/interrupts_openbsd.go index ba73406954..9fa5b68d5d 100644 --- a/collector/interrupts_openbsd.go +++ b/collector/interrupts_openbsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build openbsd && !amd64 && !nointerrupts -// +build openbsd,!amd64,!nointerrupts +//go:build !nointerrupts && !amd64 +// +build !nointerrupts,!amd64 package collector diff --git a/collector/ipvs_linux.go b/collector/ipvs_linux.go index 4a9c14b6d3..63a3a1a8a8 100644 --- a/collector/ipvs_linux.go +++ b/collector/ipvs_linux.go @@ -24,11 +24,11 @@ import ( "strconv" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) type ipvsCollector struct { diff --git a/collector/ipvs_linux_test.go b/collector/ipvs_linux_test.go index cf12a216ce..6ee41b299b 100644 --- a/collector/ipvs_linux_test.go +++ b/collector/ipvs_linux_test.go @@ -11,22 +11,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !noipvs +// +build !noipvs + package collector import ( "errors" "fmt" - "io/ioutil" "net/http" "net/http/httptest" + "os" "strings" "testing" "github.com/go-kit/log" + "github.com/alecthomas/kingpin/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "gopkg.in/alecthomas/kingpin.v2" ) func TestIPVSCollector(t *testing.T) { @@ -189,7 +192,7 @@ func TestIPVSCollectorResponse(t *testing.T) { rw := httptest.NewRecorder() promhttp.InstrumentMetricHandler(registry, promhttp.HandlerFor(registry, promhttp.HandlerOpts{})).ServeHTTP(rw, &http.Request{}) - wantMetrics, err := ioutil.ReadFile(test.metricsFile) + wantMetrics, err := os.ReadFile(test.metricsFile) if err != nil { t.Fatalf("unable to read input test file %s: %s", test.metricsFile, err) } @@ -209,9 +212,8 @@ func TestIPVSCollectorResponse(t *testing.T) { if want == got { // this is a line we are interested in, and it is correct continue wantLoop - } else { - gotLinesIdx++ } + gotLinesIdx++ } // if this point is reached, the line we want was missing t.Fatalf("Missing expected output line(s), first missing line is %s", want) diff --git a/collector/lnstat_linux.go b/collector/lnstat_linux.go index e5e13bf01b..b3c90dc06e 100644 --- a/collector/lnstat_linux.go +++ b/collector/lnstat_linux.go @@ -30,7 +30,7 @@ type lnstatCollector struct { } func init() { - registerCollector("lnstat", defaultEnabled, NewLnstatCollector) + registerCollector("lnstat", defaultDisabled, NewLnstatCollector) } func NewLnstatCollector(logger log.Logger) (Collector, error) { @@ -49,7 +49,7 @@ func (c *lnstatCollector) Update(ch chan<- prometheus.Metric) error { netStats, err := fs.NetStat() if err != nil { - return fmt.Errorf("Lnstat error: %s", err) + return fmt.Errorf("lnstat error: %s", err) } for _, netStatFile := range netStats { diff --git a/collector/loadavg_linux.go b/collector/loadavg_linux.go index d118eaba5f..aab11b1851 100644 --- a/collector/loadavg_linux.go +++ b/collector/loadavg_linux.go @@ -18,14 +18,14 @@ package collector import ( "fmt" - "io/ioutil" + "os" "strconv" "strings" ) // Read loadavg from /proc. func getLoad() (loads []float64, err error) { - data, err := ioutil.ReadFile(procFilePath("loadavg")) + data, err := os.ReadFile(procFilePath("loadavg")) if err != nil { return nil, err } diff --git a/collector/loadavg_linux_test.go b/collector/loadavg_linux_test.go index e8e5a0ce3f..2d56317dc5 100644 --- a/collector/loadavg_linux_test.go +++ b/collector/loadavg_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !noloadavg +// +build !noloadavg + package collector import "testing" diff --git a/collector/logind_linux.go b/collector/logind_linux.go index 06703e9640..de5b0d18ad 100644 --- a/collector/logind_linux.go +++ b/collector/logind_linux.go @@ -22,7 +22,7 @@ import ( "strconv" "github.com/go-kit/log" - "github.com/godbus/dbus" + "github.com/godbus/dbus/v5" "github.com/prometheus/client_golang/prometheus" ) diff --git a/collector/logind_linux_test.go b/collector/logind_linux_test.go index 349d53872a..5cfedff4db 100644 --- a/collector/logind_linux_test.go +++ b/collector/logind_linux_test.go @@ -11,12 +11,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nologind +// +build !nologind + package collector import ( "testing" - "github.com/godbus/dbus" + "github.com/godbus/dbus/v5" "github.com/prometheus/client_golang/prometheus" ) diff --git a/collector/meminfo.go b/collector/meminfo.go index 8437f0f172..b59337ddbd 100644 --- a/collector/meminfo.go +++ b/collector/meminfo.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build (darwin || linux || openbsd) && !nomeminfo -// +build darwin linux openbsd +//go:build (darwin || linux || openbsd || netbsd) && !nomeminfo +// +build darwin linux openbsd netbsd // +build !nomeminfo package collector diff --git a/collector/meminfo_darwin.go b/collector/meminfo_darwin.go index 0c7f64ee83..bbc969370f 100644 --- a/collector/meminfo_darwin.go +++ b/collector/meminfo_darwin.go @@ -68,6 +68,8 @@ func (c *meminfoCollector) getMemInfo() (map[string]float64, error) { "free_bytes": ps * float64(vmstat.free_count), "swapped_in_bytes_total": ps * float64(vmstat.pageins), "swapped_out_bytes_total": ps * float64(vmstat.pageouts), + "internal_bytes": ps * float64(vmstat.internal_page_count), + "purgeable_bytes": ps * float64(vmstat.purgeable_count), "total_bytes": float64(total), "swap_used_bytes": float64(swap.xsu_used), "swap_total_bytes": float64(swap.xsu_total), diff --git a/collector/meminfo_linux_test.go b/collector/meminfo_linux_test.go index dc0aff58d7..a000bea53c 100644 --- a/collector/meminfo_linux_test.go +++ b/collector/meminfo_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nomeminfo +// +build !nomeminfo + package collector import ( diff --git a/collector/meminfo_netbsd.go b/collector/meminfo_netbsd.go new file mode 100644 index 0000000000..a1bd118523 --- /dev/null +++ b/collector/meminfo_netbsd.go @@ -0,0 +1,43 @@ +// Copyright 2023 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 !nomeminfo +// +build !nomeminfo + +package collector + +import ( + "golang.org/x/sys/unix" +) + +func (c *meminfoCollector) getMemInfo() (map[string]float64, error) { + uvmexp, err := unix.SysctlUvmexp("vm.uvmexp2") + if err != nil { + return nil, err + } + + ps := float64(uvmexp.Pagesize) + + // see uvm(9) + return map[string]float64{ + "active_bytes": ps * float64(uvmexp.Active), + "free_bytes": ps * float64(uvmexp.Free), + "inactive_bytes": ps * float64(uvmexp.Inactive), + "size_bytes": ps * float64(uvmexp.Npages), + "swap_size_bytes": ps * float64(uvmexp.Swpages), + "swap_used_bytes": ps * float64(uvmexp.Swpginuse), + "swapped_in_pages_bytes_total": ps * float64(uvmexp.Pgswapin), + "swapped_out_pages_bytes_total": ps * float64(uvmexp.Pgswapout), + "wired_bytes": ps * float64(uvmexp.Wired), + }, nil +} diff --git a/collector/meminfo_numa_linux_test.go b/collector/meminfo_numa_linux_test.go index a17714e8df..33bc362e39 100644 --- a/collector/meminfo_numa_linux_test.go +++ b/collector/meminfo_numa_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nomeminfo_numa +// +build !nomeminfo_numa + package collector import ( diff --git a/collector/meminfo_openbsd.go b/collector/meminfo_openbsd.go index 2c81c50ccd..c5d2947ec7 100644 --- a/collector/meminfo_openbsd.go +++ b/collector/meminfo_openbsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build openbsd && !amd64 && !nomeminfo -// +build openbsd,!amd64,!nomeminfo +//go:build !nomeminfo && !amd64 +// +build !nomeminfo,!amd64 package collector diff --git a/collector/memory_bsd.go b/collector/memory_bsd.go index 5b312691e9..6af9d8aaa4 100644 --- a/collector/memory_bsd.go +++ b/collector/memory_bsd.go @@ -82,6 +82,13 @@ func NewMemoryCollector(logger log.Logger) (Collector, error) { mib: "vm.stats.vm.v_wire_count", conversion: fromPage, }, + { + name: "user_wired_bytes", + description: "Locked in memory by user, mlock, etc", + mib: "vm.stats.vm.v_user_wire_count", + conversion: fromPage, + dataType: bsdSysctlTypeCLong, + }, { name: "cache_bytes", description: "Almost free, backed by swap or files, available for re-allocation", @@ -100,6 +107,12 @@ func NewMemoryCollector(logger log.Logger) (Collector, error) { mib: "vm.stats.vm.v_free_count", conversion: fromPage, }, + { + name: "laundry_bytes", + description: "Dirty not recently used by userland", + mib: "vm.stats.vm.v_laundry_count", + conversion: fromPage, + }, { name: "size_bytes", description: "Total physical memory size", diff --git a/collector/netclass_linux.go b/collector/netclass_linux.go index a1a3fa72d8..5d9324cdee 100644 --- a/collector/netclass_linux.go +++ b/collector/netclass_linux.go @@ -19,19 +19,21 @@ package collector import ( "errors" "fmt" + "net" "os" "regexp" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/sysfs" - "gopkg.in/alecthomas/kingpin.v2" ) var ( netclassIgnoredDevices = kingpin.Flag("collector.netclass.ignored-devices", "Regexp of net devices to ignore for netclass collector.").Default("^$").String() netclassInvalidSpeed = kingpin.Flag("collector.netclass.ignore-invalid-speed", "Ignore devices where the speed is invalid. This will be the default behavior in 2.x.").Bool() + netclassNetlink = kingpin.Flag("collector.netclass.netlink", "Use netlink to gather stats instead of /proc/net/dev.").Default("false").Bool() ) type netClassCollector struct { @@ -63,6 +65,13 @@ func NewNetClassCollector(logger log.Logger) (Collector, error) { } func (c *netClassCollector) Update(ch chan<- prometheus.Metric) error { + if *netclassNetlink { + return c.netClassRTNLUpdate(ch) + } + return c.netClassSysfsUpdate(ch) +} + +func (c *netClassCollector) netClassSysfsUpdate(ch chan<- prometheus.Metric) error { netClass, err := c.getNetClassInfo() if err != nil { if errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission) { @@ -88,98 +97,58 @@ func (c *netClassCollector) Update(ch chan<- prometheus.Metric) error { infoDesc := prometheus.NewDesc( prometheus.BuildFQName(namespace, c.subsystem, "info"), "Non-numeric data from /sys/class/net/, value is always 1.", - []string{"device", "address", "broadcast", "duplex", "operstate", "ifalias"}, + []string{"device", "address", "broadcast", "duplex", "operstate", "adminstate", "ifalias"}, nil, ) infoValue := 1.0 - ch <- prometheus.MustNewConstMetric(infoDesc, prometheus.GaugeValue, infoValue, ifaceInfo.Name, ifaceInfo.Address, ifaceInfo.Broadcast, ifaceInfo.Duplex, ifaceInfo.OperState, ifaceInfo.IfAlias) - - if ifaceInfo.AddrAssignType != nil { - pushMetric(ch, c.subsystem, "address_assign_type", *ifaceInfo.AddrAssignType, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.Carrier != nil { - pushMetric(ch, c.subsystem, "carrier", *ifaceInfo.Carrier, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.CarrierChanges != nil { - pushMetric(ch, c.subsystem, "carrier_changes_total", *ifaceInfo.CarrierChanges, ifaceInfo.Name, prometheus.CounterValue) - } - - if ifaceInfo.CarrierUpCount != nil { - pushMetric(ch, c.subsystem, "carrier_up_changes_total", *ifaceInfo.CarrierUpCount, ifaceInfo.Name, prometheus.CounterValue) - } - - if ifaceInfo.CarrierDownCount != nil { - pushMetric(ch, c.subsystem, "carrier_down_changes_total", *ifaceInfo.CarrierDownCount, ifaceInfo.Name, prometheus.CounterValue) - } - - if ifaceInfo.DevID != nil { - pushMetric(ch, c.subsystem, "device_id", *ifaceInfo.DevID, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.Dormant != nil { - pushMetric(ch, c.subsystem, "dormant", *ifaceInfo.Dormant, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.Flags != nil { - pushMetric(ch, c.subsystem, "flags", *ifaceInfo.Flags, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.IfIndex != nil { - pushMetric(ch, c.subsystem, "iface_id", *ifaceInfo.IfIndex, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.IfLink != nil { - pushMetric(ch, c.subsystem, "iface_link", *ifaceInfo.IfLink, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.LinkMode != nil { - pushMetric(ch, c.subsystem, "iface_link_mode", *ifaceInfo.LinkMode, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.MTU != nil { - pushMetric(ch, c.subsystem, "mtu_bytes", *ifaceInfo.MTU, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.NameAssignType != nil { - pushMetric(ch, c.subsystem, "name_assign_type", *ifaceInfo.NameAssignType, ifaceInfo.Name, prometheus.GaugeValue) - } - - if ifaceInfo.NetDevGroup != nil { - pushMetric(ch, c.subsystem, "net_dev_group", *ifaceInfo.NetDevGroup, ifaceInfo.Name, prometheus.GaugeValue) - } + ch <- prometheus.MustNewConstMetric(infoDesc, prometheus.GaugeValue, infoValue, ifaceInfo.Name, ifaceInfo.Address, ifaceInfo.Broadcast, ifaceInfo.Duplex, ifaceInfo.OperState, getAdminState(ifaceInfo.Flags), ifaceInfo.IfAlias) + + pushMetric(ch, c.getFieldDesc("address_assign_type"), "address_assign_type", ifaceInfo.AddrAssignType, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("carrier"), "carrier", ifaceInfo.Carrier, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("carrier_changes_total"), "carrier_changes_total", ifaceInfo.CarrierChanges, prometheus.CounterValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("carrier_up_changes_total"), "carrier_up_changes_total", ifaceInfo.CarrierUpCount, prometheus.CounterValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("carrier_down_changes_total"), "carrier_down_changes_total", ifaceInfo.CarrierDownCount, prometheus.CounterValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("device_id"), "device_id", ifaceInfo.DevID, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("dormant"), "dormant", ifaceInfo.Dormant, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("flags"), "flags", ifaceInfo.Flags, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("iface_id"), "iface_id", ifaceInfo.IfIndex, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("iface_link"), "iface_link", ifaceInfo.IfLink, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("iface_link_mode"), "iface_link_mode", ifaceInfo.LinkMode, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("mtu_bytes"), "mtu_bytes", ifaceInfo.MTU, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("name_assign_type"), "name_assign_type", ifaceInfo.NameAssignType, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("net_dev_group"), "net_dev_group", ifaceInfo.NetDevGroup, prometheus.GaugeValue, ifaceInfo.Name) if ifaceInfo.Speed != nil { // Some devices return -1 if the speed is unknown. if *ifaceInfo.Speed >= 0 || !*netclassInvalidSpeed { speedBytes := int64(*ifaceInfo.Speed * 1000 * 1000 / 8) - pushMetric(ch, c.subsystem, "speed_bytes", speedBytes, ifaceInfo.Name, prometheus.GaugeValue) + pushMetric(ch, c.getFieldDesc("speed_bytes"), "speed_bytes", speedBytes, prometheus.GaugeValue, ifaceInfo.Name) } } - if ifaceInfo.TxQueueLen != nil { - pushMetric(ch, c.subsystem, "transmit_queue_length", *ifaceInfo.TxQueueLen, ifaceInfo.Name, prometheus.GaugeValue) - } + pushMetric(ch, c.getFieldDesc("transmit_queue_length"), "transmit_queue_length", ifaceInfo.TxQueueLen, prometheus.GaugeValue, ifaceInfo.Name) + pushMetric(ch, c.getFieldDesc("protocol_type"), "protocol_type", ifaceInfo.Type, prometheus.GaugeValue, ifaceInfo.Name) - if ifaceInfo.Type != nil { - pushMetric(ch, c.subsystem, "protocol_type", *ifaceInfo.Type, ifaceInfo.Name, prometheus.GaugeValue) - } } return nil } -func pushMetric(ch chan<- prometheus.Metric, subsystem string, name string, value int64, ifaceName string, valueType prometheus.ValueType) { - fieldDesc := prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, name), - fmt.Sprintf("%s value of /sys/class/net/.", name), - []string{"device"}, - nil, - ) +func (c *netClassCollector) getFieldDesc(name string) *prometheus.Desc { + fieldDesc, exists := c.metricDescs[name] - ch <- prometheus.MustNewConstMetric(fieldDesc, valueType, float64(value), ifaceName) + if !exists { + fieldDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, name), + fmt.Sprintf("Network device property: %s", name), + []string{"device"}, + nil, + ) + c.metricDescs[name] = fieldDesc + } + + return fieldDesc } func (c *netClassCollector) getNetClassInfo() (sysfs.NetClass, error) { @@ -202,3 +171,15 @@ func (c *netClassCollector) getNetClassInfo() (sysfs.NetClass, error) { return netClass, nil } + +func getAdminState(flags *int64) string { + if flags == nil { + return "unknown" + } + + if *flags&int64(net.FlagUp) == 1 { + return "up" + } + + return "down" +} diff --git a/collector/netclass_rtnl_linux.go b/collector/netclass_rtnl_linux.go new file mode 100644 index 0000000000..ef963715e5 --- /dev/null +++ b/collector/netclass_rtnl_linux.go @@ -0,0 +1,230 @@ +// Copyright 2022 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 !nonetclass && linux +// +build !nonetclass,linux + +package collector + +import ( + "errors" + "fmt" + "io/fs" + "path/filepath" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log/level" + "github.com/jsimonetti/rtnetlink" + "github.com/mdlayher/ethtool" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs/sysfs" +) + +var ( + netclassRTNLWithStats = kingpin.Flag("collector.netclass_rtnl.with-stats", "Expose the statistics for each network device, replacing netdev collector.").Bool() + operstateStr = []string{ + "unknown", "notpresent", "down", "lowerlayerdown", "testing", + "dormant", "up", + } +) + +func (c *netClassCollector) netClassRTNLUpdate(ch chan<- prometheus.Metric) error { + linkModes := make(map[string]*ethtool.LinkMode) + lms, err := c.getLinkModes() + if err != nil { + if !errors.Is(errors.Unwrap(err), fs.ErrNotExist) { + return fmt.Errorf("could not get link modes: %w", err) + } + level.Info(c.logger).Log("msg", "ETHTOOL netlink interface unavailable, duplex and linkspeed are not scraped.") + } else { + for _, lm := range lms { + if c.ignoredDevicesPattern.MatchString(lm.Interface.Name) { + continue + } + if lm.SpeedMegabits >= 0 { + speedBytes := uint64(lm.SpeedMegabits * 1000 * 1000 / 8) + pushMetric(ch, c.getFieldDesc("speed_bytes"), "speed_bytes", speedBytes, prometheus.GaugeValue, lm.Interface.Name) + } + linkModes[lm.Interface.Name] = lm + } + } + + // Get most attributes from Netlink + lMsgs, err := c.getNetClassInfoRTNL() + if err != nil { + return fmt.Errorf("could not get net class info: %w", err) + } + + relevantLinks := make([]rtnetlink.LinkMessage, 0, len(lMsgs)) + for _, msg := range lMsgs { + if !c.ignoredDevicesPattern.MatchString(msg.Attributes.Name) { + relevantLinks = append(relevantLinks, msg) + } + } + + // Read sysfs for attributes that Netlink doesn't expose + sysfsAttrs, err := getSysfsAttributes(relevantLinks) + if err != nil { + return fmt.Errorf("could not get sysfs device info: %w", err) + } + + // Parse all the info and update metrics + for _, msg := range relevantLinks { + upDesc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "up"), + "Value is 1 if operstate is 'up', 0 otherwise.", + []string{"device"}, + nil, + ) + upValue := 0.0 + if msg.Attributes.OperationalState == rtnetlink.OperStateUp { + upValue = 1.0 + } + ch <- prometheus.MustNewConstMetric(upDesc, prometheus.GaugeValue, upValue, msg.Attributes.Name) + + infoDesc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "info"), + "Non-numeric data of , value is always 1.", + []string{"device", "address", "broadcast", "duplex", "operstate", "ifalias"}, + nil, + ) + infoValue := 1.0 + + var ifalias = "" + if msg.Attributes.Alias != nil { + ifalias = *msg.Attributes.Alias + } + + duplex := "" + lm, lmExists := linkModes[msg.Attributes.Name] + if lmExists { + duplex = lm.Duplex.String() + } + + ifaceInfo := sysfsAttrs[msg.Attributes.Name] + + ch <- prometheus.MustNewConstMetric(infoDesc, prometheus.GaugeValue, infoValue, msg.Attributes.Name, msg.Attributes.Address.String(), msg.Attributes.Broadcast.String(), duplex, operstateStr[int(msg.Attributes.OperationalState)], ifalias) + + pushMetric(ch, c.getFieldDesc("address_assign_type"), "address_assign_type", ifaceInfo.AddrAssignType, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("carrier"), "carrier", msg.Attributes.Carrier, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("carrier_changes_total"), "carrier_changes_total", msg.Attributes.CarrierChanges, prometheus.CounterValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("carrier_up_changes_total"), "carrier_up_changes_total", msg.Attributes.CarrierUpCount, prometheus.CounterValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("carrier_down_changes_total"), "carrier_down_changes_total", msg.Attributes.CarrierDownCount, prometheus.CounterValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("device_id"), "device_id", ifaceInfo.DevID, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("flags"), "flags", msg.Flags, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("iface_id"), "iface_id", msg.Index, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("iface_link_mode"), "iface_link_mode", msg.Attributes.LinkMode, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("dormant"), "dormant", msg.Attributes.LinkMode, prometheus.GaugeValue, msg.Attributes.Name) + + // kernel logic: IFLA_LINK attribute will be ignore when ifindex is the same as iflink + // (dev->ifindex != dev_get_iflink(dev) && nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) + // As interface ID is never 0, we assume msg.Attributes.Type 0 means iflink is omitted in RTM_GETLINK response. + if msg.Attributes.Type > 0 { + pushMetric(ch, c.getFieldDesc("iface_link"), "iface_link", msg.Attributes.Type, prometheus.GaugeValue, msg.Attributes.Name) + } else { + pushMetric(ch, c.getFieldDesc("iface_link"), "iface_link", msg.Index, prometheus.GaugeValue, msg.Attributes.Name) + } + + pushMetric(ch, c.getFieldDesc("mtu_bytes"), "mtu_bytes", msg.Attributes.MTU, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("name_assign_type"), "name_assign_type", ifaceInfo.NameAssignType, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("net_dev_group"), "net_dev_group", msg.Attributes.NetDevGroup, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_queue_length"), "transmit_queue_length", msg.Attributes.TxQueueLen, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("protocol_type"), "protocol_type", msg.Type, prometheus.GaugeValue, msg.Attributes.Name) + + // Skip statistics if argument collector.netclass_rtnl.with-stats is false or statistics are unavailable. + if netclassRTNLWithStats == nil || !*netclassRTNLWithStats || msg.Attributes.Stats64 == nil { + continue + } + + pushMetric(ch, c.getFieldDesc("receive_packets_total"), "receive_packets_total", msg.Attributes.Stats64.RXPackets, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_packets_total"), "transmit_packets_total", msg.Attributes.Stats64.TXPackets, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_bytes_total"), "receive_bytes_total", msg.Attributes.Stats64.RXBytes, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_bytes_total"), "transmit_bytes_total", msg.Attributes.Stats64.TXBytes, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_errors_total"), "receive_errors_total", msg.Attributes.Stats64.RXErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_errors_total"), "transmit_errors_total", msg.Attributes.Stats64.TXErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_dropped_total"), "receive_dropped_total", msg.Attributes.Stats64.RXDropped, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_dropped_total"), "transmit_dropped_total", msg.Attributes.Stats64.TXDropped, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("multicast_total"), "multicast_total", msg.Attributes.Stats64.Multicast, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("collisions_total"), "collisions_total", msg.Attributes.Stats64.Collisions, prometheus.GaugeValue, msg.Attributes.Name) + + // Detailed rx_errors. + pushMetric(ch, c.getFieldDesc("receive_length_errors_total"), "receive_length_errors_total", msg.Attributes.Stats64.RXLengthErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_over_errors_total"), "receive_over_errors_total", msg.Attributes.Stats64.RXOverErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_crc_errors_total"), "receive_crc_errors_total", msg.Attributes.Stats64.RXCRCErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_frame_errors_total"), "receive_frame_errors_total", msg.Attributes.Stats64.RXFrameErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_fifo_errors_total"), "receive_fifo_errors_total", msg.Attributes.Stats64.RXFIFOErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_missed_errors_total"), "receive_missed_errors_total", msg.Attributes.Stats64.RXMissedErrors, prometheus.GaugeValue, msg.Attributes.Name) + + // Detailed tx_errors. + pushMetric(ch, c.getFieldDesc("transmit_aborted_errors_total"), "transmit_aborted_errors_total", msg.Attributes.Stats64.TXAbortedErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_carrier_errors_total"), "transmit_carrier_errors_total", msg.Attributes.Stats64.TXCarrierErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_fifo_errors_total"), "transmit_fifo_errors_total", msg.Attributes.Stats64.TXFIFOErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_heartbeat_errors_total"), "transmit_heartbeat_errors_total", msg.Attributes.Stats64.TXHeartbeatErrors, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_window_errors_total"), "transmit_window_errors_total", msg.Attributes.Stats64.TXWindowErrors, prometheus.GaugeValue, msg.Attributes.Name) + + // For cslip, etc. + pushMetric(ch, c.getFieldDesc("receive_compressed_total"), "receive_compressed_total", msg.Attributes.Stats64.RXCompressed, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("transmit_compressed_total"), "transmit_compressed_total", msg.Attributes.Stats64.TXCompressed, prometheus.GaugeValue, msg.Attributes.Name) + pushMetric(ch, c.getFieldDesc("receive_nohandler_total"), "receive_nohandler_total", msg.Attributes.Stats64.RXNoHandler, prometheus.GaugeValue, msg.Attributes.Name) + + } + + return nil +} + +func (c *netClassCollector) getNetClassInfoRTNL() ([]rtnetlink.LinkMessage, error) { + conn, err := rtnetlink.Dial(nil) + if err != nil { + return nil, err + } + defer conn.Close() + + lMsgs, err := conn.Link.List() + + return lMsgs, err + +} + +func (c *netClassCollector) getLinkModes() ([]*ethtool.LinkMode, error) { + conn, err := ethtool.New() + if err != nil { + return nil, err + } + defer conn.Close() + + lms, err := conn.LinkModes() + + return lms, err +} + +// getSysfsAttributes reads attributes that are absent from netlink but provided +// by sysfs. +func getSysfsAttributes(links []rtnetlink.LinkMessage) (sysfs.NetClass, error) { + netClass := sysfs.NetClass{} + for _, msg := range links { + interfaceClass := sysfs.NetClassIface{} + ifName := msg.Attributes.Name + devPath := filepath.Join("/sys", "class", "net", ifName) + + // These three attributes hold a device-specific lock when + // accessed, not the RTNL lock, so they are much less impactful + // than reading most of the other attributes from sysfs. + for _, attr := range []string{"addr_assign_type", "dev_id", "name_assign_type"} { + if err := sysfs.ParseNetClassAttribute(devPath, attr, &interfaceClass); err != nil { + return nil, err + } + } + netClass[ifName] = interfaceClass + } + return netClass, nil +} diff --git a/collector/netdev_bsd.go b/collector/netdev_bsd.go index d472b2dfeb..691bbec4ad 100644 --- a/collector/netdev_bsd.go +++ b/collector/netdev_bsd.go @@ -34,7 +34,7 @@ import ( */ import "C" -func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error) { +func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { netDev := netDevStats{} var ifap, ifa *C.struct_ifaddrs @@ -59,14 +59,14 @@ func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error netDev[dev] = map[string]uint64{ "receive_packets": uint64(data.ifi_ipackets), "transmit_packets": uint64(data.ifi_opackets), - "receive_errs": uint64(data.ifi_ierrors), - "transmit_errs": uint64(data.ifi_oerrors), "receive_bytes": uint64(data.ifi_ibytes), "transmit_bytes": uint64(data.ifi_obytes), + "receive_errors": uint64(data.ifi_ierrors), + "transmit_errors": uint64(data.ifi_oerrors), + "receive_dropped": uint64(data.ifi_iqdrops), + "transmit_dropped": uint64(data.ifi_oqdrops), "receive_multicast": uint64(data.ifi_imcasts), "transmit_multicast": uint64(data.ifi_omcasts), - "receive_drop": uint64(data.ifi_iqdrops), - "transmit_drop": uint64(data.ifi_oqdrops), } } diff --git a/collector/netdev_common.go b/collector/netdev_common.go index 0b40b99284..089f1e5870 100644 --- a/collector/netdev_common.go +++ b/collector/netdev_common.go @@ -22,11 +22,12 @@ import ( "fmt" "net" "strconv" + "sync" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) var ( @@ -35,13 +36,15 @@ var ( netdevDeviceExclude = kingpin.Flag("collector.netdev.device-exclude", "Regexp of net devices to exclude (mutually exclusive to device-include).").String() oldNetdevDeviceExclude = kingpin.Flag("collector.netdev.device-blacklist", "DEPRECATED: Use collector.netdev.device-exclude").Hidden().String() netdevAddressInfo = kingpin.Flag("collector.netdev.address-info", "Collect address-info for every device").Bool() + netdevDetailedMetrics = kingpin.Flag("collector.netdev.enable-detailed-metrics", "Use (incompatible) metric names that provide more detailed stats on Linux").Bool() ) type netDevCollector struct { - subsystem string - deviceFilter netDevFilter - metricDescs map[string]*prometheus.Desc - logger log.Logger + subsystem string + deviceFilter deviceFilter + metricDescsMutex sync.Mutex + metricDescs map[string]*prometheus.Desc + logger log.Logger } type netDevStats map[string]map[string]uint64 @@ -84,29 +87,39 @@ func NewNetDevCollector(logger log.Logger) (Collector, error) { return &netDevCollector{ subsystem: "network", - deviceFilter: newNetDevFilter(*netdevDeviceExclude, *netdevDeviceInclude), + deviceFilter: newDeviceFilter(*netdevDeviceExclude, *netdevDeviceInclude), metricDescs: map[string]*prometheus.Desc{}, logger: logger, }, nil } +func (c *netDevCollector) metricDesc(key string) *prometheus.Desc { + c.metricDescsMutex.Lock() + defer c.metricDescsMutex.Unlock() + + if _, ok := c.metricDescs[key]; !ok { + c.metricDescs[key] = prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, key+"_total"), + fmt.Sprintf("Network device statistic %s.", key), + []string{"device"}, + nil, + ) + } + + return c.metricDescs[key] +} + func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error { netDev, err := getNetDevStats(&c.deviceFilter, c.logger) if err != nil { return fmt.Errorf("couldn't get netstats: %w", err) } for dev, devStats := range netDev { + if !*netdevDetailedMetrics { + legacy(devStats) + } for key, value := range devStats { - desc, ok := c.metricDescs[key] - if !ok { - desc = prometheus.NewDesc( - prometheus.BuildFQName(namespace, c.subsystem, key+"_total"), - fmt.Sprintf("Network device statistic %s.", key), - []string{"device"}, - nil, - ) - c.metricDescs[key] = desc - } + desc := c.metricDesc(key) ch <- prometheus.MustNewConstMetric(desc, prometheus.CounterValue, float64(value), dev) } } @@ -175,3 +188,54 @@ func getAddrsInfo(interfaces []net.Interface) []addrInfo { return res } + +// https://github.com/torvalds/linux/blob/master/net/core/net-procfs.c#L75-L97 +func legacy(metrics map[string]uint64) { + if metric, ok := pop(metrics, "receive_errors"); ok { + metrics["receive_errs"] = metric + } + if metric, ok := pop(metrics, "receive_dropped"); ok { + metrics["receive_drop"] = metric + popz(metrics, "receive_missed_errors") + } + if metric, ok := pop(metrics, "receive_fifo_errors"); ok { + metrics["receive_fifo"] = metric + } + if metric, ok := pop(metrics, "receive_frame_errors"); ok { + metrics["receive_frame"] = metric + popz(metrics, "receive_length_errors") + popz(metrics, "receive_over_errors") + popz(metrics, "receive_crc_errors") + } + if metric, ok := pop(metrics, "multicast"); ok { + metrics["receive_multicast"] = metric + } + if metric, ok := pop(metrics, "transmit_errors"); ok { + metrics["transmit_errs"] = metric + } + if metric, ok := pop(metrics, "transmit_dropped"); ok { + metrics["transmit_drop"] = metric + } + if metric, ok := pop(metrics, "transmit_fifo_errors"); ok { + metrics["transmit_fifo"] = metric + } + if metric, ok := pop(metrics, "multicast"); ok { + metrics["receive_multicast"] = metric + } + if metric, ok := pop(metrics, "collisions"); ok { + metrics["transmit_colls"] = metric + } + if metric, ok := pop(metrics, "transmit_carrier_errors"); ok { + metrics["transmit_carrier"] = metric + popz(metrics, "transmit_aborted_errors") + popz(metrics, "transmit_heartbeat_errors") + popz(metrics, "transmit_window_errors") + } +} + +func pop(m map[string]uint64, key string) (uint64, bool) { + value, ok := m[key] + delete(m, key) + return value, ok +} + +func popz(m map[string]uint64, key string) uint64 { + if value, ok := m[key]; ok { + delete(m, key) + return value + } + return 0 +} diff --git a/collector/netdev_darwin.go b/collector/netdev_darwin.go index 0f83a60665..c08f1f8ede 100644 --- a/collector/netdev_darwin.go +++ b/collector/netdev_darwin.go @@ -27,7 +27,7 @@ import ( "golang.org/x/sys/unix" ) -func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error) { +func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { netDev := netDevStats{} ifs, err := net.Interfaces() @@ -50,12 +50,15 @@ func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error netDev[iface.Name] = map[string]uint64{ "receive_packets": ifaceData.Data.Ipackets, "transmit_packets": ifaceData.Data.Opackets, - "receive_errs": ifaceData.Data.Ierrors, - "transmit_errs": ifaceData.Data.Oerrors, "receive_bytes": ifaceData.Data.Ibytes, "transmit_bytes": ifaceData.Data.Obytes, + "receive_errors": ifaceData.Data.Ierrors, + "transmit_errors": ifaceData.Data.Oerrors, + "receive_dropped": ifaceData.Data.Iqdrops, "receive_multicast": ifaceData.Data.Imcasts, "transmit_multicast": ifaceData.Data.Omcasts, + "collisions": ifaceData.Data.Collisions, + "noproto": ifaceData.Data.Noproto, } } @@ -87,6 +90,7 @@ type ifMsghdr2 struct { Data ifData64 } +// https://github.com/apple/darwin-xnu/blob/main/bsd/net/if_var.h#L199-L231 type ifData64 struct { Type uint8 Typelen uint8 diff --git a/collector/netdev_linux.go b/collector/netdev_linux.go index e825db0855..f3348cda73 100644 --- a/collector/netdev_linux.go +++ b/collector/netdev_linux.go @@ -17,86 +17,170 @@ package collector import ( - "bufio" "fmt" - "io" - "os" - "regexp" - "strconv" - "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/jsimonetti/rtnetlink" + "github.com/prometheus/procfs" ) var ( - procNetDevInterfaceRE = regexp.MustCompile(`^(.+): *(.+)$`) - procNetDevFieldSep = regexp.MustCompile(` +`) + netDevNetlink = kingpin.Flag("collector.netdev.netlink", "Use netlink to gather stats instead of /proc/net/dev.").Default("true").Bool() ) -func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error) { - file, err := os.Open(procFilePath("net/dev")) +func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { + if *netDevNetlink { + return netlinkStats(filter, logger) + } + return procNetDevStats(filter, logger) +} + +func netlinkStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { + conn, err := rtnetlink.Dial(nil) + if err != nil { + return nil, err + } + + defer conn.Close() + links, err := conn.Link.List() if err != nil { return nil, err } - defer file.Close() - return parseNetDevStats(file, filter, logger) + return parseNetlinkStats(links, filter, logger), nil } -func parseNetDevStats(r io.Reader, filter *netDevFilter, logger log.Logger) (netDevStats, error) { - scanner := bufio.NewScanner(r) - scanner.Scan() // skip first header - scanner.Scan() - parts := strings.Split(scanner.Text(), "|") - if len(parts) != 3 { // interface + receive + transmit - return nil, fmt.Errorf("invalid header line in net/dev: %s", - scanner.Text()) - } +func parseNetlinkStats(links []rtnetlink.LinkMessage, filter *deviceFilter, logger log.Logger) netDevStats { + metrics := netDevStats{} - receiveHeader := strings.Fields(parts[1]) - transmitHeader := strings.Fields(parts[2]) - headerLength := len(receiveHeader) + len(transmitHeader) + for _, msg := range links { + if msg.Attributes == nil { + level.Debug(logger).Log("msg", "No netlink attributes, skipping") + continue + } + name := msg.Attributes.Name + stats := msg.Attributes.Stats64 + if stats32 := msg.Attributes.Stats; stats == nil && stats32 != nil { + stats = &rtnetlink.LinkStats64{ + RXPackets: uint64(stats32.RXPackets), + TXPackets: uint64(stats32.TXPackets), + RXBytes: uint64(stats32.RXBytes), + TXBytes: uint64(stats32.TXBytes), + RXErrors: uint64(stats32.RXErrors), + TXErrors: uint64(stats32.TXErrors), + RXDropped: uint64(stats32.RXDropped), + TXDropped: uint64(stats32.TXDropped), + Multicast: uint64(stats32.Multicast), + Collisions: uint64(stats32.Collisions), + RXLengthErrors: uint64(stats32.RXLengthErrors), + RXOverErrors: uint64(stats32.RXOverErrors), + RXCRCErrors: uint64(stats32.RXCRCErrors), + RXFrameErrors: uint64(stats32.RXFrameErrors), + RXFIFOErrors: uint64(stats32.RXFIFOErrors), + RXMissedErrors: uint64(stats32.RXMissedErrors), + TXAbortedErrors: uint64(stats32.TXAbortedErrors), + TXCarrierErrors: uint64(stats32.TXCarrierErrors), + TXFIFOErrors: uint64(stats32.TXFIFOErrors), + TXHeartbeatErrors: uint64(stats32.TXHeartbeatErrors), + TXWindowErrors: uint64(stats32.TXWindowErrors), + RXCompressed: uint64(stats32.RXCompressed), + TXCompressed: uint64(stats32.TXCompressed), + RXNoHandler: uint64(stats32.RXNoHandler), + RXOtherhostDropped: 0, + } + } - netDev := netDevStats{} - for scanner.Scan() { - line := strings.TrimLeft(scanner.Text(), " ") - parts := procNetDevInterfaceRE.FindStringSubmatch(line) - if len(parts) != 3 { - return nil, fmt.Errorf("couldn't get interface name, invalid line in net/dev: %q", line) + if filter.ignored(name) { + level.Debug(logger).Log("msg", "Ignoring device", "device", name) + continue } - dev := parts[1] - if filter.ignored(dev) { - level.Debug(logger).Log("msg", "Ignoring device", "device", dev) + // Make sure we don't panic when accessing `stats` attributes below. + if stats == nil { + level.Debug(logger).Log("msg", "No netlink stats, skipping") continue } - values := procNetDevFieldSep.Split(strings.TrimLeft(parts[2], " "), -1) - if len(values) != headerLength { - return nil, fmt.Errorf("couldn't get values, invalid line in net/dev: %q", parts[2]) + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h#L42-L246 + metrics[name] = map[string]uint64{ + "receive_packets": stats.RXPackets, + "transmit_packets": stats.TXPackets, + "receive_bytes": stats.RXBytes, + "transmit_bytes": stats.TXBytes, + "receive_errors": stats.RXErrors, + "transmit_errors": stats.TXErrors, + "receive_dropped": stats.RXDropped, + "transmit_dropped": stats.TXDropped, + "multicast": stats.Multicast, + "collisions": stats.Collisions, + + // detailed rx_errors + "receive_length_errors": stats.RXLengthErrors, + "receive_over_errors": stats.RXOverErrors, + "receive_crc_errors": stats.RXCRCErrors, + "receive_frame_errors": stats.RXFrameErrors, + "receive_fifo_errors": stats.RXFIFOErrors, + "receive_missed_errors": stats.RXMissedErrors, + + // detailed tx_errors + "transmit_aborted_errors": stats.TXAbortedErrors, + "transmit_carrier_errors": stats.TXCarrierErrors, + "transmit_fifo_errors": stats.TXFIFOErrors, + "transmit_heartbeat_errors": stats.TXHeartbeatErrors, + "transmit_window_errors": stats.TXWindowErrors, + + // for cslip etc + "receive_compressed": stats.RXCompressed, + "transmit_compressed": stats.TXCompressed, + "receive_nohandler": stats.RXNoHandler, } + } - devStats := map[string]uint64{} - addStats := func(key, value string) { - v, err := strconv.ParseUint(value, 0, 64) - if err != nil { - level.Debug(logger).Log("msg", "invalid value in netstats", "key", key, "value", value, "err", err) - return - } + return metrics +} - devStats[key] = v - } +func procNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { + metrics := netDevStats{} - for i := 0; i < len(receiveHeader); i++ { - addStats("receive_"+receiveHeader[i], values[i]) - } + fs, err := procfs.NewFS(*procPath) + if err != nil { + return metrics, fmt.Errorf("failed to open procfs: %w", err) + } - for i := 0; i < len(transmitHeader); i++ { - addStats("transmit_"+transmitHeader[i], values[i+len(receiveHeader)]) + netDev, err := fs.NetDev() + if err != nil { + return metrics, fmt.Errorf("failed to parse /proc/net/dev: %w", err) + } + + for _, stats := range netDev { + name := stats.Name + + if filter.ignored(name) { + level.Debug(logger).Log("msg", "Ignoring device", "device", name) + continue } - netDev[dev] = devStats + metrics[name] = map[string]uint64{ + "receive_bytes": stats.RxBytes, + "receive_packets": stats.RxPackets, + "receive_errors": stats.RxErrors, + "receive_dropped": stats.RxDropped, + "receive_fifo": stats.RxFIFO, + "receive_frame": stats.RxFrame, + "receive_compressed": stats.RxCompressed, + "receive_multicast": stats.RxMulticast, + "transmit_bytes": stats.TxBytes, + "transmit_packets": stats.TxPackets, + "transmit_errors": stats.TxErrors, + "transmit_dropped": stats.TxDropped, + "transmit_fifo": stats.TxFIFO, + "transmit_colls": stats.TxCollisions, + "transmit_carrier": stats.TxCarrier, + "transmit_compressed": stats.TxCompressed, + } } - return netDev, scanner.Err() + + return metrics, nil } diff --git a/collector/netdev_linux_test.go b/collector/netdev_linux_test.go index 8e227a2463..7909d01821 100644 --- a/collector/netdev_linux_test.go +++ b/collector/netdev_linux_test.go @@ -11,28 +11,162 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nonetdev +// +build !nonetdev + package collector import ( - "os" "testing" "github.com/go-kit/log" + + "github.com/jsimonetti/rtnetlink" ) -func TestNetDevStatsIgnore(t *testing.T) { - file, err := os.Open("fixtures/proc/net/dev") - if err != nil { - t.Fatal(err) - } - defer file.Close() +var links = []rtnetlink.LinkMessage{ + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "tun0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 24, + TXPackets: 934, + RXBytes: 1888, + TXBytes: 67120, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "veth4B09XN", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 8, + TXPackets: 10640, + RXBytes: 648, + TXBytes: 1943284, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "lo", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 1832522, + TXPackets: 1832522, + RXBytes: 435303245, + TXBytes: 435303245, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "eth0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 520993275, + TXPackets: 43451486, + RXBytes: 68210035552, + TXBytes: 9315587528, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "lxcbr0", + Stats64: &rtnetlink.LinkStats64{ + TXPackets: 28339, + TXBytes: 2630299, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "wlan0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 13899359, + TXPackets: 11726200, + RXBytes: 10437182923, + TXBytes: 2851649360, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "docker0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 1065585, + TXPackets: 1929779, + RXBytes: 64910168, + TXBytes: 2681662018, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "ibr10:30", + Stats64: &rtnetlink.LinkStats64{}, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "flannel.1", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 228499337, + TXPackets: 258369223, + RXBytes: 18144009813, + TXBytes: 20758990068, + TXDropped: 64, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "💩0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 105557, + TXPackets: 304261, + RXBytes: 57750104, + TXBytes: 404570255, + Multicast: 72, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "enp0s0f0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 226, + TXPackets: 803, + RXBytes: 231424, + TXBytes: 822272, + RXErrors: 14, + TXErrors: 2, + RXDropped: 10, + TXDropped: 17, + Multicast: 285, + Collisions: 30, + RXLengthErrors: 5, + RXOverErrors: 3, + RXCRCErrors: 1, + RXFrameErrors: 4, + RXFIFOErrors: 6, + RXMissedErrors: 21, + TXAbortedErrors: 22, + TXCarrierErrors: 7, + TXFIFOErrors: 24, + TXHeartbeatErrors: 9, + TXWindowErrors: 19, + RXCompressed: 23, + TXCompressed: 20, + RXNoHandler: 62, + }, + }, + }, +} - filter := newNetDevFilter("^veth", "") +func TestNetDevStatsIgnore(t *testing.T) { + filter := newDeviceFilter("^veth", "") - netStats, err := parseNetDevStats(file, &filter, log.NewNopLogger()) - if err != nil { - t.Fatal(err) - } + netStats := parseNetlinkStats(links, &filter, log.NewNopLogger()) if want, got := uint64(10437182923), netStats["wlan0"]["receive_bytes"]; want != got { t.Errorf("want netstat wlan0 bytes %v, got %v", want, got) @@ -46,7 +180,7 @@ func TestNetDevStatsIgnore(t *testing.T) { t.Errorf("want netstat tun0 packets %v, got %v", want, got) } - if want, got := 9, len(netStats); want != got { + if want, got := 10, len(netStats); want != got { t.Errorf("want count of devices to be %d, got %d", want, got) } @@ -58,28 +192,150 @@ func TestNetDevStatsIgnore(t *testing.T) { t.Error("want fixture interface ibr10:30 to exist, but it does not") } - if want, got := uint64(72), netStats["💩0"]["receive_multicast"]; want != got { + if want, got := uint64(72), netStats["💩0"]["multicast"]; want != got { t.Error("want fixture interface 💩0 to exist, but it does not") } } func TestNetDevStatsAccept(t *testing.T) { - file, err := os.Open("fixtures/proc/net/dev") - if err != nil { - t.Fatal(err) - } - defer file.Close() - - filter := newNetDevFilter("", "^💩0$") - netStats, err := parseNetDevStats(file, &filter, log.NewNopLogger()) - if err != nil { - t.Fatal(err) - } + filter := newDeviceFilter("", "^💩0$") + netStats := parseNetlinkStats(links, &filter, log.NewNopLogger()) if want, got := 1, len(netStats); want != got { t.Errorf("want count of devices to be %d, got %d", want, got) } - if want, got := uint64(72), netStats["💩0"]["receive_multicast"]; want != got { + if want, got := uint64(72), netStats["💩0"]["multicast"]; want != got { t.Error("want fixture interface 💩0 to exist, but it does not") } } + +func TestNetDevLegacyMetricNames(t *testing.T) { + expected := []string{ + "receive_packets", + "transmit_packets", + "receive_bytes", + "transmit_bytes", + "receive_errs", + "transmit_errs", + "receive_drop", + "transmit_drop", + "receive_multicast", + "transmit_colls", + "receive_frame", + "receive_fifo", + "transmit_carrier", + "transmit_fifo", + "receive_compressed", + "transmit_compressed", + } + + filter := newDeviceFilter("", "") + netStats := parseNetlinkStats(links, &filter, log.NewNopLogger()) + + for dev, devStats := range netStats { + legacy(devStats) + for _, name := range expected { + if _, ok := devStats[name]; !ok { + t.Errorf("metric %s should be defined on interface %s", name, dev) + } + } + } +} + +func TestNetDevLegacyMetricValues(t *testing.T) { + expected := map[string]uint64{ + "receive_packets": 226, + "transmit_packets": 803, + "receive_bytes": 231424, + "transmit_bytes": 822272, + "receive_errs": 14, + "transmit_errs": 2, + "receive_drop": 10 + 21, + "transmit_drop": 17, + "receive_multicast": 285, + "transmit_colls": 30, + "receive_frame": 5 + 3 + 1 + 4, + "receive_fifo": 6, + "transmit_carrier": 22 + 7 + 9 + 19, + "transmit_fifo": 24, + "receive_compressed": 23, + "transmit_compressed": 20, + } + + filter := newDeviceFilter("", "^enp0s0f0$") + netStats := parseNetlinkStats(links, &filter, log.NewNopLogger()) + metrics, ok := netStats["enp0s0f0"] + if !ok { + t.Error("expected stats for interface enp0s0f0") + } + + legacy(metrics) + + for name, want := range expected { + got, ok := metrics[name] + if !ok { + t.Errorf("metric %s should be defined on interface enp0s0f0", name) + continue + } + if want != got { + t.Errorf("want %s %d, got %d", name, want, got) + } + } +} + +func TestNetDevMetricValues(t *testing.T) { + filter := newDeviceFilter("", "") + netStats := parseNetlinkStats(links, &filter, log.NewNopLogger()) + + for _, msg := range links { + device := msg.Attributes.Name + stats := msg.Attributes.Stats64 + + expected := map[string]uint64{ + "receive_packets": stats.RXPackets, + "transmit_packets": stats.TXPackets, + "receive_bytes": stats.RXBytes, + "transmit_bytes": stats.TXBytes, + "receive_errors": stats.RXErrors, + "transmit_errors": stats.TXErrors, + "receive_dropped": stats.RXDropped, + "transmit_dropped": stats.TXDropped, + "multicast": stats.Multicast, + "collisions": stats.Collisions, + + // detailed rx_errors + "receive_length_errors": stats.RXLengthErrors, + "receive_over_errors": stats.RXOverErrors, + "receive_crc_errors": stats.RXCRCErrors, + "receive_frame_errors": stats.RXFrameErrors, + "receive_fifo_errors": stats.RXFIFOErrors, + "receive_missed_errors": stats.RXMissedErrors, + + // detailed tx_errors + "transmit_aborted_errors": stats.TXAbortedErrors, + "transmit_carrier_errors": stats.TXCarrierErrors, + "transmit_fifo_errors": stats.TXFIFOErrors, + "transmit_heartbeat_errors": stats.TXHeartbeatErrors, + "transmit_window_errors": stats.TXWindowErrors, + + // for cslip etc + "receive_compressed": stats.RXCompressed, + "transmit_compressed": stats.TXCompressed, + "receive_nohandler": stats.RXNoHandler, + } + + for name, want := range expected { + devStats, ok := netStats[device] + if !ok { + t.Errorf("expected stats for interface %s", device) + } + got, ok := devStats[name] + if !ok { + t.Errorf("metric %s should be defined on interface %s", name, device) + } + if want != got { + t.Errorf("want %s %d, got %d", name, want, got) + } + } + } +} diff --git a/collector/netdev_openbsd.go b/collector/netdev_openbsd.go index 2be10a3d6c..b90e3ba7ab 100644 --- a/collector/netdev_openbsd.go +++ b/collector/netdev_openbsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build openbsd && !amd64 && !nonetdev -// +build openbsd,!amd64,!nonetdev +//go:build !nonetdev && !amd64 +// +build !nonetdev,!amd64 package collector @@ -31,7 +31,7 @@ import ( */ import "C" -func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error) { +func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { netDev := netDevStats{} var ifap, ifa *C.struct_ifaddrs @@ -53,16 +53,20 @@ func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error data := (*C.struct_if_data)(ifa.ifa_data) + // https://github.com/openbsd/src/blob/master/sys/net/if.h#L101-L126 netDev[dev] = map[string]uint64{ "receive_packets": uint64(data.ifi_ipackets), "transmit_packets": uint64(data.ifi_opackets), - "receive_errs": uint64(data.ifi_ierrors), - "transmit_errs": uint64(data.ifi_oerrors), "receive_bytes": uint64(data.ifi_ibytes), "transmit_bytes": uint64(data.ifi_obytes), + "receive_errors": uint64(data.ifi_ierrors), + "transmit_errors": uint64(data.ifi_oerrors), + "receive_dropped": uint64(data.ifi_iqdrops), + "transmit_dropped": uint64(data.ifi_oqdrops), "receive_multicast": uint64(data.ifi_imcasts), "transmit_multicast": uint64(data.ifi_omcasts), - "receive_drop": uint64(data.ifi_iqdrops), + "collisions": uint64(data.ifi_collisions), + "noproto": uint64(data.ifi_noproto), } } diff --git a/collector/netdev_openbsd_amd64.go b/collector/netdev_openbsd_amd64.go index 8b2bfa0e73..da8a81f34e 100644 --- a/collector/netdev_openbsd_amd64.go +++ b/collector/netdev_openbsd_amd64.go @@ -24,7 +24,7 @@ import ( "unsafe" ) -func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error) { +func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { netDev := netDevStats{} mib := [6]_C_int{unix.CTL_NET, unix.AF_ROUTE, 0, 0, unix.NET_RT_IFLIST, 0} @@ -58,16 +58,20 @@ func getNetDevStats(filter *netDevFilter, logger log.Logger) (netDevStats, error continue } + // https://cs.opensource.google/go/x/sys/+/master:unix/ztypes_openbsd_amd64.go;l=292-316 netDev[dev] = map[string]uint64{ "receive_packets": data.Ipackets, "transmit_packets": data.Opackets, - "receive_errs": data.Ierrors, - "transmit_errs": data.Oerrors, "receive_bytes": data.Ibytes, "transmit_bytes": data.Obytes, + "receive_errors": data.Ierrors, + "transmit_errors": data.Oerrors, + "receive_dropped": data.Iqdrops, + "transmit_dropped": data.Oqdrops, "receive_multicast": data.Imcasts, "transmit_multicast": data.Omcasts, - "receive_drop": data.Iqdrops, + "collisions": data.Collisions, + "noproto": data.Noproto, } } return netDev, nil diff --git a/collector/netisr_freebsd.go b/collector/netisr_freebsd.go new file mode 100644 index 0000000000..442bcdc6a7 --- /dev/null +++ b/collector/netisr_freebsd.go @@ -0,0 +1,105 @@ +// Copyright 2023 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 !nonetisr +// +build !nonetisr + +package collector + +import ( + "fmt" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" +) + +type netisrCollector struct { + sysctls []bsdSysctl + logger log.Logger +} + +const ( + netisrCollectorSubsystem = "netisr" +) + +func init() { + registerCollector("netisr", defaultEnabled, NewNetisrCollector) +} + +func NewNetisrCollector(logger log.Logger) (Collector, error) { + return &netisrCollector{ + sysctls: []bsdSysctl{ + { + name: "numthreads", + description: "netisr current thread count", + mib: "net.isr.numthreads", + dataType: bsdSysctlTypeUint32, + valueType: prometheus.GaugeValue, + }, + { + name: "maxprot", + description: "netisr maximum protocols", + mib: "net.isr.maxprot", + dataType: bsdSysctlTypeUint32, + valueType: prometheus.GaugeValue, + }, + { + name: "defaultqlimit", + description: "netisr default queue limit", + mib: "net.isr.defaultqlimit", + dataType: bsdSysctlTypeUint32, + valueType: prometheus.GaugeValue, + }, + { + name: "maxqlimit", + description: "netisr maximum queue limit", + mib: "net.isr.maxqlimit", + dataType: bsdSysctlTypeUint32, + valueType: prometheus.GaugeValue, + }, + { + name: "bindthreads", + description: "netisr threads bound to CPUs", + mib: "net.isr.bindthreads", + dataType: bsdSysctlTypeUint32, + valueType: prometheus.GaugeValue, + }, + { + name: "maxthreads", + description: "netisr maximum thread count", + mib: "net.isr.maxthreads", + dataType: bsdSysctlTypeUint32, + valueType: prometheus.GaugeValue, + }, + }, + logger: logger, + }, nil +} + +func (c *netisrCollector) Update(ch chan<- prometheus.Metric) error { + for _, m := range c.sysctls { + v, err := m.Value() + if err != nil { + return fmt.Errorf("couldn't get sysctl: %w", err) + } + + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(namespace, netisrCollectorSubsystem, m.name), + m.description, + nil, nil, + ), m.valueType, v) + } + + return nil +} diff --git a/collector/netstat_linux.go b/collector/netstat_linux.go index 28a97fba43..8e4c9f4de8 100644 --- a/collector/netstat_linux.go +++ b/collector/netstat_linux.go @@ -26,9 +26,9 @@ import ( "strconv" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) const ( @@ -36,7 +36,7 @@ const ( ) var ( - netStatFields = kingpin.Flag("collector.netstat.fields", "Regexp of fields to return for netstat collector.").Default("^(.*_(InErrors|InErrs)|Ip_Forwarding|Ip(6|Ext)_(InOctets|OutOctets)|Icmp6?_(InMsgs|OutMsgs)|TcpExt_(Listen.*|Syncookies.*|TCPSynRetrans)|Tcp_(ActiveOpens|InSegs|OutSegs|OutRsts|PassiveOpens|RetransSegs|CurrEstab)|Udp6?_(InDatagrams|OutDatagrams|NoPorts|RcvbufErrors|SndbufErrors))$").String() + netStatFields = kingpin.Flag("collector.netstat.fields", "Regexp of fields to return for netstat collector.").Default("^(.*_(InErrors|InErrs)|Ip_Forwarding|Ip(6|Ext)_(InOctets|OutOctets)|Icmp6?_(InMsgs|OutMsgs)|TcpExt_(Listen.*|Syncookies.*|TCPSynRetrans|TCPTimeouts|TCPOFOQueue)|Tcp_(ActiveOpens|InSegs|OutSegs|OutRsts|PassiveOpens|RetransSegs|CurrEstab)|Udp6?_(InDatagrams|OutDatagrams|NoPorts|RcvbufErrors|SndbufErrors))$").String() ) type netStatCollector struct { diff --git a/collector/netstat_linux_test.go b/collector/netstat_linux_test.go index a27382b416..ec430bc3e3 100644 --- a/collector/netstat_linux_test.go +++ b/collector/netstat_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nonetstat +// +build !nonetstat + package collector import ( diff --git a/collector/nfsd_linux.go b/collector/nfsd_linux.go index faa6c960b3..8b310ea23c 100644 --- a/collector/nfsd_linux.go +++ b/collector/nfsd_linux.go @@ -82,6 +82,8 @@ func (c *nfsdCollector) Update(ch chan<- prometheus.Metric) error { c.updateNFSdRequestsv2Stats(ch, &stats.V2Stats) c.updateNFSdRequestsv3Stats(ch, &stats.V3Stats) c.updateNFSdRequestsv4Stats(ch, &stats.V4Ops) + ch <- prometheus.MustNewConstMetric(c.requestsDesc, prometheus.CounterValue, + float64(stats.WdelegGetattr), "4", "WdelegGetattr") return nil } @@ -395,6 +397,10 @@ func (c *nfsdCollector) updateNFSdRequestsv4Stats(ch chan<- prometheus.Metric, s float64(s.SecInfo), proto, "SecInfo") ch <- prometheus.MustNewConstMetric(c.requestsDesc, prometheus.CounterValue, float64(s.SetAttr), proto, "SetAttr") + ch <- prometheus.MustNewConstMetric(c.requestsDesc, prometheus.CounterValue, + float64(s.SetClientID), proto, "SetClientID") + ch <- prometheus.MustNewConstMetric(c.requestsDesc, prometheus.CounterValue, + float64(s.SetClientIDConfirm), proto, "SetClientIDConfirm") ch <- prometheus.MustNewConstMetric(c.requestsDesc, prometheus.CounterValue, float64(s.Verify), proto, "Verify") ch <- prometheus.MustNewConstMetric(c.requestsDesc, prometheus.CounterValue, diff --git a/collector/ntp.go b/collector/ntp.go index 25cb9452e8..8b8db8a950 100644 --- a/collector/ntp.go +++ b/collector/ntp.go @@ -22,10 +22,11 @@ import ( "sync" "time" + "github.com/alecthomas/kingpin/v2" "github.com/beevik/ntp" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) const ( @@ -35,6 +36,7 @@ const ( var ( ntpServer = kingpin.Flag("collector.ntp.server", "NTP server to use for ntp collector").Default("127.0.0.1").String() + ntpServerPort = kingpin.Flag("collector.ntp.server-port", "UDP port number to connect to on NTP server").Default("123").Int() ntpProtocolVersion = kingpin.Flag("collector.ntp.protocol-version", "NTP protocol version").Default("4").Int() ntpServerIsLocal = kingpin.Flag("collector.ntp.server-is-local", "Certify that collector.ntp.server address is not a public ntp server").Default("false").Bool() ntpIPTTL = kingpin.Flag("collector.ntp.ip-ttl", "IP TTL to use while sending NTP query").Default("1").Int() @@ -74,6 +76,11 @@ func NewNtpCollector(logger log.Logger) (Collector, error) { return nil, fmt.Errorf("offset tolerance must be non-negative") } + if *ntpServerPort < 1 || *ntpServerPort > 65535 { + return nil, fmt.Errorf("invalid NTP port number %d; must be between 1 and 65535 inclusive", *ntpServerPort) + } + + level.Warn(logger).Log("msg", "This collector is deprecated and will be removed in the next major version release.") return &ntpCollector{ stratum: typedDesc{prometheus.NewDesc( prometheus.BuildFQName(namespace, ntpSubsystem, "stratum"), @@ -124,6 +131,7 @@ func (c *ntpCollector) Update(ch chan<- prometheus.Metric) error { Version: *ntpProtocolVersion, TTL: *ntpIPTTL, Timeout: time.Second, // default `ntpdate` timeout + Port: *ntpServerPort, }) if err != nil { return fmt.Errorf("couldn't get SNTP reply: %w", err) diff --git a/collector/nvme_linux.go b/collector/nvme_linux.go index 15af5d7563..81d4ab2985 100644 --- a/collector/nvme_linux.go +++ b/collector/nvme_linux.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build linux && !nonvme -// +build linux,!nonvme +//go:build !nonvme +// +build !nonvme package collector diff --git a/collector/os_release.go b/collector/os_release.go index cda1eb1f6a..14a025a454 100644 --- a/collector/os_release.go +++ b/collector/os_release.go @@ -14,6 +14,7 @@ package collector import ( + "encoding/xml" "errors" "io" "os" @@ -30,8 +31,9 @@ import ( ) const ( - etcOSRelease = "/etc/os-release" - usrLibOSRelease = "/usr/lib/os-release" + etcOSRelease = "/etc/os-release" + usrLibOSRelease = "/usr/lib/os-release" + systemVersionPlist = "/System/Library/CoreServices/SystemVersion.plist" ) var ( @@ -59,12 +61,21 @@ type osReleaseCollector struct { os *osRelease osFilename string // file name of cached release information osMtime time.Time // mtime of cached release file - osMutex sync.Mutex + osMutex sync.RWMutex osReleaseFilenames []string // all os-release file names to check version float64 versionDesc *prometheus.Desc } +type Plist struct { + Dict Dict `xml:"dict"` +} + +type Dict struct { + Key []string `xml:"key"` + String []string `xml:"string"` +} + func init() { registerCollector("os", defaultEnabled, NewOSCollector) } @@ -80,7 +91,7 @@ func NewOSCollector(logger log.Logger) (Collector, error) { []string{"build_id", "id", "id_like", "image_id", "image_version", "name", "pretty_name", "variant", "variant_id", "version", "version_codename", "version_id"}, nil, ), - osReleaseFilenames: []string{etcOSRelease, usrLibOSRelease}, + osReleaseFilenames: []string{etcOSRelease, usrLibOSRelease, systemVersionPlist}, versionDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, "os", "version"), "Metric containing the major.minor part of the OS version.", @@ -120,7 +131,10 @@ func (c *osReleaseCollector) UpdateStruct(path string) error { } t := stat.ModTime() - if path == c.osFilename && t == c.osMtime { + c.osMutex.RLock() + upToDate := path == c.osFilename && t == c.osMtime + c.osMutex.RUnlock() + if upToDate { // osReleaseCollector struct is already up-to-date. return nil } @@ -133,10 +147,17 @@ func (c *osReleaseCollector) UpdateStruct(path string) error { "file", path, "old_value", c.osMtime, "new_value", t) c.osFilename = path c.osMtime = t - - c.os, err = parseOSRelease(releaseFile) - if err != nil { - return err + // SystemVersion.plist is xml file with MacOs version info + if strings.Contains(releaseFile.Name(), "SystemVersion.plist") { + c.os, err = getMacosProductVersion(releaseFile.Name()) + if err != nil { + return err + } + } else { + c.os, err = parseOSRelease(releaseFile) + if err != nil { + return err + } } majorMinor := versionRegex.FindString(c.os.VersionID) @@ -176,3 +197,35 @@ func (c *osReleaseCollector) Update(ch chan<- prometheus.Metric) error { } return nil } + +func getMacosProductVersion(filename string) (*osRelease, error) { + f, _ := os.Open(filename) + bytePlist, _ := io.ReadAll(f) + f.Close() + + var plist Plist + err := xml.Unmarshal(bytePlist, &plist) + if err != nil { + return &osRelease{}, err + } + + var osVersionID, osVersionName, osBuildID string + if len(plist.Dict.Key) > 0 { + for index, value := range plist.Dict.Key { + switch value { + case "ProductVersion": + osVersionID = plist.Dict.String[index] + case "ProductName": + osVersionName = plist.Dict.String[index] + case "ProductBuildVersion": + osBuildID = plist.Dict.String[index] + } + } + } + return &osRelease{ + Name: osVersionName, + Version: osVersionID, + VersionID: osVersionID, + BuildID: osBuildID, + }, nil +} diff --git a/collector/os_release_test.go b/collector/os_release_test.go index e37cc34cbb..46838f15f1 100644 --- a/collector/os_release_test.go +++ b/collector/os_release_test.go @@ -48,6 +48,8 @@ func TestParseOSRelease(t *testing.T) { if err != nil { t.Fatal(err) } + defer osReleaseFile.Close() + got, err := parseOSRelease(osReleaseFile) if err != nil { t.Fatal(err) diff --git a/collector/paths.go b/collector/paths.go index 5f5a7b44b3..82c941876d 100644 --- a/collector/paths.go +++ b/collector/paths.go @@ -17,15 +17,16 @@ import ( "path/filepath" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/prometheus/procfs" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) var ( // The path of the proc filesystem. - procPath = kingpin.Flag("path.procfs", "procfs mountpoint.").Default(procfs.DefaultMountPoint).String() - sysPath = kingpin.Flag("path.sysfs", "sysfs mountpoint.").Default("/sys").String() - rootfsPath = kingpin.Flag("path.rootfs", "rootfs mountpoint.").Default("/").String() + procPath = kingpin.Flag("path.procfs", "procfs mountpoint.").Default(procfs.DefaultMountPoint).String() + sysPath = kingpin.Flag("path.sysfs", "sysfs mountpoint.").Default("/sys").String() + rootfsPath = kingpin.Flag("path.rootfs", "rootfs mountpoint.").Default("/").String() + udevDataPath = kingpin.Flag("path.udev.data", "udev data path.").Default("/run/udev/data").String() ) func procFilePath(name string) string { @@ -40,6 +41,10 @@ func rootfsFilePath(name string) string { return filepath.Join(*rootfsPath, name) } +func udevDataFilePath(name string) string { + return filepath.Join(*udevDataPath, name) +} + func rootfsStripPrefix(path string) string { if *rootfsPath == "/" { return path diff --git a/collector/paths_test.go b/collector/paths_test.go index eca7b3a48d..9426fa4b8a 100644 --- a/collector/paths_test.go +++ b/collector/paths_test.go @@ -16,8 +16,8 @@ package collector import ( "testing" + "github.com/alecthomas/kingpin/v2" "github.com/prometheus/procfs" - "gopkg.in/alecthomas/kingpin.v2" ) func TestDefaultProcPath(t *testing.T) { diff --git a/collector/perf_linux.go b/collector/perf_linux.go index 7688352303..8934371ad0 100644 --- a/collector/perf_linux.go +++ b/collector/perf_linux.go @@ -22,12 +22,12 @@ import ( "strconv" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/hodgesds/perf-utils" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sys/unix" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) const ( @@ -37,12 +37,67 @@ const ( var ( perfCPUsFlag = kingpin.Flag("collector.perf.cpus", "List of CPUs from which perf metrics should be collected").Default("").String() perfTracepointFlag = kingpin.Flag("collector.perf.tracepoint", "perf tracepoint that should be collected").Strings() + perfNoHwProfiler = kingpin.Flag("collector.perf.disable-hardware-profilers", "disable perf hardware profilers").Default("false").Bool() + perfHwProfilerFlag = kingpin.Flag("collector.perf.hardware-profilers", "perf hardware profilers that should be collected").Strings() + perfNoSwProfiler = kingpin.Flag("collector.perf.disable-software-profilers", "disable perf software profilers").Default("false").Bool() + perfSwProfilerFlag = kingpin.Flag("collector.perf.software-profilers", "perf software profilers that should be collected").Strings() + perfNoCaProfiler = kingpin.Flag("collector.perf.disable-cache-profilers", "disable perf cache profilers").Default("false").Bool() + perfCaProfilerFlag = kingpin.Flag("collector.perf.cache-profilers", "perf cache profilers that should be collected").Strings() ) func init() { registerCollector(perfSubsystem, defaultDisabled, NewPerfCollector) } +var ( + perfHardwareProfilerMap = map[string]perf.HardwareProfilerType{ + "CpuCycles": perf.CpuCyclesProfiler, + "CpuInstr": perf.CpuInstrProfiler, + "CacheRef": perf.CacheRefProfiler, + "CacheMisses": perf.CacheMissesProfiler, + "BranchInstr": perf.BranchInstrProfiler, + "BranchMisses": perf.BranchMissesProfiler, + "StalledCyclesBackend": perf.StalledCyclesBackendProfiler, + "StalledCyclesFrontend": perf.StalledCyclesFrontendProfiler, + "RefCpuCycles": perf.RefCpuCyclesProfiler, + // "BusCycles": perf.BusCyclesProfiler, + } + perfSoftwareProfilerMap = map[string]perf.SoftwareProfilerType{ + "PageFault": perf.PageFaultProfiler, + "ContextSwitch": perf.ContextSwitchProfiler, + "CpuMigration": perf.CpuMigrationProfiler, + "MinorFault": perf.MinorFaultProfiler, + "MajorFault": perf.MajorFaultProfiler, + // "CpuClock": perf.CpuClockProfiler, + // "TaskClock": perf.TaskClockProfiler, + // "AlignFault": perf.AlignFaultProfiler, + // "EmuFault": perf.EmuFaultProfiler, + } + perfCacheProfilerMap = map[string]perf.CacheProfilerType{ + "L1DataReadHit": perf.L1DataReadHitProfiler, + "L1DataReadMiss": perf.L1DataReadMissProfiler, + "L1DataWriteHit": perf.L1DataWriteHitProfiler, + "L1InstrReadMiss": perf.L1InstrReadMissProfiler, + "LLReadHit": perf.LLReadHitProfiler, + "LLReadMiss": perf.LLReadMissProfiler, + "LLWriteHit": perf.LLWriteHitProfiler, + "LLWriteMiss": perf.LLWriteMissProfiler, + "InstrTLBReadHit": perf.InstrTLBReadHitProfiler, + "InstrTLBReadMiss": perf.InstrTLBReadMissProfiler, + "BPUReadHit": perf.BPUReadHitProfiler, + "BPUReadMiss": perf.BPUReadMissProfiler, + // "L1InstrReadHit": perf.L1InstrReadHitProfiler, + // "DataTLBReadHit": perf.DataTLBReadHitProfiler, + // "DataTLBReadMiss": perf.DataTLBReadMissProfiler, + // "DataTLBWriteHit": perf.DataTLBWriteHitProfiler, + // "DataTLBWriteMiss": perf.DataTLBWriteMissProfiler, + // "NodeCacheReadHit": perf.NodeCacheReadHitProfiler, + // "NodeCacheReadMiss": perf.NodeCacheReadMissProfiler, + // "NodeCacheWriteHit": perf.NodeCacheWriteHitProfiler, + // "NodeCacheWriteMiss": perf.NodeCacheWriteMissProfiler, + } +) + // perfTracepointFlagToTracepoints returns the set of configured tracepoints. func perfTracepointFlagToTracepoints(tracepointsFlag []string) ([]*perfTracepoint, error) { tracepoints := make([]*perfTracepoint, len(tracepointsFlag)) @@ -50,7 +105,7 @@ func perfTracepointFlagToTracepoints(tracepointsFlag []string) ([]*perfTracepoin for i, tracepoint := range tracepointsFlag { split := strings.Split(tracepoint, ":") if len(split) != 2 { - return nil, fmt.Errorf("Invalid tracepoint config %v", tracepoint) + return nil, fmt.Errorf("invalid tracepoint config %v", tracepoint) } tracepoints[i] = &perfTracepoint{ subsystem: split[0], @@ -161,8 +216,8 @@ func (c *perfTracepointCollector) update(ch chan<- prometheus.Metric) error { // updateCPU is used to update metrics per CPU profiler. func (c *perfTracepointCollector) updateCPU(cpu int, ch chan<- prometheus.Metric) error { profiler := c.profilers[cpu] - p, err := profiler.Profile() - if err != nil { + p := &perf.GroupProfileValue{} + if err := profiler.Profile(p); err != nil { level.Error(c.logger).Log("msg", "Failed to collect tracepoint profile", "err", err) return err } @@ -282,39 +337,82 @@ func NewPerfCollector(logger log.Logger) (Collector, error) { collector.tracepointCollector = tracepointCollector } + // Configure perf profilers + hardwareProfilers := perf.AllHardwareProfilers + if *perfHwProfilerFlag != nil && len(*perfHwProfilerFlag) > 0 { + // hardwareProfilers = 0 + for _, hf := range *perfHwProfilerFlag { + if v, ok := perfHardwareProfilerMap[hf]; ok { + hardwareProfilers |= v + } + } + } + softwareProfilers := perf.AllSoftwareProfilers + if *perfSwProfilerFlag != nil && len(*perfSwProfilerFlag) > 0 { + // softwareProfilers = 0 + for _, sf := range *perfSwProfilerFlag { + if v, ok := perfSoftwareProfilerMap[sf]; ok { + softwareProfilers |= v + } + } + } + cacheProfilers := perf.L1DataReadHitProfiler | perf.L1DataReadMissProfiler | perf.L1DataWriteHitProfiler | perf.L1InstrReadMissProfiler | perf.InstrTLBReadHitProfiler | perf.InstrTLBReadMissProfiler | perf.LLReadHitProfiler | perf.LLReadMissProfiler | perf.LLWriteHitProfiler | perf.LLWriteMissProfiler | perf.BPUReadHitProfiler | perf.BPUReadMissProfiler + if *perfCaProfilerFlag != nil && len(*perfCaProfilerFlag) > 0 { + cacheProfilers = 0 + for _, cf := range *perfCaProfilerFlag { + if v, ok := perfCacheProfilerMap[cf]; ok { + cacheProfilers |= v + } + } + } + // Configure all profilers for the specified CPUs. for _, cpu := range cpus { // Use -1 to profile all processes on the CPU, see: // man perf_event_open - hwProf, err := perf.NewHardwareProfiler(-1, cpu) - if err != nil { - return nil, err - } - if err := hwProf.Start(); err != nil { - return nil, err + if !*perfNoHwProfiler { + hwProf, err := perf.NewHardwareProfiler( + -1, + cpu, + hardwareProfilers, + ) + if err != nil && !hwProf.HasProfilers() { + return nil, err + } + if err := hwProf.Start(); err != nil { + return nil, err + } + collector.perfHwProfilers[cpu] = &hwProf + collector.hwProfilerCPUMap[&hwProf] = cpu } - collector.perfHwProfilers[cpu] = &hwProf - collector.hwProfilerCPUMap[&hwProf] = cpu - swProf, err := perf.NewSoftwareProfiler(-1, cpu) - if err != nil { - return nil, err - } - if err := swProf.Start(); err != nil { - return nil, err + if !*perfNoSwProfiler { + swProf, err := perf.NewSoftwareProfiler(-1, cpu, softwareProfilers) + if err != nil && !swProf.HasProfilers() { + return nil, err + } + if err := swProf.Start(); err != nil { + return nil, err + } + collector.perfSwProfilers[cpu] = &swProf + collector.swProfilerCPUMap[&swProf] = cpu } - collector.perfSwProfilers[cpu] = &swProf - collector.swProfilerCPUMap[&swProf] = cpu - cacheProf, err := perf.NewCacheProfiler(-1, cpu) - if err != nil { - return nil, err - } - if err := cacheProf.Start(); err != nil { - return nil, err + if !*perfNoCaProfiler { + cacheProf, err := perf.NewCacheProfiler( + -1, + cpu, + cacheProfilers, + ) + if err != nil && !cacheProf.HasProfilers() { + return nil, err + } + if err := cacheProf.Start(); err != nil { + return nil, err + } + collector.perfCacheProfilers[cpu] = &cacheProf + collector.cacheProfilerCPUMap[&cacheProf] = cpu } - collector.perfCacheProfilers[cpu] = &cacheProf - collector.cacheProfilerCPUMap[&cacheProf] = cpu } collector.desc = map[string]*prometheus.Desc{ @@ -388,6 +486,26 @@ func NewPerfCollector(logger log.Logger) (Collector, error) { []string{"cpu"}, nil, ), + "stalled_cycles_backend_total": prometheus.NewDesc( + prometheus.BuildFQName( + namespace, + perfSubsystem, + "stalled_cycles_backend_total", + ), + "Number of stalled backend CPU cycles", + []string{"cpu"}, + nil, + ), + "stalled_cycles_frontend_total": prometheus.NewDesc( + prometheus.BuildFQName( + namespace, + perfSubsystem, + "stalled_cycles_frontend_total", + ), + "Number of stalled frontend CPU cycles", + []string{"cpu"}, + nil, + ), "page_faults_total": prometheus.NewDesc( prometheus.BuildFQName( namespace, @@ -585,13 +703,10 @@ func (c *perfCollector) Update(ch chan<- prometheus.Metric) error { func (c *perfCollector) updateHardwareStats(ch chan<- prometheus.Metric) error { for _, profiler := range c.perfHwProfilers { - hwProfile, err := (*profiler).Profile() - if err != nil { + hwProfile := &perf.HardwareProfile{} + if err := (*profiler).Profile(hwProfile); err != nil { return err } - if hwProfile == nil { - continue - } cpuid := strconv.Itoa(c.hwProfilerCPUMap[profiler]) @@ -650,6 +765,22 @@ func (c *perfCollector) updateHardwareStats(ch chan<- prometheus.Metric) error { cpuid, ) } + + if hwProfile.StalledCyclesBackend != nil { + ch <- prometheus.MustNewConstMetric( + c.desc["stalled_cycles_backend_total"], + prometheus.CounterValue, float64(*hwProfile.StalledCyclesBackend), + cpuid, + ) + } + + if hwProfile.StalledCyclesFrontend != nil { + ch <- prometheus.MustNewConstMetric( + c.desc["stalled_cycles_frontend_total"], + prometheus.CounterValue, float64(*hwProfile.StalledCyclesFrontend), + cpuid, + ) + } } return nil @@ -657,13 +788,10 @@ func (c *perfCollector) updateHardwareStats(ch chan<- prometheus.Metric) error { func (c *perfCollector) updateSoftwareStats(ch chan<- prometheus.Metric) error { for _, profiler := range c.perfSwProfilers { - swProfile, err := (*profiler).Profile() - if err != nil { + swProfile := &perf.SoftwareProfile{} + if err := (*profiler).Profile(swProfile); err != nil { return err } - if swProfile == nil { - continue - } cpuid := strconv.Itoa(c.swProfilerCPUMap[profiler]) @@ -713,13 +841,10 @@ func (c *perfCollector) updateSoftwareStats(ch chan<- prometheus.Metric) error { func (c *perfCollector) updateCacheStats(ch chan<- prometheus.Metric) error { for _, profiler := range c.perfCacheProfilers { - cacheProfile, err := (*profiler).Profile() - if err != nil { + cacheProfile := &perf.CacheProfile{} + if err := (*profiler).Profile(cacheProfile); err != nil { return err } - if cacheProfile == nil { - continue - } cpuid := strconv.Itoa(c.cacheProfilerCPUMap[profiler]) diff --git a/collector/perf_linux_test.go b/collector/perf_linux_test.go index 54ef199acf..fc557ffd32 100644 --- a/collector/perf_linux_test.go +++ b/collector/perf_linux_test.go @@ -11,25 +11,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !noprocesses -// +build !noprocesses +//go:build !noperf +// +build !noperf package collector import ( - "io/ioutil" + "os" "runtime" "strconv" "strings" "testing" "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" ) func canTestPerf(t *testing.T) { - paranoidBytes, err := ioutil.ReadFile("/proc/sys/kernel/perf_event_paranoid") + paranoidBytes, err := os.ReadFile("/proc/sys/kernel/perf_event_paranoid") if err != nil { t.Skip("Procfs not mounted, skipping perf tests") } @@ -54,7 +53,9 @@ func TestPerfCollector(t *testing.T) { metrics := make(chan prometheus.Metric) defer close(metrics) go func() { + i := 0 for range metrics { + i++ } }() if err := collector.Update(metrics); err != nil { diff --git a/collector/powersupplyclass.go b/collector/powersupplyclass.go index ffa4d4e61d..7f231dac47 100644 --- a/collector/powersupplyclass.go +++ b/collector/powersupplyclass.go @@ -20,9 +20,9 @@ package collector import ( "regexp" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) var ( diff --git a/collector/powersupplyclass_darwin.go b/collector/powersupplyclass_darwin.go index a070f64d19..01d7f184f7 100644 --- a/collector/powersupplyclass_darwin.go +++ b/collector/powersupplyclass_darwin.go @@ -18,9 +18,11 @@ package collector /* #cgo LDFLAGS: -framework IOKit -framework CoreFoundation +#include +#include +#include #include #include -#include // values collected from IOKit Power Source APIs // Functions documentation available at diff --git a/collector/processes_linux_test.go b/collector/processes_linux_test.go index 9a5c86f5be..e2814a0104 100644 --- a/collector/processes_linux_test.go +++ b/collector/processes_linux_test.go @@ -19,9 +19,9 @@ package collector import ( "testing" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/procfs" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) func TestReadProcessStatus(t *testing.T) { diff --git a/collector/qdisc_linux.go b/collector/qdisc_linux.go index 3050318ab4..06ab6a88d6 100644 --- a/collector/qdisc_linux.go +++ b/collector/qdisc_linux.go @@ -18,28 +18,35 @@ package collector import ( "encoding/json" - "io/ioutil" + "fmt" + "os" "path/filepath" + "github.com/alecthomas/kingpin/v2" "github.com/ema/qdisc" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) type qdiscStatCollector struct { - bytes typedDesc - packets typedDesc - drops typedDesc - requeues typedDesc - overlimits typedDesc - qlength typedDesc - backlog typedDesc - logger log.Logger + logger log.Logger + deviceFilter deviceFilter + bytes typedDesc + packets typedDesc + drops typedDesc + requeues typedDesc + overlimits typedDesc + qlength typedDesc + backlog typedDesc } var ( - collectorQdisc = kingpin.Flag("collector.qdisc.fixtures", "test fixtures to use for qdisc collector end-to-end testing").Default("").String() + collectorQdisc = kingpin.Flag("collector.qdisc.fixtures", "test fixtures to use for qdisc collector end-to-end testing").Default("").String() + collectorQdiscDeviceInclude = kingpin.Flag("collector.qdisc.device-include", "Regexp of qdisc devices to include (mutually exclusive to device-exclude).").String() + oldCollectorQdiskDeviceInclude = kingpin.Flag("collector.qdisk.device-include", "DEPRECATED: Use collector.qdisc.device-include").Hidden().String() + collectorQdiscDeviceExclude = kingpin.Flag("collector.qdisc.device-exclude", "Regexp of qdisc devices to exclude (mutually exclusive to device-include).").String() + oldCollectorQdiskDeviceExclude = kingpin.Flag("collector.qdisk.device-exclude", "DEPRECATED: Use collector.qdisc.device-exclude").Hidden().String() ) func init() { @@ -48,6 +55,28 @@ func init() { // NewQdiscStatCollector returns a new Collector exposing queuing discipline statistics. func NewQdiscStatCollector(logger log.Logger) (Collector, error) { + if *oldCollectorQdiskDeviceInclude != "" { + if *collectorQdiscDeviceInclude == "" { + level.Warn(logger).Log("msg", "--collector.qdisk.device-include is DEPRECATED and will be removed in 2.0.0, use --collector.qdisc.device-include") + *collectorQdiscDeviceInclude = *oldCollectorQdiskDeviceInclude + } else { + return nil, fmt.Errorf("--collector.qdisk.device-include and --collector.qdisc.device-include are mutually exclusive") + } + } + + if *oldCollectorQdiskDeviceExclude != "" { + if *collectorQdiscDeviceExclude == "" { + level.Warn(logger).Log("msg", "--collector.qdisk.device-exclude is DEPRECATED and will be removed in 2.0.0, use --collector.qdisc.device-exclude") + *collectorQdiscDeviceExclude = *oldCollectorQdiskDeviceExclude + } else { + return nil, fmt.Errorf("--collector.qdisk.device-exclude and --collector.qdisc.device-exclude are mutually exclusive") + } + } + + if *collectorQdiscDeviceExclude != "" && *collectorQdiscDeviceInclude != "" { + return nil, fmt.Errorf("collector.qdisc.device-include and collector.qdisc.device-exclude are mutaly exclusive") + } + return &qdiscStatCollector{ bytes: typedDesc{prometheus.NewDesc( prometheus.BuildFQName(namespace, "qdisc", "bytes_total"), @@ -84,14 +113,15 @@ func NewQdiscStatCollector(logger log.Logger) (Collector, error) { "Number of bytes currently in queue to be sent.", []string{"device", "kind"}, nil, ), prometheus.GaugeValue}, - logger: logger, + logger: logger, + deviceFilter: newDeviceFilter(*collectorQdiscDeviceExclude, *collectorQdiscDeviceInclude), }, nil } func testQdiscGet(fixtures string) ([]qdisc.QdiscInfo, error) { var res []qdisc.QdiscInfo - b, err := ioutil.ReadFile(filepath.Join(fixtures, "results.json")) + b, err := os.ReadFile(filepath.Join(fixtures, "results.json")) if err != nil { return res, err } @@ -122,6 +152,10 @@ func (c *qdiscStatCollector) Update(ch chan<- prometheus.Metric) error { continue } + if c.deviceFilter.ignored(msg.IfaceName) { + continue + } + ch <- c.bytes.mustNewConstMetric(float64(msg.Bytes), msg.IfaceName, msg.Kind) ch <- c.packets.mustNewConstMetric(float64(msg.Packets), msg.IfaceName, msg.Kind) ch <- c.drops.mustNewConstMetric(float64(msg.Drops), msg.IfaceName, msg.Kind) diff --git a/collector/rapl_linux.go b/collector/rapl_linux.go index 5ed343bbe8..642de6c146 100644 --- a/collector/rapl_linux.go +++ b/collector/rapl_linux.go @@ -22,21 +22,30 @@ import ( "os" "strconv" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/sysfs" ) +const raplCollectorSubsystem = "rapl" + type raplCollector struct { fs sysfs.FS logger log.Logger + + joulesMetricDesc *prometheus.Desc } func init() { - registerCollector("rapl", defaultEnabled, NewRaplCollector) + registerCollector(raplCollectorSubsystem, defaultEnabled, NewRaplCollector) } +var ( + raplZoneLabel = kingpin.Flag("collector.rapl.enable-zone-label", "Enables service unit metric unit_start_time_seconds").Bool() +) + // NewRaplCollector returns a new Collector exposing RAPL metrics. func NewRaplCollector(logger log.Logger) (Collector, error) { fs, err := sysfs.NewFS(*sysPath) @@ -45,9 +54,16 @@ func NewRaplCollector(logger log.Logger) (Collector, error) { return nil, err } + joulesMetricDesc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, raplCollectorSubsystem, "joules_total"), + "Current RAPL value in joules", + []string{"index", "path", "rapl_zone"}, nil, + ) + collector := raplCollector{ - fs: fs, - logger: logger, + fs: fs, + logger: logger, + joulesMetricDesc: joulesMetricDesc, } return &collector, nil } @@ -69,7 +85,7 @@ func (c *raplCollector) Update(ch chan<- prometheus.Metric) error { } for _, rz := range zones { - newMicrojoules, err := rz.GetEnergyMicrojoules() + microJoules, err := rz.GetEnergyMicrojoules() if err != nil { if errors.Is(err, os.ErrPermission) { level.Debug(c.logger).Log("msg", "Can't access energy_uj file", "zone", rz, "err", err) @@ -77,21 +93,48 @@ func (c *raplCollector) Update(ch chan<- prometheus.Metric) error { } return err } - index := strconv.Itoa(rz.Index) - - descriptor := prometheus.NewDesc( - prometheus.BuildFQName(namespace, "rapl", rz.Name+"_joules_total"), - "Current RAPL "+rz.Name+" value in joules", - []string{"index", "path"}, nil, - ) - - ch <- prometheus.MustNewConstMetric( - descriptor, - prometheus.CounterValue, - float64(newMicrojoules)/1000000.0, - index, - rz.Path, - ) + + joules := float64(microJoules) / 1000000.0 + + if *raplZoneLabel { + ch <- c.joulesMetricWithZoneLabel(rz, joules) + } else { + ch <- c.joulesMetric(rz, joules) + } } return nil } + +func (c *raplCollector) joulesMetric(z sysfs.RaplZone, v float64) prometheus.Metric { + index := strconv.Itoa(z.Index) + descriptor := prometheus.NewDesc( + prometheus.BuildFQName( + namespace, + raplCollectorSubsystem, + fmt.Sprintf("%s_joules_total", SanitizeMetricName(z.Name)), + ), + fmt.Sprintf("Current RAPL %s value in joules", z.Name), + []string{"index", "path"}, nil, + ) + + return prometheus.MustNewConstMetric( + descriptor, + prometheus.CounterValue, + v, + index, + z.Path, + ) +} + +func (c *raplCollector) joulesMetricWithZoneLabel(z sysfs.RaplZone, v float64) prometheus.Metric { + index := strconv.Itoa(z.Index) + + return prometheus.MustNewConstMetric( + c.joulesMetricDesc, + prometheus.CounterValue, + v, + index, + z.Path, + z.Name, + ) +} diff --git a/collector/runit.go b/collector/runit.go index 2449691dbb..3cae657c33 100644 --- a/collector/runit.go +++ b/collector/runit.go @@ -17,11 +17,11 @@ package collector import ( + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/go-runit/runit" "github.com/prometheus/client_golang/prometheus" - "github.com/soundcloud/go-runit/runit" - "gopkg.in/alecthomas/kingpin.v2" ) var runitServiceDir = kingpin.Flag("collector.runit.servicedir", "Path to runit service directory.").Default("/etc/service").String() @@ -46,6 +46,8 @@ func NewRunitCollector(logger log.Logger) (Collector, error) { labelNames = []string{"service"} ) + level.Warn(logger).Log("msg", "This collector is deprecated and will be removed in the next major version release.") + return &runitCollector{ state: typedDesc{prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "state"), diff --git a/collector/selinux_linux.go b/collector/selinux_linux.go new file mode 100644 index 0000000000..79316362fe --- /dev/null +++ b/collector/selinux_linux.go @@ -0,0 +1,78 @@ +// Copyright 2022 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 !noselinux +// +build !noselinux + +package collector + +import ( + "github.com/go-kit/log" + "github.com/opencontainers/selinux/go-selinux" + "github.com/prometheus/client_golang/prometheus" +) + +type selinuxCollector struct { + configMode *prometheus.Desc + currentMode *prometheus.Desc + enabled *prometheus.Desc + logger log.Logger +} + +func init() { + registerCollector("selinux", defaultEnabled, NewSelinuxCollector) +} + +// NewSelinuxCollector returns a new Collector exposing SELinux statistics. +func NewSelinuxCollector(logger log.Logger) (Collector, error) { + const subsystem = "selinux" + + return &selinuxCollector{ + configMode: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "config_mode"), + "Configured SELinux enforcement mode", + nil, nil, + ), + currentMode: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "current_mode"), + "Current SELinux enforcement mode", + nil, nil, + ), + enabled: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "enabled"), + "SELinux is enabled, 1 is true, 0 is false", + nil, nil, + ), + logger: logger, + }, nil +} + +func (c *selinuxCollector) Update(ch chan<- prometheus.Metric) error { + if !selinux.GetEnabled() { + ch <- prometheus.MustNewConstMetric( + c.enabled, prometheus.GaugeValue, 0) + + return nil + } + + ch <- prometheus.MustNewConstMetric( + c.enabled, prometheus.GaugeValue, 1) + + ch <- prometheus.MustNewConstMetric( + c.configMode, prometheus.GaugeValue, float64(selinux.DefaultEnforceMode())) + + ch <- prometheus.MustNewConstMetric( + c.currentMode, prometheus.GaugeValue, float64(selinux.EnforceMode())) + + return nil +} diff --git a/collector/slabinfo_linux.go b/collector/slabinfo_linux.go new file mode 100644 index 0000000000..a3c3ebced7 --- /dev/null +++ b/collector/slabinfo_linux.go @@ -0,0 +1,121 @@ +// Copyright 2022 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 !noslabinfo +// +build !noslabinfo + +package collector + +import ( + "fmt" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs" +) + +type slabinfoCollector struct { + fs procfs.FS + logger log.Logger + subsystem string + labels []string +} + +func init() { + registerCollector("slabinfo", defaultDisabled, NewSlabinfoCollector) +} + +func NewSlabinfoCollector(logger log.Logger) (Collector, error) { + fs, err := procfs.NewFS(*procPath) + if err != nil { + return nil, fmt.Errorf("failed to open procfs: %w", err) + } + + return &slabinfoCollector{logger: logger, + fs: fs, + subsystem: "slabinfo", + labels: []string{"slab"}, + }, nil +} + +func (c *slabinfoCollector) Update(ch chan<- prometheus.Metric) error { + slabinfo, err := c.fs.SlabInfo() + if err != nil { + return fmt.Errorf("couldn't get %s: %w", c.subsystem, err) + } + + for _, slab := range slabinfo.Slabs { + ch <- c.activeObjects(slab.Name, slab.ObjActive) + ch <- c.objects(slab.Name, slab.ObjNum) + ch <- c.objectSizeBytes(slab.Name, slab.ObjSize) + ch <- c.objectsPerSlab(slab.Name, slab.ObjPerSlab) + ch <- c.pagesPerSlab(slab.Name, slab.PagesPerSlab) + } + + return nil +} + +func (c *slabinfoCollector) activeObjects(label string, val int64) prometheus.Metric { + desc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "active_objects"), + "The number of objects that are currently active (i.e., in use).", + c.labels, nil) + + return prometheus.MustNewConstMetric( + desc, prometheus.GaugeValue, float64(val), label, + ) +} + +func (c *slabinfoCollector) objects(label string, val int64) prometheus.Metric { + desc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "objects"), + "The total number of allocated objects (i.e., objects that are both in use and not in use).", + c.labels, nil) + + return prometheus.MustNewConstMetric( + desc, prometheus.GaugeValue, float64(val), label, + ) +} + +func (c *slabinfoCollector) objectSizeBytes(label string, val int64) prometheus.Metric { + desc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "object_size_bytes"), + "The size of objects in this slab, in bytes.", + c.labels, nil) + + return prometheus.MustNewConstMetric( + desc, prometheus.GaugeValue, float64(val), label, + ) +} + +func (c *slabinfoCollector) objectsPerSlab(label string, val int64) prometheus.Metric { + desc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "objects_per_slab"), + "The number of objects stored in each slab.", + c.labels, nil) + + return prometheus.MustNewConstMetric( + desc, prometheus.GaugeValue, float64(val), label, + ) +} + +func (c *slabinfoCollector) pagesPerSlab(label string, val int64) prometheus.Metric { + desc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "pages_per_slab"), + "The number of pages allocated for each slab.", + c.labels, nil) + + return prometheus.MustNewConstMetric( + desc, prometheus.GaugeValue, float64(val), label, + ) +} diff --git a/collector/softirq_linux.go b/collector/softirq_linux.go new file mode 100644 index 0000000000..702f34bb0c --- /dev/null +++ b/collector/softirq_linux.go @@ -0,0 +1,68 @@ +// Copyright 2023 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 !nosoftirqs +// +build !nosoftirqs + +package collector + +import ( + "fmt" + "strconv" + + "github.com/prometheus/client_golang/prometheus" +) + +var ( + softirqLabelNames = []string{"cpu", "type"} +) + +func (c *softirqsCollector) Update(ch chan<- prometheus.Metric) (err error) { + softirqs, err := c.fs.Softirqs() + if err != nil { + return fmt.Errorf("couldn't get softirqs: %w", err) + } + + for cpuNo, value := range softirqs.Hi { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "HI") + } + for cpuNo, value := range softirqs.Timer { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "TIMER") + } + for cpuNo, value := range softirqs.NetTx { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "NET_TX") + } + for cpuNo, value := range softirqs.NetRx { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "NET_RX") + } + for cpuNo, value := range softirqs.Block { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "BLOCK") + } + for cpuNo, value := range softirqs.IRQPoll { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "IRQ_POLL") + } + for cpuNo, value := range softirqs.Tasklet { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "TASKLET") + } + for cpuNo, value := range softirqs.Sched { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "SCHED") + } + for cpuNo, value := range softirqs.HRTimer { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "HRTIMER") + } + for cpuNo, value := range softirqs.RCU { + ch <- c.desc.mustNewConstMetric(float64(value), strconv.Itoa(cpuNo), "RCU") + } + + return err +} diff --git a/collector/softirqs_common.go b/collector/softirqs_common.go new file mode 100644 index 0000000000..08ef780f26 --- /dev/null +++ b/collector/softirqs_common.go @@ -0,0 +1,50 @@ +// Copyright 2023 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 linux && !nosoftirqs +// +build linux,!nosoftirqs + +package collector + +import ( + "fmt" + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs" +) + +type softirqsCollector struct { + fs procfs.FS + desc typedDesc + logger log.Logger +} + +func init() { + registerCollector("softirqs", defaultDisabled, NewSoftirqsCollector) +} + +// NewSoftirqsCollector returns a new Collector exposing softirq stats. +func NewSoftirqsCollector(logger log.Logger) (Collector, error) { + desc := typedDesc{prometheus.NewDesc( + namespace+"_softirqs_functions_total", + "Softirq counts per CPU.", + softirqLabelNames, nil, + ), prometheus.CounterValue} + + fs, err := procfs.NewFS(*procPath) + if err != nil { + return nil, fmt.Errorf("failed to open procfs: %w", err) + } + + return &softirqsCollector{fs, desc, logger}, nil +} diff --git a/collector/softnet_linux.go b/collector/softnet_linux.go index a46b6808be..42d47780e3 100644 --- a/collector/softnet_linux.go +++ b/collector/softnet_linux.go @@ -26,11 +26,15 @@ import ( ) type softnetCollector struct { - fs procfs.FS - processed *prometheus.Desc - dropped *prometheus.Desc - timeSqueezed *prometheus.Desc - logger log.Logger + fs procfs.FS + processed *prometheus.Desc + dropped *prometheus.Desc + timeSqueezed *prometheus.Desc + cpuCollision *prometheus.Desc + receivedRps *prometheus.Desc + flowLimitCount *prometheus.Desc + softnetBacklogLen *prometheus.Desc + logger log.Logger } const ( @@ -65,19 +69,41 @@ func NewSoftnetCollector(logger log.Logger) (Collector, error) { "Number of times processing packets ran out of quota", []string{"cpu"}, nil, ), + cpuCollision: prometheus.NewDesc( + prometheus.BuildFQName(namespace, softnetSubsystem, "cpu_collision_total"), + "Number of collision occur while obtaining device lock while transmitting", + []string{"cpu"}, nil, + ), + receivedRps: prometheus.NewDesc( + prometheus.BuildFQName(namespace, softnetSubsystem, "received_rps_total"), + "Number of times cpu woken up received_rps", + []string{"cpu"}, nil, + ), + flowLimitCount: prometheus.NewDesc( + prometheus.BuildFQName(namespace, softnetSubsystem, "flow_limit_count_total"), + "Number of times flow limit has been reached", + []string{"cpu"}, nil, + ), + softnetBacklogLen: prometheus.NewDesc( + prometheus.BuildFQName(namespace, softnetSubsystem, "backlog_len"), + "Softnet backlog status", + []string{"cpu"}, nil, + ), logger: logger, }, nil } // Update gets parsed softnet statistics using procfs. func (c *softnetCollector) Update(ch chan<- prometheus.Metric) error { + var cpu string + stats, err := c.fs.NetSoftnetStat() if err != nil { return fmt.Errorf("could not get softnet statistics: %w", err) } - for cpuNumber, cpuStats := range stats { - cpu := strconv.Itoa(cpuNumber) + for _, cpuStats := range stats { + cpu = strconv.FormatUint(uint64(cpuStats.Index), 10) ch <- prometheus.MustNewConstMetric( c.processed, @@ -97,6 +123,30 @@ func (c *softnetCollector) Update(ch chan<- prometheus.Metric) error { float64(cpuStats.TimeSqueezed), cpu, ) + ch <- prometheus.MustNewConstMetric( + c.cpuCollision, + prometheus.CounterValue, + float64(cpuStats.CPUCollision), + cpu, + ) + ch <- prometheus.MustNewConstMetric( + c.receivedRps, + prometheus.CounterValue, + float64(cpuStats.ReceivedRps), + cpu, + ) + ch <- prometheus.MustNewConstMetric( + c.flowLimitCount, + prometheus.CounterValue, + float64(cpuStats.FlowLimitCount), + cpu, + ) + ch <- prometheus.MustNewConstMetric( + c.softnetBacklogLen, + prometheus.GaugeValue, + float64(cpuStats.SoftnetBacklogLen), + cpu, + ) } return nil diff --git a/collector/stat_linux.go b/collector/stat_linux.go index 941c5f233b..9974ae7aa7 100644 --- a/collector/stat_linux.go +++ b/collector/stat_linux.go @@ -19,6 +19,7 @@ package collector import ( "fmt" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs" @@ -32,9 +33,12 @@ type statCollector struct { btime *prometheus.Desc procsRunning *prometheus.Desc procsBlocked *prometheus.Desc + softIRQ *prometheus.Desc logger log.Logger } +var statSoftirqFlag = kingpin.Flag("collector.stat.softirq", "Export softirq calls per vector").Default("false").Bool() + func init() { registerCollector("stat", defaultEnabled, NewStatCollector) } @@ -77,6 +81,11 @@ func NewStatCollector(logger log.Logger) (Collector, error) { "Number of processes blocked waiting for I/O to complete.", nil, nil, ), + softIRQ: prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "softirqs_total"), + "Number of softirq calls.", + []string{"vector"}, nil, + ), logger: logger, }, nil } @@ -97,5 +106,27 @@ func (c *statCollector) Update(ch chan<- prometheus.Metric) error { ch <- prometheus.MustNewConstMetric(c.procsRunning, prometheus.GaugeValue, float64(stats.ProcessesRunning)) ch <- prometheus.MustNewConstMetric(c.procsBlocked, prometheus.GaugeValue, float64(stats.ProcessesBlocked)) + if *statSoftirqFlag { + si := stats.SoftIRQ + + for _, vec := range []struct { + name string + value uint64 + }{ + {name: "hi", value: si.Hi}, + {name: "timer", value: si.Timer}, + {name: "net_tx", value: si.NetTx}, + {name: "net_rx", value: si.NetRx}, + {name: "block", value: si.Block}, + {name: "block_iopoll", value: si.BlockIoPoll}, + {name: "tasklet", value: si.Tasklet}, + {name: "sched", value: si.Sched}, + {name: "hrtimer", value: si.Hrtimer}, + {name: "rcu", value: si.Rcu}, + } { + ch <- prometheus.MustNewConstMetric(c.softIRQ, prometheus.CounterValue, float64(vec.value), vec.name) + } + } + return nil } diff --git a/collector/supervisord.go b/collector/supervisord.go index b3b0f1372c..9b517f0a42 100644 --- a/collector/supervisord.go +++ b/collector/supervisord.go @@ -24,11 +24,11 @@ import ( "net/url" "time" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/mattn/go-xmlrpc" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) var ( @@ -69,6 +69,8 @@ func NewSupervisordCollector(logger log.Logger) (Collector, error) { xrpc = xmlrpc.NewClient(*supervisordURL) } + level.Warn(logger).Log("msg", "This collector is deprecated and will be removed in the next major version release.") + return &supervisordCollector{ upDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "up"), diff --git a/collector/sysctl_bsd.go b/collector/sysctl_bsd.go index 03a878f790..2ab248ed2e 100644 --- a/collector/sysctl_bsd.go +++ b/collector/sysctl_bsd.go @@ -36,7 +36,6 @@ const ( // Default to uint32. bsdSysctlTypeUint32 bsdSysctlType = iota bsdSysctlTypeUint64 - bsdSysctlTypeStructTimeval bsdSysctlTypeCLong ) @@ -75,8 +74,6 @@ func (b bsdSysctl) Value() (float64, error) { case bsdSysctlTypeUint64: tmp64, err = unix.SysctlUint64(b.mib) tmpf64 = float64(tmp64) - case bsdSysctlTypeStructTimeval: - tmpf64, err = b.getStructTimeval() case bsdSysctlTypeCLong: tmpf64, err = b.getCLong() } @@ -92,28 +89,6 @@ func (b bsdSysctl) Value() (float64, error) { return tmpf64, nil } -func (b bsdSysctl) getStructTimeval() (float64, error) { - raw, err := unix.SysctlRaw(b.mib) - if err != nil { - return 0, err - } - - if len(raw) != int(unsafe.Sizeof(unix.Timeval{})) { - // Shouldn't get here. - return 0, fmt.Errorf( - "length of bytes received from sysctl (%d) does not match expected bytes (%d)", - len(raw), - unsafe.Sizeof(unix.Timeval{}), - ) - } - - tv := *(*unix.Timeval)(unsafe.Pointer(&raw[0])) - - // This conversion maintains the usec precision. Using the time - // package did not. - return (float64(tv.Sec) + (float64(tv.Usec) / float64(1000*1000))), nil -} - func (b bsdSysctl) getCLong() (float64, error) { raw, err := unix.SysctlRaw(b.mib) if err != nil { diff --git a/collector/sysctl_linux.go b/collector/sysctl_linux.go new file mode 100644 index 0000000000..c14341db85 --- /dev/null +++ b/collector/sysctl_linux.go @@ -0,0 +1,218 @@ +// Copyright 2022 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. + +package collector + +import ( + "fmt" + "strconv" + "strings" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs" +) + +var ( + sysctlInclude = kingpin.Flag("collector.sysctl.include", "Select sysctl metrics to include").Strings() + sysctlIncludeInfo = kingpin.Flag("collector.sysctl.include-info", "Select sysctl metrics to include as info metrics").Strings() + + sysctlInfoDesc = prometheus.NewDesc(prometheus.BuildFQName(namespace, "sysctl", "info"), "sysctl info", []string{"name", "value", "index"}, nil) +) + +type sysctlCollector struct { + fs procfs.FS + logger log.Logger + sysctls []*sysctl +} + +func init() { + registerCollector("sysctl", defaultDisabled, NewSysctlCollector) +} + +func NewSysctlCollector(logger log.Logger) (Collector, error) { + fs, err := procfs.NewFS(*procPath) + if err != nil { + return nil, fmt.Errorf("failed to open sysfs: %w", err) + } + c := &sysctlCollector{ + logger: logger, + fs: fs, + sysctls: []*sysctl{}, + } + + for _, include := range *sysctlInclude { + sysctl, err := newSysctl(include, true) + if err != nil { + return nil, err + } + c.sysctls = append(c.sysctls, sysctl) + } + + for _, include := range *sysctlIncludeInfo { + sysctl, err := newSysctl(include, false) + if err != nil { + return nil, err + } + c.sysctls = append(c.sysctls, sysctl) + } + return c, nil +} + +func (c *sysctlCollector) Update(ch chan<- prometheus.Metric) error { + for _, sysctl := range c.sysctls { + metrics, err := c.newMetrics(sysctl) + if err != nil { + return err + } + + for _, metric := range metrics { + ch <- metric + } + } + return nil +} + +func (c *sysctlCollector) newMetrics(s *sysctl) ([]prometheus.Metric, error) { + var ( + values interface{} + length int + err error + ) + + if s.numeric { + values, err = c.fs.SysctlInts(s.name) + if err != nil { + return nil, fmt.Errorf("error obtaining sysctl info: %w", err) + } + length = len(values.([]int)) + } else { + values, err = c.fs.SysctlStrings(s.name) + if err != nil { + return nil, fmt.Errorf("error obtaining sysctl info: %w", err) + } + length = len(values.([]string)) + } + + switch length { + case 0: + return nil, fmt.Errorf("sysctl %s has no values", s.name) + case 1: + if len(s.keys) > 0 { + return nil, fmt.Errorf("sysctl %s has only one value, but expected %v", s.name, s.keys) + } + return []prometheus.Metric{s.newConstMetric(values)}, nil + + default: + + if len(s.keys) == 0 { + return s.newIndexedMetrics(values), nil + } + + if length != len(s.keys) { + return nil, fmt.Errorf("sysctl %s has %d keys but only %d defined in f lag", s.name, length, len(s.keys)) + } + + return s.newMappedMetrics(values) + } +} + +type sysctl struct { + numeric bool + name string + keys []string +} + +func newSysctl(include string, numeric bool) (*sysctl, error) { + parts := strings.SplitN(include, ":", 2) + s := &sysctl{ + numeric: numeric, + name: parts[0], + } + if len(parts) == 2 { + s.keys = strings.Split(parts[1], ",") + s.name = parts[0] + } + return s, nil +} + +func (s *sysctl) metricName() string { + return SanitizeMetricName(s.name) +} + +func (s *sysctl) newConstMetric(v interface{}) prometheus.Metric { + if s.numeric { + return prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(namespace, "sysctl", s.metricName()), + fmt.Sprintf("sysctl %s", s.name), + nil, nil), + prometheus.UntypedValue, + float64(v.([]int)[0])) + } + return prometheus.MustNewConstMetric( + sysctlInfoDesc, + prometheus.GaugeValue, + 1.0, + s.name, + v.([]string)[0], + "0", + ) +} + +func (s *sysctl) newIndexedMetrics(v interface{}) []prometheus.Metric { + desc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, "sysctl", s.metricName()), + fmt.Sprintf("sysctl %s", s.name), + []string{"index"}, nil, + ) + switch values := v.(type) { + case []int: + metrics := make([]prometheus.Metric, len(values)) + for i, n := range values { + metrics[i] = prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, float64(n), strconv.Itoa(i)) + } + return metrics + case []string: + metrics := make([]prometheus.Metric, len(values)) + for i, str := range values { + metrics[i] = prometheus.MustNewConstMetric(sysctlInfoDesc, prometheus.GaugeValue, 1.0, s.name, str, strconv.Itoa(i)) + } + return metrics + default: + panic(fmt.Sprintf("unexpected type %T", values)) + } +} + +func (s *sysctl) newMappedMetrics(v interface{}) ([]prometheus.Metric, error) { + switch values := v.(type) { + case []int: + metrics := make([]prometheus.Metric, len(values)) + for i, n := range values { + key := s.keys[i] + desc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, "sysctl", s.metricName()+"_"+key), + fmt.Sprintf("sysctl %s, field %d", s.name, i), + nil, + nil, + ) + metrics[i] = prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, float64(n)) + } + return metrics, nil + case []string: + return nil, fmt.Errorf("mapped sysctl string values not supported") + default: + return nil, fmt.Errorf("unexpected type %T", values) + } +} diff --git a/collector/systemd_linux.go b/collector/systemd_linux.go index 495aa560d8..3323251114 100644 --- a/collector/systemd_linux.go +++ b/collector/systemd_linux.go @@ -17,6 +17,7 @@ package collector import ( + "context" "errors" "fmt" "math" @@ -26,11 +27,11 @@ import ( "sync" "time" - "github.com/coreos/go-systemd/dbus" + "github.com/alecthomas/kingpin/v2" + "github.com/coreos/go-systemd/v22/dbus" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) const ( @@ -41,22 +42,24 @@ const ( ) var ( - unitIncludeSet bool - unitInclude = kingpin.Flag("collector.systemd.unit-include", "Regexp of systemd units to include. Units must both match include and not match exclude to be included.").Default(".+").PreAction(func(c *kingpin.ParseContext) error { - unitIncludeSet = true + systemdUnitIncludeSet bool + systemdUnitInclude = kingpin.Flag("collector.systemd.unit-include", "Regexp of systemd units to include. Units must both match include and not match exclude to be included.").Default(".+").PreAction(func(c *kingpin.ParseContext) error { + systemdUnitIncludeSet = true return nil }).String() - oldUnitInclude = kingpin.Flag("collector.systemd.unit-whitelist", "DEPRECATED: Use --collector.systemd.unit-include").Hidden().String() - unitExcludeSet bool - unitExclude = kingpin.Flag("collector.systemd.unit-exclude", "Regexp of systemd units to exclude. Units must both match include and not match exclude to be included.").Default(".+\\.(automount|device|mount|scope|slice)").PreAction(func(c *kingpin.ParseContext) error { - unitExcludeSet = true + oldSystemdUnitInclude = kingpin.Flag("collector.systemd.unit-whitelist", "DEPRECATED: Use --collector.systemd.unit-include").Hidden().String() + systemdUnitExcludeSet bool + systemdUnitExclude = kingpin.Flag("collector.systemd.unit-exclude", "Regexp of systemd units to exclude. Units must both match include and not match exclude to be included.").Default(".+\\.(automount|device|mount|scope|slice)").PreAction(func(c *kingpin.ParseContext) error { + systemdUnitExcludeSet = true return nil }).String() - oldUnitExclude = kingpin.Flag("collector.systemd.unit-blacklist", "DEPRECATED: Use collector.systemd.unit-exclude").Hidden().String() + oldSystemdUnitExclude = kingpin.Flag("collector.systemd.unit-blacklist", "DEPRECATED: Use collector.systemd.unit-exclude").Hidden().String() systemdPrivate = kingpin.Flag("collector.systemd.private", "Establish a private, direct connection to systemd without dbus (Strongly discouraged since it requires root. For testing purposes only).").Hidden().Bool() enableTaskMetrics = kingpin.Flag("collector.systemd.enable-task-metrics", "Enables service unit tasks metrics unit_tasks_current and unit_tasks_max").Bool() enableRestartsMetrics = kingpin.Flag("collector.systemd.enable-restarts-metrics", "Enables service unit metric service_restart_total").Bool() enableStartTimeMetrics = kingpin.Flag("collector.systemd.enable-start-time-metrics", "Enables service unit metric unit_start_time_seconds").Bool() + + systemdVersionRE = regexp.MustCompile(`[0-9]{3,}(\.[0-9]+)?`) ) type systemdCollector struct { @@ -72,10 +75,10 @@ type systemdCollector struct { socketCurrentConnectionsDesc *prometheus.Desc socketRefusedConnectionsDesc *prometheus.Desc systemdVersionDesc *prometheus.Desc - systemdVersion int - unitIncludePattern *regexp.Regexp - unitExcludePattern *regexp.Regexp - logger log.Logger + // Use regexps for more flexability than device_filter.go allows + systemdUnitIncludePattern *regexp.Regexp + systemdUnitExcludePattern *regexp.Regexp + logger log.Logger } var unitStatesName = []string{"active", "activating", "deactivating", "inactive", "failed"} @@ -129,34 +132,28 @@ func NewSystemdCollector(logger log.Logger) (Collector, error) { "Total number of refused socket connections", []string{"name"}, nil) systemdVersionDesc := prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "version"), - "Detected systemd version", []string{}, nil) + "Detected systemd version", []string{"version"}, nil) - if *oldUnitExclude != "" { - if !unitExcludeSet { + if *oldSystemdUnitExclude != "" { + if !systemdUnitExcludeSet { level.Warn(logger).Log("msg", "--collector.systemd.unit-blacklist is DEPRECATED and will be removed in 2.0.0, use --collector.systemd.unit-exclude") - *unitExclude = *oldUnitExclude + *systemdUnitExclude = *oldSystemdUnitExclude } else { return nil, errors.New("--collector.systemd.unit-blacklist and --collector.systemd.unit-exclude are mutually exclusive") } } - if *oldUnitInclude != "" { - if !unitIncludeSet { + if *oldSystemdUnitInclude != "" { + if !systemdUnitIncludeSet { level.Warn(logger).Log("msg", "--collector.systemd.unit-whitelist is DEPRECATED and will be removed in 2.0.0, use --collector.systemd.unit-include") - *unitInclude = *oldUnitInclude + *systemdUnitInclude = *oldSystemdUnitInclude } else { return nil, errors.New("--collector.systemd.unit-whitelist and --collector.systemd.unit-include are mutually exclusive") } } - level.Info(logger).Log("msg", "Parsed flag --collector.systemd.unit-include", "flag", *unitInclude) - unitIncludePattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitInclude)) - level.Info(logger).Log("msg", "Parsed flag --collector.systemd.unit-exclude", "flag", *unitExclude) - unitExcludePattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitExclude)) - - systemdVersion := getSystemdVersion(logger) - if systemdVersion < minSystemdVersionSystemState { - level.Warn(logger).Log("msg", "Detected systemd version is lower than minimum", "current", systemdVersion, "minimum", minSystemdVersionSystemState) - level.Warn(logger).Log("msg", "Some systemd state and timer metrics will not be available") - } + level.Info(logger).Log("msg", "Parsed flag --collector.systemd.unit-include", "flag", *systemdUnitInclude) + systemdUnitIncludePattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *systemdUnitInclude)) + level.Info(logger).Log("msg", "Parsed flag --collector.systemd.unit-exclude", "flag", *systemdUnitExclude) + systemdUnitExcludePattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *systemdUnitExclude)) return &systemdCollector{ unitDesc: unitDesc, @@ -171,9 +168,8 @@ func NewSystemdCollector(logger log.Logger) (Collector, error) { socketCurrentConnectionsDesc: socketCurrentConnectionsDesc, socketRefusedConnectionsDesc: socketRefusedConnectionsDesc, systemdVersionDesc: systemdVersionDesc, - systemdVersion: systemdVersion, - unitIncludePattern: unitIncludePattern, - unitExcludePattern: unitExcludePattern, + systemdUnitIncludePattern: systemdUnitIncludePattern, + systemdUnitExcludePattern: systemdUnitExcludePattern, logger: logger, }, nil } @@ -188,6 +184,17 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { } defer conn.Close() + systemdVersion, systemdVersionFull := c.getSystemdVersion(conn) + if systemdVersion < minSystemdVersionSystemState { + level.Debug(c.logger).Log("msg", "Detected systemd version is lower than minimum, some systemd state and timer metrics will not be available", "current", systemdVersion, "minimum", minSystemdVersionSystemState) + } + ch <- prometheus.MustNewConstMetric( + c.systemdVersionDesc, + prometheus.GaugeValue, + systemdVersion, + systemdVersionFull, + ) + allUnits, err := c.getAllUnits(conn) if err != nil { return fmt.Errorf("couldn't get units: %w", err) @@ -200,7 +207,7 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { level.Debug(c.logger).Log("msg", "collectSummaryMetrics took", "duration_seconds", time.Since(begin).Seconds()) begin = time.Now() - units := filterUnits(allUnits, c.unitIncludePattern, c.unitExcludePattern, c.logger) + units := filterUnits(allUnits, c.systemdUnitIncludePattern, c.systemdUnitExcludePattern, c.logger) level.Debug(c.logger).Log("msg", "filterUnits took", "duration_seconds", time.Since(begin).Seconds()) var wg sync.WaitGroup @@ -234,7 +241,7 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { }() } - if c.systemdVersion >= minSystemdVersionSystemState { + if systemdVersion >= minSystemdVersionSystemState { wg.Add(1) go func() { defer wg.Done() @@ -252,15 +259,12 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { level.Debug(c.logger).Log("msg", "collectSockets took", "duration_seconds", time.Since(begin).Seconds()) }() - if c.systemdVersion >= minSystemdVersionSystemState { + if systemdVersion >= minSystemdVersionSystemState { begin = time.Now() err = c.collectSystemState(conn, ch) level.Debug(c.logger).Log("msg", "collectSystemState took", "duration_seconds", time.Since(begin).Seconds()) } - ch <- prometheus.MustNewConstMetric( - c.systemdVersionDesc, prometheus.GaugeValue, float64(c.systemdVersion)) - return err } @@ -268,14 +272,14 @@ func (c *systemdCollector) collectUnitStatusMetrics(conn *dbus.Conn, ch chan<- p for _, unit := range units { serviceType := "" if strings.HasSuffix(unit.Name, ".service") { - serviceTypeProperty, err := conn.GetUnitTypeProperty(unit.Name, "Service", "Type") + serviceTypeProperty, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Service", "Type") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit type", "unit", unit.Name, "err", err) } else { serviceType = serviceTypeProperty.Value.Value().(string) } } else if strings.HasSuffix(unit.Name, ".mount") { - serviceTypeProperty, err := conn.GetUnitTypeProperty(unit.Name, "Mount", "Type") + serviceTypeProperty, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Mount", "Type") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit type", "unit", unit.Name, "err", err) } else { @@ -293,7 +297,7 @@ func (c *systemdCollector) collectUnitStatusMetrics(conn *dbus.Conn, ch chan<- p } if *enableRestartsMetrics && strings.HasSuffix(unit.Name, ".service") { // NRestarts wasn't added until systemd 235. - restartsCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "NRestarts") + restartsCount, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Service", "NRestarts") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit NRestarts", "unit", unit.Name, "err", err) } else { @@ -311,7 +315,7 @@ func (c *systemdCollector) collectSockets(conn *dbus.Conn, ch chan<- prometheus. continue } - acceptedConnectionCount, err := conn.GetUnitTypeProperty(unit.Name, "Socket", "NAccepted") + acceptedConnectionCount, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Socket", "NAccepted") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit NAccepted", "unit", unit.Name, "err", err) continue @@ -320,7 +324,7 @@ func (c *systemdCollector) collectSockets(conn *dbus.Conn, ch chan<- prometheus. c.socketAcceptedConnectionsDesc, prometheus.CounterValue, float64(acceptedConnectionCount.Value.Value().(uint32)), unit.Name) - currentConnectionCount, err := conn.GetUnitTypeProperty(unit.Name, "Socket", "NConnections") + currentConnectionCount, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Socket", "NConnections") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit NConnections", "unit", unit.Name, "err", err) continue @@ -330,10 +334,8 @@ func (c *systemdCollector) collectSockets(conn *dbus.Conn, ch chan<- prometheus. float64(currentConnectionCount.Value.Value().(uint32)), unit.Name) // NRefused wasn't added until systemd 239. - refusedConnectionCount, err := conn.GetUnitTypeProperty(unit.Name, "Socket", "NRefused") - if err != nil { - //log.Debugf("couldn't get unit '%s' NRefused: %s", unit.Name, err) - } else { + refusedConnectionCount, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Socket", "NRefused") + if err == nil { ch <- prometheus.MustNewConstMetric( c.socketRefusedConnectionsDesc, prometheus.GaugeValue, float64(refusedConnectionCount.Value.Value().(uint32)), unit.Name) @@ -348,7 +350,7 @@ func (c *systemdCollector) collectUnitStartTimeMetrics(conn *dbus.Conn, ch chan< if unit.ActiveState != "active" { startTimeUsec = 0 } else { - timestampValue, err := conn.GetUnitProperty(unit.Name, "ActiveEnterTimestamp") + timestampValue, err := conn.GetUnitPropertyContext(context.TODO(), unit.Name, "ActiveEnterTimestamp") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit StartTimeUsec", "unit", unit.Name, "err", err) continue @@ -366,7 +368,7 @@ func (c *systemdCollector) collectUnitTasksMetrics(conn *dbus.Conn, ch chan<- pr var val uint64 for _, unit := range units { if strings.HasSuffix(unit.Name, ".service") { - tasksCurrentCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "TasksCurrent") + tasksCurrentCount, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Service", "TasksCurrent") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit TasksCurrent", "unit", unit.Name, "err", err) } else { @@ -378,7 +380,7 @@ func (c *systemdCollector) collectUnitTasksMetrics(conn *dbus.Conn, ch chan<- pr float64(val), unit.Name) } } - tasksMaxCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "TasksMax") + tasksMaxCount, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Service", "TasksMax") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit TasksMax", "unit", unit.Name, "err", err) } else { @@ -400,7 +402,7 @@ func (c *systemdCollector) collectTimers(conn *dbus.Conn, ch chan<- prometheus.M continue } - lastTriggerValue, err := conn.GetUnitTypeProperty(unit.Name, "Timer", "LastTriggerUSec") + lastTriggerValue, err := conn.GetUnitTypePropertyContext(context.TODO(), unit.Name, "Timer", "LastTriggerUSec") if err != nil { level.Debug(c.logger).Log("msg", "couldn't get unit LastTriggerUSec", "unit", unit.Name, "err", err) continue @@ -434,9 +436,9 @@ func (c *systemdCollector) collectSystemState(conn *dbus.Conn, ch chan<- prometh func newSystemdDbusConn() (*dbus.Conn, error) { if *systemdPrivate { - return dbus.NewSystemdConnection() + return dbus.NewSystemdConnectionContext(context.TODO()) } - return dbus.New() + return dbus.NewWithContext(context.TODO()) } type unit struct { @@ -444,7 +446,7 @@ type unit struct { } func (c *systemdCollector) getAllUnits(conn *dbus.Conn) ([]unit, error) { - allUnits, err := conn.ListUnits() + allUnits, err := conn.ListUnitsContext(context.TODO()) if err != nil { return nil, err } @@ -488,24 +490,19 @@ func filterUnits(units []unit, includePattern, excludePattern *regexp.Regexp, lo return filtered } -func getSystemdVersion(logger log.Logger) int { - conn, err := newSystemdDbusConn() - if err != nil { - level.Warn(logger).Log("msg", "Unable to get systemd dbus connection, defaulting systemd version to 0", "err", err) - return 0 - } - defer conn.Close() +func (c *systemdCollector) getSystemdVersion(conn *dbus.Conn) (float64, string) { version, err := conn.GetManagerProperty("Version") if err != nil { - level.Warn(logger).Log("msg", "Unable to get systemd version property, defaulting to 0") - return 0 + level.Debug(c.logger).Log("msg", "Unable to get systemd version property, defaulting to 0") + return 0, "" } - re := regexp.MustCompile(`[0-9][0-9][0-9]`) - version = re.FindString(version) - v, err := strconv.Atoi(version) + version = strings.TrimPrefix(strings.TrimSuffix(version, `"`), `"`) + level.Debug(c.logger).Log("msg", "Got systemd version", "version", version) + parsedVersion := systemdVersionRE.FindString(version) + v, err := strconv.ParseFloat(parsedVersion, 64) if err != nil { - level.Warn(logger).Log("msg", "Got invalid systemd version", "version", version) - return 0 + level.Debug(c.logger).Log("msg", "Got invalid systemd version", "version", version) + return 0, "" } - return v + return v, version } diff --git a/collector/systemd_linux_test.go b/collector/systemd_linux_test.go index 1b55af7c3a..d4e300d1d2 100644 --- a/collector/systemd_linux_test.go +++ b/collector/systemd_linux_test.go @@ -11,14 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nosystemd +// +build !nosystemd + package collector import ( - "github.com/go-kit/log" "regexp" "testing" - "github.com/coreos/go-systemd/dbus" + "github.com/coreos/go-systemd/v22/dbus" + "github.com/go-kit/log" ) // Creates mock UnitLists @@ -106,7 +109,7 @@ func TestSystemdIgnoreFilterDefaultKeepsAll(t *testing.T) { } fixtures := getUnitListFixtures() collector := c.(*systemdCollector) - filtered := filterUnits(fixtures[0], collector.unitIncludePattern, collector.unitExcludePattern, logger) + filtered := filterUnits(fixtures[0], collector.systemdUnitIncludePattern, collector.systemdUnitExcludePattern, logger) // Adjust fixtures by 3 "not-found" units. if len(filtered) != len(fixtures[0])-3 { t.Error("Default filters removed units") diff --git a/collector/tapestats_linux.go b/collector/tapestats_linux.go index 441ac61073..264c2210f1 100644 --- a/collector/tapestats_linux.go +++ b/collector/tapestats_linux.go @@ -21,11 +21,11 @@ import ( "os" "regexp" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/sysfs" - "gopkg.in/alecthomas/kingpin.v2" ) var ( diff --git a/collector/tcpstat_linux.go b/collector/tcpstat_linux.go index 47c3f3e076..99e33bc6a3 100644 --- a/collector/tcpstat_linux.go +++ b/collector/tcpstat_linux.go @@ -18,13 +18,12 @@ package collector import ( "fmt" - "io" - "io/ioutil" "os" - "strconv" - "strings" + "syscall" + "unsafe" "github.com/go-kit/log" + "github.com/mdlayher/netlink" "github.com/prometheus/client_golang/prometheus" ) @@ -80,16 +79,64 @@ func NewTCPStatCollector(logger log.Logger) (Collector, error) { }, nil } +// InetDiagSockID (inet_diag_sockid) contains the socket identity. +// https://github.com/torvalds/linux/blob/v4.0/include/uapi/linux/inet_diag.h#L13 +type InetDiagSockID struct { + SourcePort [2]byte + DestPort [2]byte + SourceIP [4][4]byte + DestIP [4][4]byte + Interface uint32 + Cookie [2]uint32 +} + +// InetDiagReqV2 (inet_diag_req_v2) is used to request diagnostic data. +// https://github.com/torvalds/linux/blob/v4.0/include/uapi/linux/inet_diag.h#L37 +type InetDiagReqV2 struct { + Family uint8 + Protocol uint8 + Ext uint8 + Pad uint8 + States uint32 + ID InetDiagSockID +} + +const sizeOfDiagRequest = 0x38 + +func (req *InetDiagReqV2) Serialize() []byte { + return (*(*[sizeOfDiagRequest]byte)(unsafe.Pointer(req)))[:] +} + +func (req *InetDiagReqV2) Len() int { + return sizeOfDiagRequest +} + +type InetDiagMsg struct { + Family uint8 + State uint8 + Timer uint8 + Retrans uint8 + ID InetDiagSockID + Expires uint32 + RQueue uint32 + WQueue uint32 + UID uint32 + Inode uint32 +} + +func parseInetDiagMsg(b []byte) *InetDiagMsg { + return (*InetDiagMsg)(unsafe.Pointer(&b[0])) +} + func (c *tcpStatCollector) Update(ch chan<- prometheus.Metric) error { - tcpStats, err := getTCPStats(procFilePath("net/tcp")) + tcpStats, err := getTCPStats(syscall.AF_INET) if err != nil { return fmt.Errorf("couldn't get tcpstats: %w", err) } // if enabled ipv6 system - tcp6File := procFilePath("net/tcp6") - if _, hasIPv6 := os.Stat(tcp6File); hasIPv6 == nil { - tcp6Stats, err := getTCPStats(tcp6File) + if _, hasIPv6 := os.Stat(procFilePath("net/tcp6")); hasIPv6 == nil { + tcp6Stats, err := getTCPStats(syscall.AF_INET6) if err != nil { return fmt.Errorf("couldn't get tcp6stats: %w", err) } @@ -102,59 +149,51 @@ func (c *tcpStatCollector) Update(ch chan<- prometheus.Metric) error { for st, value := range tcpStats { ch <- c.desc.mustNewConstMetric(value, st.String()) } + return nil } -func getTCPStats(statsFile string) (map[tcpConnectionState]float64, error) { - file, err := os.Open(statsFile) +func getTCPStats(family uint8) (map[tcpConnectionState]float64, error) { + const TCPFAll = 0xFFF + const InetDiagInfo = 2 + const SockDiagByFamily = 20 + + conn, err := netlink.Dial(syscall.NETLINK_INET_DIAG, nil) if err != nil { - return nil, err + return nil, fmt.Errorf("couldn't connect netlink: %w", err) + } + defer conn.Close() + + msg := netlink.Message{ + Header: netlink.Header{ + Type: SockDiagByFamily, + Flags: syscall.NLM_F_REQUEST | syscall.NLM_F_DUMP, + }, + Data: (&InetDiagReqV2{ + Family: family, + Protocol: syscall.IPPROTO_TCP, + States: TCPFAll, + Ext: 0 | 1<<(InetDiagInfo-1), + }).Serialize(), } - defer file.Close() - - return parseTCPStats(file) -} -func parseTCPStats(r io.Reader) (map[tcpConnectionState]float64, error) { - tcpStats := map[tcpConnectionState]float64{} - contents, err := ioutil.ReadAll(r) + messages, err := conn.Execute(msg) if err != nil { return nil, err } - for _, line := range strings.Split(string(contents), "\n")[1:] { - parts := strings.Fields(line) - if len(parts) == 0 { - continue - } - if len(parts) < 5 { - return nil, fmt.Errorf("invalid TCP stats line: %q", line) - } - - qu := strings.Split(parts[4], ":") - if len(qu) < 2 { - return nil, fmt.Errorf("cannot parse tx_queues and rx_queues: %q", line) - } - - tx, err := strconv.ParseUint(qu[0], 16, 64) - if err != nil { - return nil, err - } - tcpStats[tcpConnectionState(tcpTxQueuedBytes)] += float64(tx) - - rx, err := strconv.ParseUint(qu[1], 16, 64) - if err != nil { - return nil, err - } - tcpStats[tcpConnectionState(tcpRxQueuedBytes)] += float64(rx) + return parseTCPStats(messages) +} - st, err := strconv.ParseInt(parts[3], 16, 8) - if err != nil { - return nil, err - } +func parseTCPStats(msgs []netlink.Message) (map[tcpConnectionState]float64, error) { + tcpStats := map[tcpConnectionState]float64{} - tcpStats[tcpConnectionState(st)]++ + for _, m := range msgs { + msg := parseInetDiagMsg(m.Data) + tcpStats[tcpTxQueuedBytes] += float64(msg.WQueue) + tcpStats[tcpRxQueuedBytes] += float64(msg.RQueue) + tcpStats[tcpConnectionState(msg.State)]++ } return tcpStats, nil diff --git a/collector/tcpstat_linux_test.go b/collector/tcpstat_linux_test.go index b609b84679..e1bd090a79 100644 --- a/collector/tcpstat_linux_test.go +++ b/collector/tcpstat_linux_test.go @@ -11,69 +11,63 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !notcpstat +// +build !notcpstat + package collector import ( - "os" - "strings" + "bytes" + "encoding/binary" + "syscall" "testing" + + "github.com/josharian/native" + "github.com/mdlayher/netlink" ) -func Test_parseTCPStatsError(t *testing.T) { - tests := []struct { - name string - in string - }{ - { - name: "too few fields", - in: "sl local_address\n 0: 00000000:0016", - }, - { - name: "missing colon in tx-rx field", - in: "sl local_address rem_address st tx_queue rx_queue\n" + - " 1: 0F02000A:0016 0202000A:8B6B 01 0000000000000001", - }, - { - name: "tx parsing issue", - in: "sl local_address rem_address st tx_queue rx_queue\n" + - " 1: 0F02000A:0016 0202000A:8B6B 01 0000000x:00000001", - }, +func Test_parseTCPStats(t *testing.T) { + encode := func(m InetDiagMsg) []byte { + var buf bytes.Buffer + err := binary.Write(&buf, native.Endian, m) + if err != nil { + panic(err) + } + return buf.Bytes() + } + + msg := []netlink.Message{ { - name: "rx parsing issue", - in: "sl local_address rem_address st tx_queue rx_queue\n" + - " 1: 0F02000A:0016 0202000A:8B6B 01 00000000:0000000x", + Data: encode(InetDiagMsg{ + Family: syscall.AF_INET, + State: uint8(tcpEstablished), + Timer: 0, + Retrans: 0, + ID: InetDiagSockID{}, + Expires: 0, + RQueue: 11, + WQueue: 21, + UID: 0, + Inode: 0, + }), }, { - name: "state parsing issue", - in: "sl local_address rem_address st tx_queue rx_queue\n" + - " 1: 0F02000A:0016 0202000A:8B6B 0H 00000000:00000001", + Data: encode(InetDiagMsg{ + Family: syscall.AF_INET, + State: uint8(tcpListen), + Timer: 0, + Retrans: 0, + ID: InetDiagSockID{}, + Expires: 0, + RQueue: 11, + WQueue: 21, + UID: 0, + Inode: 0, + }), }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if _, err := parseTCPStats(strings.NewReader(tt.in)); err == nil { - t.Fatal("expected an error, but none occurred") - } - }) - } -} - -func TestTCPStat(t *testing.T) { - - noFile, _ := os.Open("follow the white rabbit") - defer noFile.Close() - if _, err := parseTCPStats(noFile); err == nil { - t.Fatal("expected an error, but none occurred") - } - - file, err := os.Open("fixtures/proc/net/tcpstat") - if err != nil { - t.Fatal(err) - } - defer file.Close() - - tcpStats, err := parseTCPStats(file) + tcpStats, err := parseTCPStats(msg) if err != nil { t.Fatal(err) } @@ -89,35 +83,8 @@ func TestTCPStat(t *testing.T) { if want, got := 42, int(tcpStats[tcpTxQueuedBytes]); want != got { t.Errorf("want tcpstat number of bytes in tx queue %d, got %d", want, got) } - if want, got := 1, int(tcpStats[tcpRxQueuedBytes]); want != got { + if want, got := 22, int(tcpStats[tcpRxQueuedBytes]); want != got { t.Errorf("want tcpstat number of bytes in rx queue %d, got %d", want, got) } } - -func Test_getTCPStats(t *testing.T) { - type args struct { - statsFile string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "file not found", - args: args{statsFile: "somewhere over the rainbow"}, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - _, err := getTCPStats(tt.args.statsFile) - if (err != nil) != tt.wantErr { - t.Errorf("getTCPStats() error = %v, wantErr %v", err, tt.wantErr) - return - } - // other cases are covered by TestTCPStat() - }) - } -} diff --git a/collector/textfile.go b/collector/textfile.go index 469235dc6e..48133f7c98 100644 --- a/collector/textfile.go +++ b/collector/textfile.go @@ -18,19 +18,18 @@ package collector import ( "fmt" - "io/ioutil" "os" "path/filepath" "sort" "strings" "time" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) var ( @@ -192,37 +191,58 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error { // Iterate over files and accumulate their metrics, but also track any // parsing errors so an error metric can be reported. var errored bool + var parsedFamilies []*dto.MetricFamily + metricsNamesToFiles := map[string][]string{} paths, err := filepath.Glob(c.path) if err != nil || len(paths) == 0 { // not glob or not accessible path either way assume single - // directory and let ioutil.ReadDir handle it + // directory and let os.ReadDir handle it paths = []string{c.path} } mtimes := make(map[string]time.Time) for _, path := range paths { - files, err := ioutil.ReadDir(path) + files, err := os.ReadDir(path) if err != nil && path != "" { errored = true level.Error(c.logger).Log("msg", "failed to read textfile collector directory", "path", path, "err", err) } for _, f := range files { + metricsFilePath := filepath.Join(path, f.Name()) if !strings.HasSuffix(f.Name(), ".prom") { continue } - mtime, err := c.processFile(path, f.Name(), ch) + mtime, families, err := c.processFile(path, f.Name(), ch) + + for _, mf := range families { + metricsNamesToFiles[*mf.Name] = append(metricsNamesToFiles[*mf.Name], metricsFilePath) + parsedFamilies = append(parsedFamilies, mf) + } + if err != nil { errored = true level.Error(c.logger).Log("msg", "failed to collect textfile data", "file", f.Name(), "err", err) continue } - mtimes[filepath.Join(path, f.Name())] = *mtime + mtimes[metricsFilePath] = *mtime } } + + for _, mf := range parsedFamilies { + if mf.Help == nil { + help := fmt.Sprintf("Metric read from %s", strings.Join(metricsNamesToFiles[*mf.Name], ", ")) + mf.Help = &help + } + } + + for _, mf := range parsedFamilies { + convertMetricFamily(mf, ch, c.logger) + } + c.exportMTimes(mtimes, ch) // Export if there were errors. @@ -244,44 +264,33 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error { } // processFile processes a single file, returning its modification time on success. -func (c *textFileCollector) processFile(dir, name string, ch chan<- prometheus.Metric) (*time.Time, error) { +func (c *textFileCollector) processFile(dir, name string, ch chan<- prometheus.Metric) (*time.Time, map[string]*dto.MetricFamily, error) { path := filepath.Join(dir, name) f, err := os.Open(path) if err != nil { - return nil, fmt.Errorf("failed to open textfile data file %q: %w", path, err) + return nil, nil, fmt.Errorf("failed to open textfile data file %q: %w", path, err) } defer f.Close() var parser expfmt.TextParser families, err := parser.TextToMetricFamilies(f) if err != nil { - return nil, fmt.Errorf("failed to parse textfile data from %q: %w", path, err) + return nil, nil, fmt.Errorf("failed to parse textfile data from %q: %w", path, err) } if hasTimestamps(families) { - return nil, fmt.Errorf("textfile %q contains unsupported client-side timestamps, skipping entire file", path) - } - - for _, mf := range families { - if mf.Help == nil { - help := fmt.Sprintf("Metric read from %s", path) - mf.Help = &help - } - } - - for _, mf := range families { - convertMetricFamily(mf, ch, c.logger) + return nil, nil, fmt.Errorf("textfile %q contains unsupported client-side timestamps, skipping entire file", path) } // Only stat the file once it has been parsed and validated, so that // a failure does not appear fresh. stat, err := f.Stat() if err != nil { - return nil, fmt.Errorf("failed to stat %q: %w", path, err) + return nil, families, fmt.Errorf("failed to stat %q: %w", path, err) } t := stat.ModTime() - return &t, nil + return &t, families, nil } // hasTimestamps returns true when metrics contain unsupported timestamps. diff --git a/collector/textfile_test.go b/collector/textfile_test.go index b0f8c537ac..95e5966f3e 100644 --- a/collector/textfile_test.go +++ b/collector/textfile_test.go @@ -11,21 +11,24 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !notextfile +// +build !notextfile + package collector import ( "fmt" - "io/ioutil" "net/http" "net/http/httptest" + "os" "testing" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/promlog" "github.com/prometheus/common/promlog/flag" - "gopkg.in/alecthomas/kingpin.v2" ) type collectorAdapter struct { @@ -95,6 +98,22 @@ func TestTextfileCollector(t *testing.T) { path: "fixtures/textfile/*_extra_dimension", out: "fixtures/textfile/glob_extra_dimension.out", }, + { + path: "fixtures/textfile/metrics_merge_empty_help", + out: "fixtures/textfile/metrics_merge_empty_help.out", + }, + { + path: "fixtures/textfile/metrics_merge_no_help", + out: "fixtures/textfile/metrics_merge_no_help.out", + }, + { + path: "fixtures/textfile/metrics_merge_same_help", + out: "fixtures/textfile/metrics_merge_same_help.out", + }, + { + path: "fixtures/textfile/metrics_merge_different_help", + out: "fixtures/textfile/metrics_merge_different_help.out", + }, } for i, test := range tests { @@ -117,10 +136,10 @@ func TestTextfileCollector(t *testing.T) { registry.MustRegister(collectorAdapter{c}) rw := httptest.NewRecorder() - promhttp.HandlerFor(registry, promhttp.HandlerOpts{}).ServeHTTP(rw, &http.Request{}) + promhttp.HandlerFor(registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}).ServeHTTP(rw, &http.Request{}) got := string(rw.Body.String()) - want, err := ioutil.ReadFile(test.out) + want, err := os.ReadFile(test.out) if err != nil { t.Fatalf("%d. error reading fixture file %s: %s", i, test.out, err) } diff --git a/collector/thermal_darwin.go b/collector/thermal_darwin.go index 282ca3f383..25673dcc4d 100644 --- a/collector/thermal_darwin.go +++ b/collector/thermal_darwin.go @@ -47,9 +47,10 @@ import "C" import ( "errors" "fmt" + "unsafe" + "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" - "unsafe" ) type thermCollector struct { @@ -118,7 +119,9 @@ func (c *thermCollector) Update(ch chan<- prometheus.Metric) error { func fetchCPUPowerStatus() (map[string]int, error) { cfDictRef, _ := C.FetchThermal() defer func() { - C.CFRelease(C.CFTypeRef(cfDictRef.ref)) + if cfDictRef.ref != 0x0 { + C.CFRelease(C.CFTypeRef(cfDictRef.ref)) + } }() if C.kIOReturnNotFound == cfDictRef.ret { diff --git a/collector/thermal_zone_linux.go b/collector/thermal_zone_linux.go index 6aedf34796..6eff27321a 100644 --- a/collector/thermal_zone_linux.go +++ b/collector/thermal_zone_linux.go @@ -17,9 +17,12 @@ package collector import ( + "errors" "fmt" + "os" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs/sysfs" ) @@ -70,6 +73,10 @@ func NewThermalZoneCollector(logger log.Logger) (Collector, error) { func (c *thermalZoneCollector) Update(ch chan<- prometheus.Metric) error { thermalZones, err := c.fs.ClassThermalZoneStats() if err != nil { + if errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission) || errors.Is(err, os.ErrInvalid) { + level.Debug(c.logger).Log("msg", "Could not read thermal zone stats", "err", err) + return ErrNoData + } return err } diff --git a/collector/time.go b/collector/time.go index 34c5aad25b..31a6e74e24 100644 --- a/collector/time.go +++ b/collector/time.go @@ -25,9 +25,11 @@ import ( ) type timeCollector struct { - nowDesc *prometheus.Desc - zoneDesc *prometheus.Desc - logger log.Logger + now typedDesc + zone typedDesc + clocksourcesAvailable typedDesc + clocksourceCurrent typedDesc + logger log.Logger } func init() { @@ -39,16 +41,26 @@ func init() { func NewTimeCollector(logger log.Logger) (Collector, error) { const subsystem = "time" return &timeCollector{ - nowDesc: prometheus.NewDesc( + now: typedDesc{prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "seconds"), "System time in seconds since epoch (1970).", nil, nil, - ), - zoneDesc: prometheus.NewDesc( + ), prometheus.GaugeValue}, + zone: typedDesc{prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "zone_offset_seconds"), "System time zone offset in seconds.", []string{"time_zone"}, nil, - ), + ), prometheus.GaugeValue}, + clocksourcesAvailable: typedDesc{prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "clocksource_available_info"), + "Available clocksources read from '/sys/devices/system/clocksource'.", + []string{"device", "clocksource"}, nil, + ), prometheus.GaugeValue}, + clocksourceCurrent: typedDesc{prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "clocksource_current_info"), + "Current clocksource read from '/sys/devices/system/clocksource'.", + []string{"device", "clocksource"}, nil, + ), prometheus.GaugeValue}, logger: logger, }, nil } @@ -59,8 +71,8 @@ func (c *timeCollector) Update(ch chan<- prometheus.Metric) error { zone, zoneOffset := now.Zone() level.Debug(c.logger).Log("msg", "Return time", "now", nowSec) - ch <- prometheus.MustNewConstMetric(c.nowDesc, prometheus.GaugeValue, nowSec) + ch <- c.now.mustNewConstMetric(nowSec) level.Debug(c.logger).Log("msg", "Zone offset", "offset", zoneOffset, "time_zone", zone) - ch <- prometheus.MustNewConstMetric(c.zoneDesc, prometheus.GaugeValue, float64(zoneOffset), zone) - return nil + ch <- c.zone.mustNewConstMetric(float64(zoneOffset), zone) + return c.update(ch) } diff --git a/collector/time_linux.go b/collector/time_linux.go new file mode 100644 index 0000000000..dd4afe7592 --- /dev/null +++ b/collector/time_linux.go @@ -0,0 +1,48 @@ +// Copyright 2021 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 !notime +// +build !notime + +package collector + +import ( + "fmt" + "strconv" + + "github.com/go-kit/log/level" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs/sysfs" +) + +func (c *timeCollector) update(ch chan<- prometheus.Metric) error { + fs, err := sysfs.NewFS(*sysPath) + if err != nil { + return fmt.Errorf("failed to open procfs: %w", err) + } + + clocksources, err := fs.ClockSources() + if err != nil { + return fmt.Errorf("couldn't get clocksources: %w", err) + } + level.Debug(c.logger).Log("msg", "in Update", "clocksources", fmt.Sprintf("%v", clocksources)) + + for i, clocksource := range clocksources { + is := strconv.Itoa(i) + for _, cs := range clocksource.Available { + ch <- c.clocksourcesAvailable.mustNewConstMetric(1.0, is, cs) + } + ch <- c.clocksourceCurrent.mustNewConstMetric(1.0, is, clocksource.Current) + } + return nil +} diff --git a/collector/time_other.go b/collector/time_other.go new file mode 100644 index 0000000000..8227435bd9 --- /dev/null +++ b/collector/time_other.go @@ -0,0 +1,25 @@ +// Copyright 2021 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 !linux && !notime +// +build !linux,!notime + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +func (c *timeCollector) update(ch chan<- prometheus.Metric) error { + return nil +} diff --git a/collector/timex.go b/collector/timex.go index c444d3ea14..69cbc1a1d0 100644 --- a/collector/timex.go +++ b/collector/timex.go @@ -38,6 +38,9 @@ const ( // 1 second in nanoSeconds = 1000000000 microSeconds = 1000000 + + // See NOTES in adjtimex(2). + ppm16frac = 1000000.0 * 65536.0 ) type timexCollector struct { @@ -183,8 +186,6 @@ func (c *timexCollector) Update(ch chan<- prometheus.Metric) error { } else { divisor = microSeconds } - // See NOTES in adjtimex(2). - const ppm16frac = 1000000.0 * 65536.0 ch <- c.syncStatus.mustNewConstMetric(syncStatus) ch <- c.offset.mustNewConstMetric(float64(timex.Offset) / divisor) diff --git a/collector/uname.go b/collector/uname.go index 14cfefb324..76e66b7e33 100644 --- a/collector/uname.go +++ b/collector/uname.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build (darwin || freebsd || openbsd || linux) && !nouname -// +build darwin freebsd openbsd linux +//go:build (darwin || freebsd || openbsd || netbsd || linux) && !nouname +// +build darwin freebsd openbsd netbsd linux // +build !nouname package collector diff --git a/collector/uname_bsd.go b/collector/uname_bsd.go index 77d47877be..69bf38e910 100644 --- a/collector/uname_bsd.go +++ b/collector/uname_bsd.go @@ -11,14 +11,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build (darwin || freebsd || openbsd) && !nouname -// +build darwin freebsd openbsd +//go:build (darwin || freebsd || openbsd || netbsd) && !nouname +// +build darwin freebsd openbsd netbsd // +build !nouname package collector import ( - "bytes" "strings" "golang.org/x/sys/unix" @@ -33,10 +32,10 @@ func getUname() (uname, error) { nodeName, domainName := parseHostNameAndDomainName(utsname) output := uname{ - SysName: string(utsname.Sysname[:bytes.IndexByte(utsname.Sysname[:], 0)]), - Release: string(utsname.Release[:bytes.IndexByte(utsname.Release[:], 0)]), - Version: string(utsname.Version[:bytes.IndexByte(utsname.Version[:], 0)]), - Machine: string(utsname.Machine[:bytes.IndexByte(utsname.Machine[:], 0)]), + SysName: unix.ByteSliceToString(utsname.Sysname[:]), + Release: unix.ByteSliceToString(utsname.Release[:]), + Version: unix.ByteSliceToString(utsname.Version[:]), + Machine: unix.ByteSliceToString(utsname.Machine[:]), NodeName: nodeName, DomainName: domainName, } @@ -47,7 +46,7 @@ func getUname() (uname, error) { // parseHostNameAndDomainName for FreeBSD,OpenBSD,Darwin. // Attempts to emulate what happens in the Linux uname calls since these OS doesn't have a Domainname. func parseHostNameAndDomainName(utsname unix.Utsname) (hostname string, domainname string) { - nodename := string(utsname.Nodename[:bytes.IndexByte(utsname.Nodename[:], 0)]) + nodename := unix.ByteSliceToString(utsname.Nodename[:]) split := strings.SplitN(nodename, ".", 2) // We'll always have at least a single element in the array. We assume this diff --git a/collector/uname_linux.go b/collector/uname_linux.go index 549c221ab6..4f8bac33e3 100644 --- a/collector/uname_linux.go +++ b/collector/uname_linux.go @@ -16,11 +16,7 @@ package collector -import ( - "bytes" - - "golang.org/x/sys/unix" -) +import "golang.org/x/sys/unix" func getUname() (uname, error) { var utsname unix.Utsname @@ -29,12 +25,12 @@ func getUname() (uname, error) { } output := uname{ - SysName: string(utsname.Sysname[:bytes.IndexByte(utsname.Sysname[:], 0)]), - Release: string(utsname.Release[:bytes.IndexByte(utsname.Release[:], 0)]), - Version: string(utsname.Version[:bytes.IndexByte(utsname.Version[:], 0)]), - Machine: string(utsname.Machine[:bytes.IndexByte(utsname.Machine[:], 0)]), - NodeName: string(utsname.Nodename[:bytes.IndexByte(utsname.Nodename[:], 0)]), - DomainName: string(utsname.Domainname[:bytes.IndexByte(utsname.Domainname[:], 0)]), + SysName: unix.ByteSliceToString(utsname.Sysname[:]), + Release: unix.ByteSliceToString(utsname.Release[:]), + Version: unix.ByteSliceToString(utsname.Version[:]), + Machine: unix.ByteSliceToString(utsname.Machine[:]), + NodeName: unix.ByteSliceToString(utsname.Nodename[:]), + DomainName: unix.ByteSliceToString(utsname.Domainname[:]), } return output, nil diff --git a/collector/vmstat_linux.go b/collector/vmstat_linux.go index a59916573b..cde2df5da5 100644 --- a/collector/vmstat_linux.go +++ b/collector/vmstat_linux.go @@ -24,9 +24,9 @@ import ( "strconv" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) const ( diff --git a/collector/wifi_linux.go b/collector/wifi_linux.go index 4b293ea379..aff8eb2d36 100644 --- a/collector/wifi_linux.go +++ b/collector/wifi_linux.go @@ -20,15 +20,14 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "os" "path/filepath" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/mdlayher/wifi" "github.com/prometheus/client_golang/prometheus" - "gopkg.in/alecthomas/kingpin.v2" ) type wifiCollector struct { @@ -366,7 +365,7 @@ type mockWifiStater struct { } func (s *mockWifiStater) unmarshalJSONFile(filename string, v interface{}) error { - b, err := ioutil.ReadFile(filepath.Join(s.fixtures, filename)) + b, err := os.ReadFile(filepath.Join(s.fixtures, filename)) if err != nil { return err } diff --git a/collector/xfrm.go b/collector/xfrm.go new file mode 100644 index 0000000000..cbdcc97f1f --- /dev/null +++ b/collector/xfrm.go @@ -0,0 +1,228 @@ +// Copyright 2023 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 !noxfrm +// +build !noxfrm + +package collector + +import ( + "fmt" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs" +) + +type xfrmCollector struct { + fs procfs.FS + logger log.Logger +} + +func init() { + registerCollector("xfrm", defaultDisabled, NewXfrmCollector) +} + +// NewXfrmCollector returns a new Collector exposing XFRM stats. +func NewXfrmCollector(logger log.Logger) (Collector, error) { + fs, err := procfs.NewFS(*procPath) + if err != nil { + return nil, fmt.Errorf("failed to open procfs: %w", err) + } + + return &xfrmCollector{ + fs: fs, + logger: logger, + }, nil +} + +var ( + xfrmInErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_error_packets_total"), + "All errors not matched by other", + nil, nil, + ) + xfrmInBufferErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_buffer_error_packets_total"), + "No buffer is left", + nil, nil, + ) + xfrmInHdrErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_hdr_error_packets_total"), + "Header error", + nil, nil, + ) + xfrmInNoStatesDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_no_states_packets_total"), + "No state is found i.e. Either inbound SPI, address, or IPsec protocol at SA is wrong", + nil, nil, + ) + xfrmInStateProtoErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_state_proto_error_packets_total"), + "Transformation protocol specific error e.g. SA key is wrong", + nil, nil, + ) + xfrmInStateModeErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_state_mode_error_packets_total"), + "Transformation mode specific error", + nil, nil, + ) + xfrmInStateSeqErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_state_seq_error_packets_total"), + "Sequence error i.e. Sequence number is out of window", + nil, nil, + ) + xfrmInStateExpiredDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_state_expired_packets_total"), + "State is expired", + nil, nil, + ) + xfrmInStateMismatchDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_state_mismatch_packets_total"), + "State has mismatch option e.g. UDP encapsulation type is mismatch", + nil, nil, + ) + xfrmInStateInvalidDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_state_invalid_packets_total"), + "State is invalid", + nil, nil, + ) + xfrmInTmplMismatchDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_tmpl_mismatch_packets_total"), + "No matching template for states e.g. Inbound SAs are correct but SP rule is wrong", + nil, nil, + ) + xfrmInNoPolsDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_no_pols_packets_total"), + "No policy is found for states e.g. Inbound SAs are correct but no SP is found", + nil, nil, + ) + xfrmInPolBlockDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_pol_block_packets_total"), + "Policy discards", + nil, nil, + ) + xfrmInPolErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "in_pol_error_packets_total"), + "Policy error", + nil, nil, + ) + xfrmOutErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_error_packets_total"), + "All errors which is not matched others", + nil, nil, + ) + xfrmOutBundleGenErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_bundle_gen_error_packets_total"), + "Bundle generation error", + nil, nil, + ) + xfrmOutBundleCheckErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_bundle_check_error_packets_total"), + "Bundle check error", + nil, nil, + ) + xfrmOutNoStatesDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_no_states_packets_total"), + "No state is found", + nil, nil, + ) + xfrmOutStateProtoErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_state_proto_error_packets_total"), + "Transformation protocol specific error", + nil, nil, + ) + xfrmOutStateModeErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_state_mode_error_packets_total"), + "Transformation mode specific error", + nil, nil, + ) + xfrmOutStateSeqErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_state_seq_error_packets_total"), + "Sequence error i.e. Sequence number overflow", + nil, nil, + ) + xfrmOutStateExpiredDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_state_expired_packets_total"), + "State is expired", + nil, nil, + ) + xfrmOutPolBlockDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_pol_block_packets_total"), + "Policy discards", + nil, nil, + ) + xfrmOutPolDeadDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_pol_dead_packets_total"), + "Policy is dead", + nil, nil, + ) + xfrmOutPolErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_pol_error_packets_total"), + "Policy error", + nil, nil, + ) + xfrmFwdHdrErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "fwd_hdr_error_packets_total"), + "Forward routing of a packet is not allowed", + nil, nil, + ) + xfrmOutStateInvalidDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "out_state_invalid_packets_total"), + "State is invalid, perhaps expired", + nil, nil, + ) + xfrmAcquireErrorDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "xfrm", "acquire_error_packets_total"), + "State hasn’t been fully acquired before use", + nil, nil, + ) +) + +func (c *xfrmCollector) Update(ch chan<- prometheus.Metric) error { + stat, err := c.fs.NewXfrmStat() + if err != nil { + return err + } + + ch <- prometheus.MustNewConstMetric(xfrmInErrorDesc, prometheus.CounterValue, float64(stat.XfrmInError)) + ch <- prometheus.MustNewConstMetric(xfrmInBufferErrorDesc, prometheus.CounterValue, float64(stat.XfrmInBufferError)) + ch <- prometheus.MustNewConstMetric(xfrmInHdrErrorDesc, prometheus.CounterValue, float64(stat.XfrmInHdrError)) + ch <- prometheus.MustNewConstMetric(xfrmInNoStatesDesc, prometheus.CounterValue, float64(stat.XfrmInNoStates)) + ch <- prometheus.MustNewConstMetric(xfrmInStateProtoErrorDesc, prometheus.CounterValue, float64(stat.XfrmInStateProtoError)) + ch <- prometheus.MustNewConstMetric(xfrmInStateModeErrorDesc, prometheus.CounterValue, float64(stat.XfrmInStateModeError)) + ch <- prometheus.MustNewConstMetric(xfrmInStateSeqErrorDesc, prometheus.CounterValue, float64(stat.XfrmInStateSeqError)) + ch <- prometheus.MustNewConstMetric(xfrmInStateExpiredDesc, prometheus.CounterValue, float64(stat.XfrmInStateExpired)) + ch <- prometheus.MustNewConstMetric(xfrmInStateMismatchDesc, prometheus.CounterValue, float64(stat.XfrmInStateMismatch)) + ch <- prometheus.MustNewConstMetric(xfrmInStateInvalidDesc, prometheus.CounterValue, float64(stat.XfrmInStateInvalid)) + ch <- prometheus.MustNewConstMetric(xfrmInTmplMismatchDesc, prometheus.CounterValue, float64(stat.XfrmInTmplMismatch)) + ch <- prometheus.MustNewConstMetric(xfrmInNoPolsDesc, prometheus.CounterValue, float64(stat.XfrmInNoPols)) + ch <- prometheus.MustNewConstMetric(xfrmInPolBlockDesc, prometheus.CounterValue, float64(stat.XfrmInPolBlock)) + ch <- prometheus.MustNewConstMetric(xfrmInPolErrorDesc, prometheus.CounterValue, float64(stat.XfrmInPolError)) + ch <- prometheus.MustNewConstMetric(xfrmOutErrorDesc, prometheus.CounterValue, float64(stat.XfrmOutError)) + ch <- prometheus.MustNewConstMetric(xfrmOutBundleGenErrorDesc, prometheus.CounterValue, float64(stat.XfrmOutBundleGenError)) + ch <- prometheus.MustNewConstMetric(xfrmOutBundleCheckErrorDesc, prometheus.CounterValue, float64(stat.XfrmOutBundleCheckError)) + ch <- prometheus.MustNewConstMetric(xfrmOutNoStatesDesc, prometheus.CounterValue, float64(stat.XfrmOutNoStates)) + ch <- prometheus.MustNewConstMetric(xfrmOutStateProtoErrorDesc, prometheus.CounterValue, float64(stat.XfrmOutStateProtoError)) + ch <- prometheus.MustNewConstMetric(xfrmOutStateModeErrorDesc, prometheus.CounterValue, float64(stat.XfrmOutStateModeError)) + ch <- prometheus.MustNewConstMetric(xfrmOutStateSeqErrorDesc, prometheus.CounterValue, float64(stat.XfrmOutStateSeqError)) + ch <- prometheus.MustNewConstMetric(xfrmOutStateExpiredDesc, prometheus.CounterValue, float64(stat.XfrmOutStateExpired)) + ch <- prometheus.MustNewConstMetric(xfrmOutPolBlockDesc, prometheus.CounterValue, float64(stat.XfrmOutPolBlock)) + ch <- prometheus.MustNewConstMetric(xfrmOutPolDeadDesc, prometheus.CounterValue, float64(stat.XfrmOutPolDead)) + ch <- prometheus.MustNewConstMetric(xfrmOutPolErrorDesc, prometheus.CounterValue, float64(stat.XfrmOutPolError)) + ch <- prometheus.MustNewConstMetric(xfrmFwdHdrErrorDesc, prometheus.CounterValue, float64(stat.XfrmFwdHdrError)) + ch <- prometheus.MustNewConstMetric(xfrmOutStateInvalidDesc, prometheus.CounterValue, float64(stat.XfrmOutStateInvalid)) + ch <- prometheus.MustNewConstMetric(xfrmAcquireErrorDesc, prometheus.CounterValue, float64(stat.XfrmAcquireError)) + + return err +} diff --git a/collector/xfrm_test.go b/collector/xfrm_test.go new file mode 100644 index 0000000000..2e1ac02899 --- /dev/null +++ b/collector/xfrm_test.go @@ -0,0 +1,151 @@ +// Copyright 2023 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 !noxfrm +// +build !noxfrm + +package collector + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" +) + +type testXfrmCollector struct { + xc Collector +} + +func (c testXfrmCollector) Collect(ch chan<- prometheus.Metric) { + c.xc.Update(ch) +} + +func (c testXfrmCollector) Describe(ch chan<- *prometheus.Desc) { + prometheus.DescribeByCollect(c, ch) +} + +func TestXfrmStats(t *testing.T) { + testcase := `# HELP node_xfrm_acquire_error_packets_total State hasn’t been fully acquired before use + # TYPE node_xfrm_acquire_error_packets_total counter + node_xfrm_acquire_error_packets_total 24532 + # HELP node_xfrm_fwd_hdr_error_packets_total Forward routing of a packet is not allowed + # TYPE node_xfrm_fwd_hdr_error_packets_total counter + node_xfrm_fwd_hdr_error_packets_total 6654 + # HELP node_xfrm_in_buffer_error_packets_total No buffer is left + # TYPE node_xfrm_in_buffer_error_packets_total counter + node_xfrm_in_buffer_error_packets_total 2 + # HELP node_xfrm_in_error_packets_total All errors not matched by other + # TYPE node_xfrm_in_error_packets_total counter + node_xfrm_in_error_packets_total 1 + # HELP node_xfrm_in_hdr_error_packets_total Header error + # TYPE node_xfrm_in_hdr_error_packets_total counter + node_xfrm_in_hdr_error_packets_total 4 + # HELP node_xfrm_in_no_pols_packets_total No policy is found for states e.g. Inbound SAs are correct but no SP is found + # TYPE node_xfrm_in_no_pols_packets_total counter + node_xfrm_in_no_pols_packets_total 65432 + # HELP node_xfrm_in_no_states_packets_total No state is found i.e. Either inbound SPI, address, or IPsec protocol at SA is wrong + # TYPE node_xfrm_in_no_states_packets_total counter + node_xfrm_in_no_states_packets_total 3 + # HELP node_xfrm_in_pol_block_packets_total Policy discards + # TYPE node_xfrm_in_pol_block_packets_total counter + node_xfrm_in_pol_block_packets_total 100 + # HELP node_xfrm_in_pol_error_packets_total Policy error + # TYPE node_xfrm_in_pol_error_packets_total counter + node_xfrm_in_pol_error_packets_total 10000 + # HELP node_xfrm_in_state_expired_packets_total State is expired + # TYPE node_xfrm_in_state_expired_packets_total counter + node_xfrm_in_state_expired_packets_total 7 + # HELP node_xfrm_in_state_invalid_packets_total State is invalid + # TYPE node_xfrm_in_state_invalid_packets_total counter + node_xfrm_in_state_invalid_packets_total 55555 + # HELP node_xfrm_in_state_mismatch_packets_total State has mismatch option e.g. UDP encapsulation type is mismatch + # TYPE node_xfrm_in_state_mismatch_packets_total counter + node_xfrm_in_state_mismatch_packets_total 23451 + # HELP node_xfrm_in_state_mode_error_packets_total Transformation mode specific error + # TYPE node_xfrm_in_state_mode_error_packets_total counter + node_xfrm_in_state_mode_error_packets_total 100 + # HELP node_xfrm_in_state_proto_error_packets_total Transformation protocol specific error e.g. SA key is wrong + # TYPE node_xfrm_in_state_proto_error_packets_total counter + node_xfrm_in_state_proto_error_packets_total 40 + # HELP node_xfrm_in_state_seq_error_packets_total Sequence error i.e. Sequence number is out of window + # TYPE node_xfrm_in_state_seq_error_packets_total counter + node_xfrm_in_state_seq_error_packets_total 6000 + # HELP node_xfrm_in_tmpl_mismatch_packets_total No matching template for states e.g. Inbound SAs are correct but SP rule is wrong + # TYPE node_xfrm_in_tmpl_mismatch_packets_total counter + node_xfrm_in_tmpl_mismatch_packets_total 51 + # HELP node_xfrm_out_bundle_check_error_packets_total Bundle check error + # TYPE node_xfrm_out_bundle_check_error_packets_total counter + node_xfrm_out_bundle_check_error_packets_total 555 + # HELP node_xfrm_out_bundle_gen_error_packets_total Bundle generation error + # TYPE node_xfrm_out_bundle_gen_error_packets_total counter + node_xfrm_out_bundle_gen_error_packets_total 43321 + # HELP node_xfrm_out_error_packets_total All errors which is not matched others + # TYPE node_xfrm_out_error_packets_total counter + node_xfrm_out_error_packets_total 1e+06 + # HELP node_xfrm_out_no_states_packets_total No state is found + # TYPE node_xfrm_out_no_states_packets_total counter + node_xfrm_out_no_states_packets_total 869 + # HELP node_xfrm_out_pol_block_packets_total Policy discards + # TYPE node_xfrm_out_pol_block_packets_total counter + node_xfrm_out_pol_block_packets_total 43456 + # HELP node_xfrm_out_pol_dead_packets_total Policy is dead + # TYPE node_xfrm_out_pol_dead_packets_total counter + node_xfrm_out_pol_dead_packets_total 7656 + # HELP node_xfrm_out_pol_error_packets_total Policy error + # TYPE node_xfrm_out_pol_error_packets_total counter + node_xfrm_out_pol_error_packets_total 1454 + # HELP node_xfrm_out_state_expired_packets_total State is expired + # TYPE node_xfrm_out_state_expired_packets_total counter + node_xfrm_out_state_expired_packets_total 565 + # HELP node_xfrm_out_state_invalid_packets_total State is invalid, perhaps expired + # TYPE node_xfrm_out_state_invalid_packets_total counter + node_xfrm_out_state_invalid_packets_total 28765 + # HELP node_xfrm_out_state_mode_error_packets_total Transformation mode specific error + # TYPE node_xfrm_out_state_mode_error_packets_total counter + node_xfrm_out_state_mode_error_packets_total 8 + # HELP node_xfrm_out_state_proto_error_packets_total Transformation protocol specific error + # TYPE node_xfrm_out_state_proto_error_packets_total counter + node_xfrm_out_state_proto_error_packets_total 4542 + # HELP node_xfrm_out_state_seq_error_packets_total Sequence error i.e. Sequence number overflow + # TYPE node_xfrm_out_state_seq_error_packets_total counter + node_xfrm_out_state_seq_error_packets_total 543 + ` + *procPath = "fixtures/proc" + + logger := log.NewLogfmtLogger(os.Stderr) + c, err := NewXfrmCollector(logger) + if err != nil { + t.Fatal(err) + } + reg := prometheus.NewRegistry() + reg.MustRegister(&testXfrmCollector{xc: c}) + + sink := make(chan prometheus.Metric) + go func() { + err = c.Update(sink) + if err != nil { + panic(fmt.Errorf("failed to update collector: %s", err)) + } + close(sink) + }() + + err = testutil.GatherAndCompare(reg, strings.NewReader(testcase)) + if err != nil { + t.Fatal(err) + } +} diff --git a/collector/zfs.go b/collector/zfs.go index 8ddbe3c278..df1a97aec3 100644 --- a/collector/zfs.go +++ b/collector/zfs.go @@ -52,7 +52,7 @@ func NewZFSCollector(logger log.Logger) (Collector, error) { linuxPathMap: map[string]string{ "zfs_abd": "abdstats", "zfs_arc": "arcstats", - "zfs_dbuf": "dbuf_stats", + "zfs_dbuf": "dbufstats", "zfs_dmu_tx": "dmu_tx", "zfs_dnode": "dnodestats", "zfs_fm": "fm", diff --git a/collector/zfs_freebsd.go b/collector/zfs_freebsd.go index 2418b229d0..bc4aa1c3f7 100644 --- a/collector/zfs_freebsd.go +++ b/collector/zfs_freebsd.go @@ -17,9 +17,8 @@ package collector import ( - "fmt" - "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" ) @@ -214,6 +213,7 @@ func NewZfsCollector(logger log.Logger) (Collector, error) { dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, }, + // when FreeBSD 14.0+, `meta/pm/pd` install of `p`. { name: "arcstats_p_bytes", description: "ZFS ARC MRU target size", @@ -221,6 +221,27 @@ func NewZfsCollector(logger log.Logger) (Collector, error) { dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, }, + { + name: "arcstats_meta_bytes", + description: "ZFS ARC metadata target frac ", + mib: "kstat.zfs.misc.arcstats.meta", + dataType: bsdSysctlTypeUint64, + valueType: prometheus.GaugeValue, + }, + { + name: "arcstats_pd_bytes", + description: "ZFS ARC data MRU target frac", + mib: "kstat.zfs.misc.arcstats.pd", + dataType: bsdSysctlTypeUint64, + valueType: prometheus.GaugeValue, + }, + { + name: "arcstats_pm_bytes", + description: "ZFS ARC meta MRU target frac", + mib: "kstat.zfs.misc.arcstats.pm", + dataType: bsdSysctlTypeUint64, + valueType: prometheus.GaugeValue, + }, { name: "arcstats_size_bytes", description: "ZFS ARC size", @@ -251,7 +272,9 @@ func (c *zfsCollector) Update(ch chan<- prometheus.Metric) error { for _, m := range c.sysctls { v, err := m.Value() if err != nil { - return fmt.Errorf("couldn't get sysctl: %w", err) + // debug logging + level.Debug(c.logger).Log("name", m.name, "couldn't get sysctl:", err) + continue } ch <- prometheus.MustNewConstMetric( diff --git a/collector/zfs_linux.go b/collector/zfs_linux.go index 735e2154c9..ec195b3d62 100644 --- a/collector/zfs_linux.go +++ b/collector/zfs_linux.go @@ -35,14 +35,14 @@ const ( // kstatDataChar = "0" // kstatDataInt32 = "1" // kstatDataUint32 = "2" - // kstatDataInt64 = "3" + kstatDataInt64 = "3" kstatDataUint64 = "4" // kstatDataLong = "5" // kstatDataUlong = "6" // kstatDataString = "7" ) -var zfsPoolStatesName = []string{"online", "degraded", "faulted", "offline", "removed", "unavail"} +var zfsPoolStatesName = []string{"online", "degraded", "faulted", "offline", "removed", "unavail", "suspended"} func (c *zfsCollector) openProcFile(path string) (*os.File, error) { file, err := os.Open(procFilePath(path)) @@ -74,10 +74,6 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error { return err } - if zpoolPaths == nil { - return nil - } - for _, zpoolPath := range zpoolPaths { file, err := os.Open(zpoolPath) if err != nil { @@ -167,7 +163,7 @@ func (c *zfsCollector) parseProcfsFile(reader io.Reader, fmtExt string, handler // kstat data type (column 2) should be KSTAT_DATA_UINT64, otherwise ignore // TODO: when other KSTAT_DATA_* types arrive, much of this will need to be restructured - if parts[1] == kstatDataUint64 { + if parts[1] == kstatDataUint64 || parts[1] == kstatDataInt64 { key := fmt.Sprintf("kstat.zfs.misc.%s.%s", fmtExt, parts[0]) value, err := strconv.ParseUint(parts[2], 10, 64) if err != nil { diff --git a/collector/zfs_linux_test.go b/collector/zfs_linux_test.go index b9aec14480..69e4ed8fc1 100644 --- a/collector/zfs_linux_test.go +++ b/collector/zfs_linux_test.go @@ -391,7 +391,7 @@ func TestAbdstatsParsing(t *testing.T) { } func TestDbufstatsParsing(t *testing.T) { - dbufstatsFile, err := os.Open("fixtures/proc/spl/kstat/zfs/dbuf_stats") + dbufstatsFile, err := os.Open("fixtures/proc/spl/kstat/zfs/dbufstats") if err != nil { t.Fatal(err) } @@ -535,6 +535,15 @@ func TestPoolStateParsing(t *testing.T) { t.Fatalf("Incorrect parsed value for degraded state") } } + if poolName == "pool2" { + if isActive != uint64(1) && stateName == "suspended" { + t.Fatalf("Incorrect parsed value for suspended state") + } + if isActive != uint64(0) && stateName != "suspended" { + t.Fatalf("Incorrect parsed value for suspended state") + } + } + }) file.Close() if err != nil { diff --git a/collector/zfs_solaris.go b/collector/zfs_solaris.go index 040f31dbbd..52f2500f25 100644 --- a/collector/zfs_solaris.go +++ b/collector/zfs_solaris.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build solaris && !nozfs -// +build solaris,!nozfs +//go:build !nozfs +// +build !nozfs package collector diff --git a/docs/TIME.md b/docs/TIME.md index 340c72d65c..4f0b01a04b 100644 --- a/docs/TIME.md +++ b/docs/TIME.md @@ -2,6 +2,8 @@ ## `ntp` collector +NOTE: This collector is deprecated and will be removed in the next major version release. + This collector is intended for usage with local NTP daemons including [ntp.org](http://ntp.org/), [chrony](https://chrony.tuxfamily.org/comparison.html), and [OpenNTPD](http://www.openntpd.org/). Note, some chrony packages have `local stratum 10` configuration value making chrony a valid server when it is unsynchronised. This configuration makes one of the heuristics that derive `node_ntp_sanity` unreliable. diff --git a/docs/example-16-compatibility-rules-new-to-old.yml b/docs/example-16-compatibility-rules-new-to-old.yml index 1d94672cc9..3d74eb5de7 100644 --- a/docs/example-16-compatibility-rules-new-to-old.yml +++ b/docs/example-16-compatibility-rules-new-to-old.yml @@ -21,7 +21,7 @@ groups: record: node_intr - name: node_exporter-16-cpu rules: - - expr: label_replace(node_cpu_seconds_total, "cpu", "$1", "cpu", "cpu(.+)") + - expr: label_replace(node_cpu_seconds_total, "cpu", "cpu$1", "cpu", "(.+)") record: node_cpu - name: node_exporter-16-diskstats rules: diff --git a/docs/example-16-compatibility-rules.yml b/docs/example-16-compatibility-rules.yml index f79ebb5040..f05e1b4210 100644 --- a/docs/example-16-compatibility-rules.yml +++ b/docs/example-16-compatibility-rules.yml @@ -21,8 +21,8 @@ groups: expr: node_intr - name: node_exporter-16-cpu rules: - - record: node_cpu_seconds_total - expr: label_replace(node_cpu, "cpu", "$1", "cpu", "cpu(.+)") + - record: node_cpu + expr: label_replace(node_cpu_seconds_total, "cpu", "$1", "cpu", "cpu(.+)") - name: node_exporter-16-diskstats rules: - record: node_disk_read_bytes_total diff --git a/docs/node-mixin/README.md b/docs/node-mixin/README.md index 492409c3c8..824385ec71 100644 --- a/docs/node-mixin/README.md +++ b/docs/node-mixin/README.md @@ -10,33 +10,36 @@ for Grafana. To use them, you need to have `jsonnet` (v0.16+) and `jb` installed. If you have a working Go development environment, it's easiest to run the following: + ```bash -$ go install github.com/google/go-jsonnet/cmd/jsonnet@latest -$ go install github.com/google/go-jsonnet/cmd/jsonnetfmt@latest -$ go install github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb@latest +go install github.com/google/go-jsonnet/cmd/jsonnet@latest +go install github.com/google/go-jsonnet/cmd/jsonnetfmt@latest +go install github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb@latest ``` Next, install the dependencies by running the following command in this directory: + ```bash -$ jb install +jb install ``` You can then build the Prometheus rules files `node_alerts.yaml` and `node_rules.yaml`: + ```bash -$ make node_alerts.yaml node_rules.yaml +make node_alerts.yaml node_rules.yaml ``` You can also build a directory `dashboard_out` with the JSON dashboard files for Grafana: + ```bash -$ make dashboards_out +make dashboards_out ``` Note that some of the generated dashboards require recording rules specified in the previously generated `node_rules.yaml`. For more advanced uses of mixins, see -https://github.com/monitoring-mixins/docs. - +. diff --git a/docs/node-mixin/alerts/alerts.libsonnet b/docs/node-mixin/alerts/alerts.libsonnet index 1d81136a81..c346480906 100644 --- a/docs/node-mixin/alerts/alerts.libsonnet +++ b/docs/node-mixin/alerts/alerts.libsonnet @@ -8,11 +8,11 @@ alert: 'NodeFilesystemSpaceFillingUp', expr: ||| ( - node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < %(fsSpaceFillingUpWarningThreshold)d + node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < %(fsSpaceFillingUpWarningThreshold)d and - predict_linear(node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s}[6h], 24*60*60) < 0 + predict_linear(node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s}[%(fsSpaceFillingUpPredictionWindow)s], 24*60*60) < 0 and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '1h', @@ -21,18 +21,18 @@ }, annotations: { summary: 'Filesystem is predicted to run out of space within the next 24 hours.', - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up.', + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up.', }, }, { alert: 'NodeFilesystemSpaceFillingUp', expr: ||| ( - node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < %(fsSpaceFillingUpCriticalThreshold)d + node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < %(fsSpaceFillingUpCriticalThreshold)d and - predict_linear(node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s}[6h], 4*60*60) < 0 + predict_linear(node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s}[6h], 4*60*60) < 0 and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '1h', @@ -41,16 +41,16 @@ }, annotations: { summary: 'Filesystem is predicted to run out of space within the next 4 hours.', - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up fast.', + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up fast.', }, }, { alert: 'NodeFilesystemAlmostOutOfSpace', expr: ||| ( - node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < %(fsSpaceAvailableCriticalThreshold)d + node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < %(fsSpaceAvailableWarningThreshold)d and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '30m', @@ -58,17 +58,17 @@ severity: 'warning', }, annotations: { - summary: 'Filesystem has less than %(fsSpaceAvailableCriticalThreshold)d%% space left.' % $._config, - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left.', + summary: 'Filesystem has less than %(fsSpaceAvailableWarningThreshold)d%% space left.' % $._config, + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left.', }, }, { alert: 'NodeFilesystemAlmostOutOfSpace', expr: ||| ( - node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < %(fsSpaceAvailableWarningThreshold)d + node_filesystem_avail_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_size_bytes{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < %(fsSpaceAvailableCriticalThreshold)d and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '30m', @@ -76,19 +76,19 @@ severity: '%(nodeCriticalSeverity)s' % $._config, }, annotations: { - summary: 'Filesystem has less than %(fsSpaceAvailableWarningThreshold)d%% space left.' % $._config, - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left.', + summary: 'Filesystem has less than %(fsSpaceAvailableCriticalThreshold)d%% space left.' % $._config, + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left.', }, }, { alert: 'NodeFilesystemFilesFillingUp', expr: ||| ( - node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < 40 + node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < 40 and - predict_linear(node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s}[6h], 24*60*60) < 0 + predict_linear(node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s}[6h], 24*60*60) < 0 and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '1h', @@ -97,18 +97,18 @@ }, annotations: { summary: 'Filesystem is predicted to run out of inodes within the next 24 hours.', - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up.', + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up.', }, }, { alert: 'NodeFilesystemFilesFillingUp', expr: ||| ( - node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < 20 + node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < 20 and - predict_linear(node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s}[6h], 4*60*60) < 0 + predict_linear(node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s}[6h], 4*60*60) < 0 and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '1h', @@ -117,16 +117,16 @@ }, annotations: { summary: 'Filesystem is predicted to run out of inodes within the next 4 hours.', - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up fast.', + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up fast.', }, }, { alert: 'NodeFilesystemAlmostOutOfFiles', expr: ||| ( - node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < 5 + node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < 5 and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '1h', @@ -135,16 +135,16 @@ }, annotations: { summary: 'Filesystem has less than 5% inodes left.', - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left.', + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left.', }, }, { alert: 'NodeFilesystemAlmostOutOfFiles', expr: ||| ( - node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s} * 100 < 3 + node_filesystem_files_free{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} / node_filesystem_files{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} * 100 < 3 and - node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s} == 0 + node_filesystem_readonly{%(nodeExporterSelector)s,%(fsSelector)s,%(fsMountpointSelector)s} == 0 ) ||| % $._config, 'for': '1h', @@ -153,13 +153,13 @@ }, annotations: { summary: 'Filesystem has less than 3% inodes left.', - description: 'Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left.', + description: 'Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left.', }, }, { alert: 'NodeNetworkReceiveErrs', expr: ||| - rate(node_network_receive_errs_total[2m]) / rate(node_network_receive_packets_total[2m]) > 0.01 + rate(node_network_receive_errs_total{%(nodeExporterSelector)s}[2m]) / rate(node_network_receive_packets_total{%(nodeExporterSelector)s}[2m]) > 0.01 ||| % $._config, 'for': '1h', labels: { @@ -173,7 +173,7 @@ { alert: 'NodeNetworkTransmitErrs', expr: ||| - rate(node_network_transmit_errs_total[2m]) / rate(node_network_transmit_packets_total[2m]) > 0.01 + rate(node_network_transmit_errs_total{%(nodeExporterSelector)s}[2m]) / rate(node_network_transmit_packets_total{%(nodeExporterSelector)s}[2m]) > 0.01 ||| % $._config, 'for': '1h', labels: { @@ -187,7 +187,7 @@ { alert: 'NodeHighNumberConntrackEntriesUsed', expr: ||| - (node_nf_conntrack_entries / node_nf_conntrack_entries_limit) > 0.75 + (node_nf_conntrack_entries{%(nodeExporterSelector)s} / node_nf_conntrack_entries_limit) > 0.75 ||| % $._config, annotations: { summary: 'Number of conntrack are getting close to the limit.', @@ -204,7 +204,7 @@ ||| % $._config, annotations: { summary: 'Node Exporter text file collector failed to scrape.', - description: 'Node Exporter text file collector failed to scrape.', + description: 'Node Exporter text file collector on {{ $labels.instance }} failed to scrape.', }, labels: { severity: 'warning', @@ -214,15 +214,15 @@ alert: 'NodeClockSkewDetected', expr: ||| ( - node_timex_offset_seconds > 0.05 + node_timex_offset_seconds{%(nodeExporterSelector)s} > 0.05 and - deriv(node_timex_offset_seconds[5m]) >= 0 + deriv(node_timex_offset_seconds{%(nodeExporterSelector)s}[5m]) >= 0 ) or ( - node_timex_offset_seconds < -0.05 + node_timex_offset_seconds{%(nodeExporterSelector)s} < -0.05 and - deriv(node_timex_offset_seconds[5m]) <= 0 + deriv(node_timex_offset_seconds{%(nodeExporterSelector)s}[5m]) <= 0 ) ||| % $._config, 'for': '10m', @@ -231,15 +231,15 @@ }, annotations: { summary: 'Clock skew detected.', - description: 'Clock on {{ $labels.instance }} is out of sync by more than 300s. Ensure NTP is configured correctly on this host.', + description: 'Clock at {{ $labels.instance }} is out of sync by more than 0.05s. Ensure NTP is configured correctly on this host.', }, }, { alert: 'NodeClockNotSynchronising', expr: ||| - min_over_time(node_timex_sync_status[5m]) == 0 + min_over_time(node_timex_sync_status{%(nodeExporterSelector)s}[5m]) == 0 and - node_timex_maxerror_seconds >= 16 + node_timex_maxerror_seconds{%(nodeExporterSelector)s} >= 16 ||| % $._config, 'for': '10m', labels: { @@ -247,41 +247,41 @@ }, annotations: { summary: 'Clock not synchronising.', - description: 'Clock on {{ $labels.instance }} is not synchronising. Ensure NTP is configured on this host.', + description: 'Clock at {{ $labels.instance }} is not synchronising. Ensure NTP is configured on this host.', }, }, { alert: 'NodeRAIDDegraded', expr: ||| - node_md_disks_required - ignoring (state) (node_md_disks{state="active"}) > 0 + node_md_disks_required{%(nodeExporterSelector)s,%(diskDeviceSelector)s} - ignoring (state) (node_md_disks{state="active",%(nodeExporterSelector)s,%(diskDeviceSelector)s}) > 0 ||| % $._config, 'for': '15m', labels: { severity: 'critical', }, annotations: { - summary: 'RAID Array is degraded', - description: "RAID array '{{ $labels.device }}' on {{ $labels.instance }} is in degraded state due to one or more disks failures. Number of spare drives is insufficient to fix issue automatically.", + summary: 'RAID Array is degraded.', + description: "RAID array '{{ $labels.device }}' at {{ $labels.instance }} is in degraded state due to one or more disks failures. Number of spare drives is insufficient to fix issue automatically.", }, }, { alert: 'NodeRAIDDiskFailure', expr: ||| - node_md_disks{state="failed"} > 0 + node_md_disks{state="failed",%(nodeExporterSelector)s,%(diskDeviceSelector)s} > 0 ||| % $._config, labels: { severity: 'warning', }, annotations: { - summary: 'Failed device in RAID array', - description: "At least one device in RAID array on {{ $labels.instance }} failed. Array '{{ $labels.device }}' needs attention and possibly a disk swap.", + summary: 'Failed device in RAID array.', + description: "At least one device in RAID array at {{ $labels.instance }} failed. Array '{{ $labels.device }}' needs attention and possibly a disk swap.", }, }, { alert: 'NodeFileDescriptorLimit', expr: ||| ( - node_filefd_allocated{job="node-exporter"} * 100 / node_filefd_maximum{job="node-exporter"} > 70 + node_filefd_allocated{%(nodeExporterSelector)s} * 100 / node_filefd_maximum{%(nodeExporterSelector)s} > 70 ) ||| % $._config, 'for': '15m', @@ -297,7 +297,7 @@ alert: 'NodeFileDescriptorLimit', expr: ||| ( - node_filefd_allocated{job="node-exporter"} * 100 / node_filefd_maximum{job="node-exporter"} > 90 + node_filefd_allocated{%(nodeExporterSelector)s} * 100 / node_filefd_maximum{%(nodeExporterSelector)s} > 90 ) ||| % $._config, 'for': '15m', @@ -309,6 +309,118 @@ description: 'File descriptors limit at {{ $labels.instance }} is currently at {{ printf "%.2f" $value }}%.', }, }, + { + alert: 'NodeCPUHighUsage', + expr: ||| + sum without(mode) (avg without (cpu) (rate(node_cpu_seconds_total{%(nodeExporterSelector)s, mode!="idle"}[2m]))) * 100 > %(cpuHighUsageThreshold)d + ||| % $._config, + 'for': '15m', + labels: { + severity: 'info', + }, + annotations: { + summary: 'High CPU usage.', + description: ||| + CPU usage at {{ $labels.instance }} has been above %(cpuHighUsageThreshold)d%% for the last 15 minutes, is currently at {{ printf "%%.2f" $value }}%%. + ||| % $._config, + }, + }, + { + alert: 'NodeSystemSaturation', + expr: ||| + node_load1{%(nodeExporterSelector)s} + / count without (cpu, mode) (node_cpu_seconds_total{%(nodeExporterSelector)s, mode="idle"}) > %(systemSaturationPerCoreThreshold)d + ||| % $._config, + 'for': '15m', + labels: { + severity: 'warning', + }, + annotations: { + summary: 'System saturated, load per core is very high.', + description: ||| + System load per core at {{ $labels.instance }} has been above %(systemSaturationPerCoreThreshold)d for the last 15 minutes, is currently at {{ printf "%%.2f" $value }}. + This might indicate this instance resources saturation and can cause it becoming unresponsive. + ||| % $._config, + }, + }, + { + alert: 'NodeMemoryMajorPagesFaults', + expr: ||| + rate(node_vmstat_pgmajfault{%(nodeExporterSelector)s}[5m]) > %(memoryMajorPagesFaultsThreshold)d + ||| % $._config, + 'for': '15m', + labels: { + severity: 'warning', + }, + annotations: { + summary: 'Memory major page faults are occurring at very high rate.', + description: ||| + Memory major pages are occurring at very high rate at {{ $labels.instance }}, %(memoryMajorPagesFaultsThreshold)d major page faults per second for the last 15 minutes, is currently at {{ printf "%%.2f" $value }}. + Please check that there is enough memory available at this instance. + ||| % $._config, + }, + }, + { + alert: 'NodeMemoryHighUtilization', + expr: ||| + 100 - (node_memory_MemAvailable_bytes{%(nodeExporterSelector)s} / node_memory_MemTotal_bytes{%(nodeExporterSelector)s} * 100) > %(memoryHighUtilizationThreshold)d + ||| % $._config, + 'for': '15m', + labels: { + severity: 'warning', + }, + annotations: { + summary: 'Host is running out of memory.', + description: ||| + Memory is filling up at {{ $labels.instance }}, has been above %(memoryHighUtilizationThreshold)d%% for the last 15 minutes, is currently at {{ printf "%%.2f" $value }}%%. + ||| % $._config, + }, + }, + { + alert: 'NodeDiskIOSaturation', + expr: ||| + rate(node_disk_io_time_weighted_seconds_total{%(nodeExporterSelector)s, %(diskDeviceSelector)s}[5m]) > %(diskIOSaturationThreshold)d + ||| % $._config, + 'for': '30m', + labels: { + severity: 'warning', + }, + annotations: { + summary: 'Disk IO queue is high.', + description: ||| + Disk IO queue (aqu-sq) is high on {{ $labels.device }} at {{ $labels.instance }}, has been above %(diskIOSaturationThreshold)d for the last 30 minutes, is currently at {{ printf "%%.2f" $value }}. + This symptom might indicate disk saturation. + ||| % $._config, + }, + }, + { + alert: 'NodeSystemdServiceFailed', + expr: ||| + node_systemd_unit_state{%(nodeExporterSelector)s, state="failed"} == 1 + ||| % $._config, + 'for': '5m', + labels: { + severity: 'warning', + }, + annotations: { + summary: 'Systemd service has entered failed state.', + description: 'Systemd service {{ $labels.name }} has entered failed state at {{ $labels.instance }}', + }, + }, + { + alert: 'NodeBondingDegraded', + expr: ||| + (node_bonding_slaves - node_bonding_active) != 0 + ||| % $._config, + 'for': '5m', + labels: { + severity: 'warning', + }, + annotations: { + summary: 'Bonding interface is degraded', + description: 'Bonding interface {{ $labels.master }} on {{ $labels.instance }} is in degraded state due to one or more slave failures.', + }, + }, ], }, ], diff --git a/docs/node-mixin/config.libsonnet b/docs/node-mixin/config.libsonnet index eb5ab330b3..bf6c83edd3 100644 --- a/docs/node-mixin/config.libsonnet +++ b/docs/node-mixin/config.libsonnet @@ -16,6 +16,14 @@ // alerting, you can exclude them here, e.g. 'fstype!="tmpfs"'. fsSelector: 'fstype!=""', + // Select the mountpoint for filesystem-related queries. If left + // empty, all mountpoints are selected. For example if you have a + // special purpose tmpfs instance that has a fixed size and will + // always be 100% full, but you still want alerts and dashboards for + // other tmpfs instances, you can exclude those by mountpoint prefix + // like so: 'mountpoint!~"/var/lib/foo.*"'. + fsMountpointSelector: 'mountpoint!=""', + // Select the device for disk-related queries. If left empty, all // devices are selected. If you have unusual devices you don't // want to include in dashboards and alerting, you can exclude @@ -35,22 +43,47 @@ // just a warning for K8s nodes. nodeCriticalSeverity: 'critical', + // CPU utilization (%) on which to trigger the + // 'NodeCPUHighUsage' alert. + cpuHighUsageThreshold: 90, + // Load average 1m (per core) on which to trigger the + // 'NodeSystemSaturation' alert. + systemSaturationPerCoreThreshold: 2, + // Available disk space (%) thresholds on which to trigger the // 'NodeFilesystemSpaceFillingUp' alerts. These alerts fire if the disk // usage grows in a way that it is predicted to run out in 4h or 1d // and if the provided thresholds have been reached right now. - // In some cases you'll want to adjust these, e.g. by default Kubernetes + // In some cases you'll want to adjust these, e.g., by default, Kubernetes // runs the image garbage collection when the disk usage reaches 85% // of its available space. In that case, you'll want to reduce the // critical threshold below to something like 14 or 15, otherwise // the alert could fire under normal node usage. + // Additionally, the prediction window for the alert can be configured + // to account for environments where disk usage can fluctuate within + // a short time frame. By extending the prediction window, you can + // reduce false positives caused by temporary spikes, providing a + // more accurate prediction of disk space issues. fsSpaceFillingUpWarningThreshold: 40, fsSpaceFillingUpCriticalThreshold: 20, + fsSpaceFillingUpPredictionWindow: '6h', // Available disk space (%) thresholds on which to trigger the // 'NodeFilesystemAlmostOutOfSpace' alerts. - fsSpaceAvailableCriticalThreshold: 5, - fsSpaceAvailableWarningThreshold: 3, + fsSpaceAvailableWarningThreshold: 5, + fsSpaceAvailableCriticalThreshold: 3, + + // Memory utilzation (%) level on which to trigger the + // 'NodeMemoryHighUtilization' alert. + memoryHighUtilizationThreshold: 90, + + // Threshold for the rate of memory major page faults to trigger + // 'NodeMemoryMajorPagesFaults' alert. + memoryMajorPagesFaultsThreshold: 500, + + // Disk IO queue level above which to trigger + // 'NodeDiskIOSaturation' alert. + diskIOSaturationThreshold: 10, rateInterval: '5m', // Opt-in for multi-cluster support. diff --git a/docs/node-mixin/dashboards/node.libsonnet b/docs/node-mixin/dashboards/node.libsonnet index ef8d3ae243..898c912d56 100644 --- a/docs/node-mixin/dashboards/node.libsonnet +++ b/docs/node-mixin/dashboards/node.libsonnet @@ -1,256 +1,7 @@ -local grafana = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet'; -local dashboard = grafana.dashboard; -local row = grafana.row; -local prometheus = grafana.prometheus; -local template = grafana.template; -local graphPanel = grafana.graphPanel; -local promgrafonnet = import 'github.com/kubernetes-monitoring/kubernetes-mixin/lib/promgrafonnet/promgrafonnet.libsonnet'; -local gauge = promgrafonnet.gauge; - { + local nodemixin = import '../lib/prom-mixin.libsonnet', grafanaDashboards+:: { - 'nodes.json': - local idleCPU = - graphPanel.new( - 'CPU Usage', - datasource='$datasource', - span=6, - format='percentunit', - max=1, - min=0, - stack=true, - ) - .addTarget(prometheus.target( - ||| - ( - (1 - sum without (mode) (rate(node_cpu_seconds_total{%(nodeExporterSelector)s, mode=~"idle|iowait|steal", instance="$instance"}[$__rate_interval]))) - / ignoring(cpu) group_left - count without (cpu, mode) (node_cpu_seconds_total{%(nodeExporterSelector)s, mode="idle", instance="$instance"}) - ) - ||| % $._config, - legendFormat='{{cpu}}', - intervalFactor=5, - )); - - local systemLoad = - graphPanel.new( - 'Load Average', - datasource='$datasource', - span=6, - format='short', - min=0, - fill=0, - ) - .addTarget(prometheus.target('node_load1{%(nodeExporterSelector)s, instance="$instance"}' % $._config, legendFormat='1m load average')) - .addTarget(prometheus.target('node_load5{%(nodeExporterSelector)s, instance="$instance"}' % $._config, legendFormat='5m load average')) - .addTarget(prometheus.target('node_load15{%(nodeExporterSelector)s, instance="$instance"}' % $._config, legendFormat='15m load average')) - .addTarget(prometheus.target('count(node_cpu_seconds_total{%(nodeExporterSelector)s, instance="$instance", mode="idle"})' % $._config, legendFormat='logical cores')); - - local memoryGraph = - graphPanel.new( - 'Memory Usage', - datasource='$datasource', - span=9, - format='bytes', - stack=true, - min=0, - ) - .addTarget(prometheus.target( - ||| - ( - node_memory_MemTotal_bytes{%(nodeExporterSelector)s, instance="$instance"} - - - node_memory_MemFree_bytes{%(nodeExporterSelector)s, instance="$instance"} - - - node_memory_Buffers_bytes{%(nodeExporterSelector)s, instance="$instance"} - - - node_memory_Cached_bytes{%(nodeExporterSelector)s, instance="$instance"} - ) - ||| % $._config, legendFormat='memory used' - )) - .addTarget(prometheus.target('node_memory_Buffers_bytes{%(nodeExporterSelector)s, instance="$instance"}' % $._config, legendFormat='memory buffers')) - .addTarget(prometheus.target('node_memory_Cached_bytes{%(nodeExporterSelector)s, instance="$instance"}' % $._config, legendFormat='memory cached')) - .addTarget(prometheus.target('node_memory_MemFree_bytes{%(nodeExporterSelector)s, instance="$instance"}' % $._config, legendFormat='memory free')); - - // TODO: It would be nicer to have a gauge that gets a 0-1 range and displays it as a percentage 0%-100%. - // This needs to be added upstream in the promgrafonnet library and then changed here. - // NOTE: avg() is used to circumvent a label change caused by a node_exporter rollout. - local memoryGauge = gauge.new( - 'Memory Usage', - ||| - 100 - - ( - avg(node_memory_MemAvailable_bytes{%(nodeExporterSelector)s, instance="$instance"}) - / - avg(node_memory_MemTotal_bytes{%(nodeExporterSelector)s, instance="$instance"}) - * 100 - ) - ||| % $._config, - ).withLowerBeingBetter(); - - local diskIO = - graphPanel.new( - 'Disk I/O', - datasource='$datasource', - span=6, - min=0, - fill=0, - ) - // TODO: Does it make sense to have those three in the same panel? - .addTarget(prometheus.target( - 'rate(node_disk_read_bytes_total{%(nodeExporterSelector)s, instance="$instance", %(diskDeviceSelector)s}[$__rate_interval])' % $._config, - legendFormat='{{device}} read', - )) - .addTarget(prometheus.target( - 'rate(node_disk_written_bytes_total{%(nodeExporterSelector)s, instance="$instance", %(diskDeviceSelector)s}[$__rate_interval])' % $._config, - legendFormat='{{device}} written', - )) - .addTarget(prometheus.target( - 'rate(node_disk_io_time_seconds_total{%(nodeExporterSelector)s, instance="$instance", %(diskDeviceSelector)s}[$__rate_interval])' % $._config, - legendFormat='{{device}} io time', - )) + - { - seriesOverrides: [ - { - alias: '/ read| written/', - yaxis: 1, - }, - { - alias: '/ io time/', - yaxis: 2, - }, - ], - yaxes: [ - self.yaxe(format='bytes'), - self.yaxe(format='s'), - ], - }; - - // TODO: Somehow partition this by device while excluding read-only devices. - local diskSpaceUsage = - graphPanel.new( - 'Disk Space Usage', - datasource='$datasource', - span=6, - format='bytes', - min=0, - fill=1, - stack=true, - ) - .addTarget(prometheus.target( - ||| - sum( - max by (device) ( - node_filesystem_size_bytes{%(nodeExporterSelector)s, instance="$instance", %(fsSelector)s} - - - node_filesystem_avail_bytes{%(nodeExporterSelector)s, instance="$instance", %(fsSelector)s} - ) - ) - ||| % $._config, - legendFormat='used', - )) - .addTarget(prometheus.target( - ||| - sum( - max by (device) ( - node_filesystem_avail_bytes{%(nodeExporterSelector)s, instance="$instance", %(fsSelector)s} - ) - ) - ||| % $._config, - legendFormat='available', - )) + - { - seriesOverrides: [ - { - alias: 'used', - color: '#E0B400', - }, - { - alias: 'available', - color: '#73BF69', - }, - ], - }; - - local networkReceived = - graphPanel.new( - 'Network Received', - datasource='$datasource', - span=6, - format='bytes', - min=0, - fill=0, - ) - .addTarget(prometheus.target( - 'rate(node_network_receive_bytes_total{%(nodeExporterSelector)s, instance="$instance", device!="lo"}[$__rate_interval])' % $._config, - legendFormat='{{device}}', - )); - - local networkTransmitted = - graphPanel.new( - 'Network Transmitted', - datasource='$datasource', - span=6, - format='bytes', - min=0, - fill=0, - ) - .addTarget(prometheus.target( - 'rate(node_network_transmit_bytes_total{%(nodeExporterSelector)s, instance="$instance", device!="lo"}[$__rate_interval])' % $._config, - legendFormat='{{device}}', - )); - - dashboard.new( - '%sNodes' % $._config.dashboardNamePrefix, - time_from='now-1h', - tags=($._config.dashboardTags), - timezone='utc', - refresh='30s', - graphTooltip='shared_crosshair' - ) - .addTemplate( - { - current: { - text: 'Prometheus', - value: 'Prometheus', - }, - hide: 0, - label: 'Data Source', - name: 'datasource', - options: [], - query: 'prometheus', - refresh: 1, - regex: '', - type: 'datasource', - }, - ) - .addTemplate( - template.new( - 'instance', - '$datasource', - 'label_values(node_exporter_build_info{%(nodeExporterSelector)s}, instance)' % $._config, - refresh='time', - ) - ) - .addRow( - row.new() - .addPanel(idleCPU) - .addPanel(systemLoad) - ) - .addRow( - row.new() - .addPanel(memoryGraph) - .addPanel(memoryGauge) - ) - .addRow( - row.new() - .addPanel(diskIO) - .addPanel(diskSpaceUsage) - ) - .addRow( - row.new() - .addPanel(networkReceived) - .addPanel(networkTransmitted) - ), + 'nodes.json': nodemixin.new(config=$._config, platform='Linux').dashboard, + 'nodes-darwin.json': nodemixin.new(config=$._config, platform='Darwin').dashboard, }, } diff --git a/docs/node-mixin/dashboards/use.libsonnet b/docs/node-mixin/dashboards/use.libsonnet index e830d7b555..65e96dd8dc 100644 --- a/docs/node-mixin/dashboards/use.libsonnet +++ b/docs/node-mixin/dashboards/use.libsonnet @@ -9,8 +9,8 @@ local c = import '../config.libsonnet'; local datasourceTemplate = { current: { - text: 'Prometheus', - value: 'Prometheus', + text: 'default', + value: 'default', }, hide: 0, label: 'Data Source', @@ -307,12 +307,12 @@ local diskSpaceUtilisation = ||| sum without (device) ( max without (fstype, mountpoint) (( - node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(clusterLabel)s="$cluster"} + node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(fsMountpointSelector)s, %(clusterLabel)s="$cluster"} - - node_filesystem_avail_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(clusterLabel)s="$cluster"} + node_filesystem_avail_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(fsMountpointSelector)s, %(clusterLabel)s="$cluster"} ) != 0) ) - / scalar(sum(max without (fstype, mountpoint) (node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(clusterLabel)s="$cluster"}))) + / scalar(sum(max without (fstype, mountpoint) (node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(fsMountpointSelector)s, %(clusterLabel)s="$cluster"}))) ||| % $._config, legendFormat='{{instance}}' )) ) @@ -453,10 +453,10 @@ local diskSpaceUtilisation = sum ( sum without (device) ( max without (fstype, mountpoint, instance, pod) (( - node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s} - node_filesystem_avail_bytes{%(nodeExporterSelector)s, %(fsSelector)s} + node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(fsMountpointSelector)s} - node_filesystem_avail_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(fsMountpointSelector)s} ) != 0) ) - / scalar(sum(max without (fstype, mountpoint) (node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s}))) + / scalar(sum(max without (fstype, mountpoint) (node_filesystem_size_bytes{%(nodeExporterSelector)s, %(fsSelector)s, %(fsMountpointSelector)s}))) ) by (%(clusterLabel)s) ||| % $._config, legendFormat='{{%(clusterLabel)s}}' % $._config )) diff --git a/docs/node-mixin/jsonnetfile.json b/docs/node-mixin/jsonnetfile.json index 46ebffe47c..721d4833a0 100644 --- a/docs/node-mixin/jsonnetfile.json +++ b/docs/node-mixin/jsonnetfile.json @@ -13,17 +13,8 @@ { "source": { "git": { - "remote": "https://github.com/grafana/jsonnet-libs.git", - "subdir": "grafana-builder" - } - }, - "version": "master" - }, - { - "source": { - "git": { - "remote": "https://github.com/kubernetes-monitoring/kubernetes-mixin.git", - "subdir": "lib/promgrafonnet" + "remote": "https://github.com/grafana/grafonnet-lib.git", + "subdir": "grafonnet-7.0" } }, "version": "master" diff --git a/docs/node-mixin/lib/prom-mixin.libsonnet b/docs/node-mixin/lib/prom-mixin.libsonnet new file mode 100644 index 0000000000..6c4d990481 --- /dev/null +++ b/docs/node-mixin/lib/prom-mixin.libsonnet @@ -0,0 +1,504 @@ +local grafana = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet'; +local dashboard = grafana.dashboard; +local row = grafana.row; +local prometheus = grafana.prometheus; +local template = grafana.template; +local graphPanel = grafana.graphPanel; +local grafana70 = import 'github.com/grafana/grafonnet-lib/grafonnet-7.0/grafana.libsonnet'; +local gaugePanel = grafana70.panel.gauge; +local table = grafana70.panel.table; + +{ + + new(config=null, platform=null):: { + + local prometheusDatasourceTemplate = { + current: { + text: 'default', + value: 'default', + }, + hide: 0, + label: 'Data Source', + name: 'datasource', + options: [], + query: 'prometheus', + refresh: 1, + regex: '', + type: 'datasource', + }, + + local instanceTemplatePrototype = + template.new( + 'instance', + '$datasource', + '', + refresh='time', + label='Instance', + ), + local instanceTemplate = + if platform == 'Darwin' then + instanceTemplatePrototype + { query: 'label_values(node_uname_info{%(nodeExporterSelector)s, sysname="Darwin"}, instance)' % config } + else + instanceTemplatePrototype + { query: 'label_values(node_uname_info{%(nodeExporterSelector)s, sysname!="Darwin"}, instance)' % config }, + + + local idleCPU = + graphPanel.new( + 'CPU Usage', + datasource='$datasource', + span=6, + format='percentunit', + max=1, + min=0, + stack=true, + ) + .addTarget(prometheus.target( + ||| + ( + (1 - sum without (mode) (rate(node_cpu_seconds_total{%(nodeExporterSelector)s, mode=~"idle|iowait|steal", instance="$instance"}[$__rate_interval]))) + / ignoring(cpu) group_left + count without (cpu, mode) (node_cpu_seconds_total{%(nodeExporterSelector)s, mode="idle", instance="$instance"}) + ) + ||| % config, + legendFormat='{{cpu}}', + intervalFactor=5, + )), + + local systemLoad = + graphPanel.new( + 'Load Average', + datasource='$datasource', + span=6, + format='short', + min=0, + fill=0, + ) + .addTarget(prometheus.target('node_load1{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='1m load average')) + .addTarget(prometheus.target('node_load5{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='5m load average')) + .addTarget(prometheus.target('node_load15{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='15m load average')) + .addTarget(prometheus.target('count(node_cpu_seconds_total{%(nodeExporterSelector)s, instance="$instance", mode="idle"})' % config, legendFormat='logical cores')), + + local memoryGraphPanelPrototype = + graphPanel.new( + 'Memory Usage', + datasource='$datasource', + span=9, + format='bytes', + min=0, + ), + local memoryGraph = + if platform == 'Linux' then + memoryGraphPanelPrototype { stack: true } + .addTarget(prometheus.target( + ||| + ( + node_memory_MemTotal_bytes{%(nodeExporterSelector)s, instance="$instance"} + - + node_memory_MemFree_bytes{%(nodeExporterSelector)s, instance="$instance"} + - + node_memory_Buffers_bytes{%(nodeExporterSelector)s, instance="$instance"} + - + node_memory_Cached_bytes{%(nodeExporterSelector)s, instance="$instance"} + ) + ||| % config, + legendFormat='memory used' + )) + .addTarget(prometheus.target('node_memory_Buffers_bytes{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='memory buffers')) + .addTarget(prometheus.target('node_memory_Cached_bytes{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='memory cached')) + .addTarget(prometheus.target('node_memory_MemFree_bytes{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='memory free')) + else if platform == 'Darwin' then + // not useful to stack + memoryGraphPanelPrototype { stack: false } + .addTarget(prometheus.target('node_memory_total_bytes{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='Physical Memory')) + .addTarget(prometheus.target( + ||| + ( + node_memory_internal_bytes{%(nodeExporterSelector)s, instance="$instance"} - + node_memory_purgeable_bytes{%(nodeExporterSelector)s, instance="$instance"} + + node_memory_wired_bytes{%(nodeExporterSelector)s, instance="$instance"} + + node_memory_compressed_bytes{%(nodeExporterSelector)s, instance="$instance"} + ) + ||| % config, legendFormat='Memory Used' + )) + .addTarget(prometheus.target( + ||| + ( + node_memory_internal_bytes{%(nodeExporterSelector)s, instance="$instance"} - + node_memory_purgeable_bytes{%(nodeExporterSelector)s, instance="$instance"} + ) + ||| % config, legendFormat='App Memory' + )) + .addTarget(prometheus.target('node_memory_wired_bytes{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='Wired Memory')) + .addTarget(prometheus.target('node_memory_compressed_bytes{%(nodeExporterSelector)s, instance="$instance"}' % config, legendFormat='Compressed')), + + // NOTE: avg() is used to circumvent a label change caused by a node_exporter rollout. + local memoryGaugePanelPrototype = + gaugePanel.new( + title='Memory Usage', + datasource='$datasource', + ) + .addThresholdStep('rgba(50, 172, 45, 0.97)') + .addThresholdStep('rgba(237, 129, 40, 0.89)', 80) + .addThresholdStep('rgba(245, 54, 54, 0.9)', 90) + .setFieldConfig(max=100, min=0, unit='percent') + + { + span: 3, + }, + + local memoryGauge = + if platform == 'Linux' then + memoryGaugePanelPrototype + + .addTarget(prometheus.target( + ||| + 100 - + ( + avg(node_memory_MemAvailable_bytes{%(nodeExporterSelector)s, instance="$instance"}) / + avg(node_memory_MemTotal_bytes{%(nodeExporterSelector)s, instance="$instance"}) + * 100 + ) + ||| % config, + )) + + else if platform == 'Darwin' then + memoryGaugePanelPrototype + .addTarget(prometheus.target( + ||| + ( + ( + avg(node_memory_internal_bytes{%(nodeExporterSelector)s, instance="$instance"}) - + avg(node_memory_purgeable_bytes{%(nodeExporterSelector)s, instance="$instance"}) + + avg(node_memory_wired_bytes{%(nodeExporterSelector)s, instance="$instance"}) + + avg(node_memory_compressed_bytes{%(nodeExporterSelector)s, instance="$instance"}) + ) / + avg(node_memory_total_bytes{%(nodeExporterSelector)s, instance="$instance"}) + ) + * + 100 + ||| % config + )), + + local diskIO = + graphPanel.new( + 'Disk I/O', + datasource='$datasource', + span=6, + min=0, + fill=0, + ) + // TODO: Does it make sense to have those three in the same panel? + .addTarget(prometheus.target( + 'rate(node_disk_read_bytes_total{%(nodeExporterSelector)s, instance="$instance", %(diskDeviceSelector)s}[$__rate_interval])' % config, + legendFormat='{{device}} read', + intervalFactor=1, + )) + .addTarget(prometheus.target( + 'rate(node_disk_written_bytes_total{%(nodeExporterSelector)s, instance="$instance", %(diskDeviceSelector)s}[$__rate_interval])' % config, + legendFormat='{{device}} written', + intervalFactor=1, + )) + .addTarget(prometheus.target( + 'rate(node_disk_io_time_seconds_total{%(nodeExporterSelector)s, instance="$instance", %(diskDeviceSelector)s}[$__rate_interval])' % config, + legendFormat='{{device}} io time', + intervalFactor=1, + )) + + { + seriesOverrides: [ + { + alias: '/ read| written/', + yaxis: 1, + }, + { + alias: '/ io time/', + yaxis: 2, + }, + ], + yaxes: [ + self.yaxe(format='Bps'), + self.yaxe(format='percentunit'), + ], + }, + + local diskSpaceUsage = + table.new( + title='Disk Space Usage', + datasource='$datasource', + ) + .setFieldConfig(unit='decbytes') + .addThresholdStep(color='green', value=null) + .addThresholdStep(color='yellow', value=0.8) + .addThresholdStep(color='red', value=0.9) + .addTarget(prometheus.target( + ||| + max by (mountpoint) (node_filesystem_size_bytes{%(nodeExporterSelector)s, instance="$instance", %(fsSelector)s, %(fsMountpointSelector)s}) + ||| % config, + legendFormat='', + instant=true, + format='table' + )) + .addTarget(prometheus.target( + ||| + max by (mountpoint) (node_filesystem_avail_bytes{%(nodeExporterSelector)s, instance="$instance", %(fsSelector)s, %(fsMountpointSelector)s}) + ||| % config, + legendFormat='', + instant=true, + format='table' + )) + .addOverride( + matcher={ + id: 'byName', + options: 'Mounted on', + }, + properties=[ + { + id: 'custom.width', + value: 260, + }, + ], + ) + .addOverride( + matcher={ + id: 'byName', + options: 'Size', + }, + properties=[ + + { + id: 'custom.width', + value: 93, + }, + + ], + ) + .addOverride( + matcher={ + id: 'byName', + options: 'Used', + }, + properties=[ + { + id: 'custom.width', + value: 72, + }, + ], + ) + .addOverride( + matcher={ + id: 'byName', + options: 'Available', + }, + properties=[ + { + id: 'custom.width', + value: 88, + }, + ], + ) + + .addOverride( + matcher={ + id: 'byName', + options: 'Used, %', + }, + properties=[ + { + id: 'unit', + value: 'percentunit', + }, + { + id: 'custom.displayMode', + value: 'gradient-gauge', + }, + { + id: 'max', + value: 1, + }, + { + id: 'min', + value: 0, + }, + ] + ) + + { span: 6 } + + { + transformations: [ + { + id: 'groupBy', + options: { + fields: { + 'Value #A': { + aggregations: [ + 'lastNotNull', + ], + operation: 'aggregate', + }, + 'Value #B': { + aggregations: [ + 'lastNotNull', + ], + operation: 'aggregate', + }, + mountpoint: { + aggregations: [], + operation: 'groupby', + }, + }, + }, + }, + { + id: 'merge', + options: {}, + }, + { + id: 'calculateField', + options: { + alias: 'Used', + binary: { + left: 'Value #A (lastNotNull)', + operator: '-', + reducer: 'sum', + right: 'Value #B (lastNotNull)', + }, + mode: 'binary', + reduce: { + reducer: 'sum', + }, + }, + }, + { + id: 'calculateField', + options: { + alias: 'Used, %', + binary: { + left: 'Used', + operator: '/', + reducer: 'sum', + right: 'Value #A (lastNotNull)', + }, + mode: 'binary', + reduce: { + reducer: 'sum', + }, + }, + }, + { + id: 'organize', + options: { + excludeByName: {}, + indexByName: {}, + renameByName: { + 'Value #A (lastNotNull)': 'Size', + 'Value #B (lastNotNull)': 'Available', + mountpoint: 'Mounted on', + }, + }, + }, + { + id: 'sortBy', + options: { + fields: {}, + sort: [ + { + field: 'Mounted on', + }, + ], + }, + }, + ], + }, + + + local networkReceived = + graphPanel.new( + 'Network Received', + description='Network received (bits/s)', + datasource='$datasource', + span=6, + format='bps', + min=0, + fill=0, + ) + .addTarget(prometheus.target( + 'rate(node_network_receive_bytes_total{%(nodeExporterSelector)s, instance="$instance", device!="lo"}[$__rate_interval]) * 8' % config, + legendFormat='{{device}}', + intervalFactor=1, + )), + + local networkTransmitted = + graphPanel.new( + 'Network Transmitted', + description='Network transmitted (bits/s)', + datasource='$datasource', + span=6, + format='bps', + min=0, + fill=0, + ) + .addTarget(prometheus.target( + 'rate(node_network_transmit_bytes_total{%(nodeExporterSelector)s, instance="$instance", device!="lo"}[$__rate_interval]) * 8' % config, + legendFormat='{{device}}', + intervalFactor=1, + )), + + local cpuRow = + row.new('CPU') + .addPanel(idleCPU) + .addPanel(systemLoad), + + local memoryRow = + row.new('Memory') + .addPanel(memoryGraph) + .addPanel(memoryGauge), + + local diskRow = + row.new('Disk') + .addPanel(diskIO) + .addPanel(diskSpaceUsage), + + local networkRow = + row.new('Network') + .addPanel(networkReceived) + .addPanel(networkTransmitted), + + local rows = + [ + cpuRow, + memoryRow, + diskRow, + networkRow, + ], + + local templates = + [ + prometheusDatasourceTemplate, + instanceTemplate, + ], + + + dashboard: if platform == 'Linux' then + dashboard.new( + '%sNodes' % config.dashboardNamePrefix, + time_from='now-1h', + tags=(config.dashboardTags), + timezone='utc', + refresh='30s', + graphTooltip='shared_crosshair' + ) + .addTemplates(templates) + .addRows(rows) + else if platform == 'Darwin' then + dashboard.new( + '%sMacOS' % config.dashboardNamePrefix, + time_from='now-1h', + tags=(config.dashboardTags), + timezone='utc', + refresh='30s', + graphTooltip='shared_crosshair' + ) + .addTemplates(templates) + .addRows(rows), + + }, +} diff --git a/end-to-end-test.sh b/end-to-end-test.sh index 8739e6b67f..46d52603e7 100755 --- a/end-to-end-test.sh +++ b/end-to-end-test.sh @@ -5,12 +5,16 @@ set -euf -o pipefail enabled_collectors=$(cat << COLLECTORS arp bcache + bonding btrfs buddyinfo + cgroups conntrack cpu cpufreq + cpu_vulnerabilities diskstats + dmi drbd edac entropy @@ -32,26 +36,29 @@ enabled_collectors=$(cat << COLLECTORS nfs nfsd pressure + processes qdisc rapl schedstat + selinux + slabinfo sockstat + softirqs stat - thermal_zone + sysctl textfile - bonding - udp_queues + thermal_zone + udp_queues vmstat wifi + xfrm xfs zfs - processes zoneinfo COLLECTORS ) disabled_collectors=$(cat << COLLECTORS filesystem - time timex uname COLLECTORS @@ -61,7 +68,7 @@ cd "$(dirname $0)" port="$((10000 + (RANDOM % 10000)))" tmpdir=$(mktemp -d /tmp/node_exporter_e2e_test.XXXXXX) -skip_re="^(go_|node_exporter_build_info|node_scrape_collector_duration_seconds|process_|node_textfile_mtime_seconds)" +skip_re="^(go_|node_exporter_build_info|node_scrape_collector_duration_seconds|process_|node_textfile_mtime_seconds|node_time_(zone|seconds)|node_network_(receive|transmit)_(bytes|packets)_total)" arch="$(uname -m)" @@ -70,6 +77,20 @@ case "${arch}" in *) fixture='collector/fixtures/e2e-output.txt' ;; esac +# Only test CPU info collection on x86_64. +case "${arch}" in + x86_64) + cpu_info_collector='--collector.cpu.info' + cpu_info_bugs='^(cpu_meltdown|spectre_.*|mds)$' + cpu_info_flags='^(aes|avx.?|constant_tsc)$' + ;; + *) + cpu_info_collector='--no-collector.cpu.info' + cpu_info_bugs='' + cpu_info_flags='' + ;; +esac + keep=0; update=0; verbose=0 while getopts 'hkuv' opt do @@ -104,17 +125,28 @@ fi --path.rootfs="collector/fixtures" \ --path.procfs="collector/fixtures/proc" \ --path.sysfs="collector/fixtures/sys" \ + --path.udev.data="collector/fixtures/udev/data" \ $(for c in ${enabled_collectors}; do echo --collector.${c} ; done) \ $(for c in ${disabled_collectors}; do echo --no-collector.${c} ; done) \ --collector.textfile.directory="collector/fixtures/textfile/two_metric_files/" \ --collector.wifi.fixtures="collector/fixtures/wifi" \ --collector.qdisc.fixtures="collector/fixtures/qdisc/" \ + --collector.qdisc.device-include="(wlan0|eth0)" \ + --collector.arp.device-exclude="nope" \ + --no-collector.arp.netlink \ + --collector.hwmon.chip-include="(applesmc|coretemp|hwmon4|nct6779)" \ --collector.netclass.ignored-devices="(dmz|int)" \ --collector.netclass.ignore-invalid-speed \ + --collector.netdev.device-include="lo" \ --collector.bcache.priorityStats \ - --collector.cpu.info \ - --collector.cpu.info.flags-include="^(aes|avx.?|constant_tsc)$" \ - --collector.cpu.info.bugs-include="^(cpu_meltdown|spectre_.*|mds)$" \ + "${cpu_info_collector}" \ + --collector.cpu.info.bugs-include="${cpu_info_bugs}" \ + --collector.cpu.info.flags-include="${cpu_info_flags}" \ + --collector.stat.softirq \ + --collector.sysctl.include="kernel.threads-max" \ + --collector.sysctl.include="fs.file-nr" \ + --collector.sysctl.include="fs.file-nr:total,current,max" \ + --collector.sysctl.include-info="kernel.seccomp.actions_avail" \ --web.listen-address "127.0.0.1:${port}" \ --log.level="debug" > "${tmpdir}/node_exporter.log" 2>&1 & diff --git a/examples/systemd/README.md b/examples/systemd/README.md index 67039bed13..3b3577fa0f 100644 --- a/examples/systemd/README.md +++ b/examples/systemd/README.md @@ -2,7 +2,7 @@ If you are using distribution packages or the copr repository, you don't need to deal with these files! -The unit file in this directory is to be put into `/etc/systemd/system`. +The unit files (`*.service` and `*.socket`) in this directory are to be put into `/etc/systemd/system`. It needs a user named `node_exporter`, whose shell should be `/sbin/nologin` and should not have any special privileges. It needs a sysconfig file in `/etc/sysconfig/node_exporter`. It needs a directory named `/var/lib/node_exporter/textfile_collector`, whose owner should be `node_exporter`:`node_exporter`. diff --git a/examples/systemd/node_exporter.service b/examples/systemd/node_exporter.service index 64f1405b02..82553e91ee 100644 --- a/examples/systemd/node_exporter.service +++ b/examples/systemd/node_exporter.service @@ -1,10 +1,11 @@ [Unit] Description=Node Exporter +Requires=node_exporter.socket [Service] User=node_exporter EnvironmentFile=/etc/sysconfig/node_exporter -ExecStart=/usr/sbin/node_exporter $OPTIONS +ExecStart=/usr/sbin/node_exporter --web.systemd-socket $OPTIONS [Install] WantedBy=multi-user.target diff --git a/examples/systemd/node_exporter.socket b/examples/systemd/node_exporter.socket new file mode 100644 index 0000000000..c3e5670bfb --- /dev/null +++ b/examples/systemd/node_exporter.socket @@ -0,0 +1,8 @@ +[Unit] +Description=Node Exporter + +[Socket] +ListenStream=9100 + +[Install] +WantedBy=sockets.target diff --git a/go.mod b/go.mod index d248eb5399..98ae1cf10f 100644 --- a/go.mod +++ b/go.mod @@ -1,28 +1,62 @@ module github.com/prometheus/node_exporter +go 1.20 + require ( + github.com/alecthomas/kingpin/v2 v2.4.0 github.com/beevik/ntp v0.3.0 - github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf - github.com/ema/qdisc v0.0.0-20200603082823-62d0308e3e00 - github.com/go-kit/log v0.2.0 - github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968 - github.com/hashicorp/go-envparse v0.0.0-20200406174449-d9cfd743a15e - github.com/hodgesds/perf-utils v0.3.1 + github.com/coreos/go-systemd/v22 v22.5.0 + github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1 + github.com/ema/qdisc v1.0.0 + github.com/go-kit/log v0.2.1 + github.com/godbus/dbus/v5 v5.1.0 + github.com/hashicorp/go-envparse v0.1.0 + github.com/hodgesds/perf-utils v0.7.0 github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973 - github.com/jsimonetti/rtnetlink v0.0.0-20210922080037-435639c8e6a8 - github.com/lufia/iostat v1.1.1 + github.com/josharian/native v1.1.0 + github.com/jsimonetti/rtnetlink v1.2.4 + github.com/lufia/iostat v1.2.1 github.com/mattn/go-xmlrpc v0.0.3 - github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd - github.com/prometheus/client_golang v1.11.0 - github.com/prometheus/client_model v0.2.0 - github.com/prometheus/common v0.31.1 - github.com/prometheus/exporter-toolkit v0.6.1 - github.com/prometheus/procfs v0.7.4-0.20211011103944-1a7a2bd3279f - github.com/safchain/ethtool v0.0.0-20211027131506-00502cff1260 - github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973 // indirect - github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a - golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 - gopkg.in/alecthomas/kingpin.v2 v2.2.6 + github.com/mdlayher/ethtool v0.1.0 + github.com/mdlayher/netlink v1.7.2 + github.com/mdlayher/wifi v0.1.0 + github.com/opencontainers/selinux v1.11.0 + github.com/prometheus-community/go-runit v0.1.0 + github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/client_model v0.5.0 + github.com/prometheus/common v0.45.0 + github.com/prometheus/exporter-toolkit v0.11.0 + github.com/prometheus/procfs v0.12.0 + github.com/safchain/ethtool v0.3.0 + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 + golang.org/x/sys v0.16.0 + howett.net/plist v1.0.1 ) -go 1.14 +require ( + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dennwc/ioctl v1.0.0 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + github.com/mdlayher/genetlink v1.3.2 // indirect + github.com/mdlayher/socket v0.4.1 // indirect + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973 // indirect + 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.17.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/go.sum b/go.sum index 2f82a358b6..9b0e056b6c 100644 --- a/go.sum +++ b/go.sum @@ -1,576 +1,165 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw= github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cilium/ebpf v0.9.3 h1:5KtxXZU+scyERvkJMEm16TbScVvuuMrlhPly78ZMbSc= +github.com/cilium/ebpf v0.9.3/go.mod h1:w27N4UjpaQ9X/DGrSugxUG+H+NhgntDuPb5lCzxCn8A= +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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ema/qdisc v0.0.0-20200603082823-62d0308e3e00 h1:0GHzegkDz/zSrt+Zph1OueNImPdUxoToypnkhhRYTjI= -github.com/ema/qdisc v0.0.0-20200603082823-62d0308e3e00/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1 h1:ue4Es4Xzz255hWQ7NAWzZxuXG+YOV7URzzusLLSe0zU= +github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1/go.mod h1:MYsOV9Dgsec3FFSOjywi0QK5r6TeBbdWxdrMGtiYXHA= +github.com/dennwc/ioctl v1.0.0 h1:DsWAAjIxRqNcLn9x6mwfuf2pet3iB7aK90K4tF16rLg= +github.com/dennwc/ioctl v1.0.0/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0= +github.com/ema/qdisc v1.0.0 h1:EHLG08FVRbWLg8uRICa3xzC9Zm0m7HyMHfXobWFnXYg= +github.com/ema/qdisc v1.0.0/go.mod h1:FhIc0fLYi7f+lK5maMsesDqwYojIOh3VfRs8EVd5YJQ= +github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968 h1:s+PDl6lozQ+dEUtUtQnO7+A2iPG3sK1pI4liU+jxn90= -github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/go-envparse v0.0.0-20200406174449-d9cfd743a15e h1:v1d9+AJMP6i4p8BSKNU0InuvmIAdZjQLNN19V86AG4Q= -github.com/hashicorp/go-envparse v0.0.0-20200406174449-d9cfd743a15e/go.mod h1:/NlxCzN2D4C4L2uDE6ux/h6jM+n98VFQM14nnCIfHJU= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hodgesds/perf-utils v0.3.1 h1:iizGJVzJnPW32Gvk1cFZINiGA5lVxjkZS5G0NJ6YQU0= -github.com/hodgesds/perf-utils v0.3.1/go.mod h1:oH2rI7A/UyTAlIxaP4CwSE11vDH8kGQeTBA6Oz3ltfQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdmPSDFPY= +github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= +github.com/hodgesds/perf-utils v0.7.0 h1:7KlHGMuig4FRH5fNw68PV6xLmgTe7jKs9hgAcEAbioU= +github.com/hodgesds/perf-utils v0.7.0/go.mod h1:LAklqfDadNKpkxoAJNHpD5tkY0rkZEVdnCEWN5k4QJY= github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973 h1:hk4LPqXIY/c9XzRbe7dA6qQxaT6Axcbny0L/G5a4owQ= github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973/go.mod h1:PoK3ejP3LJkGTzKqRlpvCIFas3ncU02v8zzWDW+g0FY= -github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA= -github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +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 v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= -github.com/jsimonetti/rtnetlink v0.0.0-20190830100107-3784a6c7c552/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= -github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= -github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= -github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw= -github.com/jsimonetti/rtnetlink v0.0.0-20201220180245-69540ac93943/go.mod h1:z4c53zj6Eex712ROyh8WI0ihysb5j2ROyV42iNogmAs= -github.com/jsimonetti/rtnetlink v0.0.0-20210122163228-8d122574c736/go.mod h1:ZXpIyOK59ZnN7J0BV99cZUPmsqDRZ3eq5X+st7u/oSA= -github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9Rh8m+aHZIG69YPGGem1i5VzoyRC8nw2kA8B+ik5U= -github.com/jsimonetti/rtnetlink v0.0.0-20210525051524-4cc836578190/go.mod h1:NmKSdU4VGSiv1bMsdqNALI4RSvvjtz65tTMCnD05qLo= -github.com/jsimonetti/rtnetlink v0.0.0-20210922080037-435639c8e6a8 h1:URWZhDC6GjaHuI7uYYBaDeT52G0rR3HFqxnzvS0e4OU= -github.com/jsimonetti/rtnetlink v0.0.0-20210922080037-435639c8e6a8/go.mod h1:qdKhcKUxYn3/QvneOvPWXXMPqktEBHnCW98wUTA3rmA= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/jsimonetti/rtnetlink v1.2.4 h1:u0lAnId+dzUOYI7wmHows+Mx+sDpdGOfDQhUBBCkb+g= +github.com/jsimonetti/rtnetlink v1.2.4/go.mod h1:5r5Rj9WEseVOUzDk5RN9v0gVXbkBz9XtENwhC6PwvtU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lufia/iostat v1.1.1 h1:DloZH7Py1k/m43Ii+j1VNQ1QWcFnahBIOp0atIUXCNg= -github.com/lufia/iostat v1.1.1/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +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/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY= -github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo= -github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0= -github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= -github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= -github.com/mdlayher/netlink v0.0.0-20190828143259-340058475d09/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= -github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= -github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= -github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= -github.com/mdlayher/netlink v1.2.0/go.mod h1:kwVW1io0AZy9A1E2YYgaD4Cj+C+GPkU6klXCMzIJ9p8= -github.com/mdlayher/netlink v1.2.1/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= -github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= -github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys= -github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= -github.com/mdlayher/netlink v1.4.1 h1:I154BCU+mKlIf7BgcAJB2r7QjveNPty6uNY1g9ChVfI= -github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= -github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00 h1:qEtkL8n1DAHpi5/AOgAckwGQUlMe4+jhL/GMt+GKIks= -github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= -github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd h1:50p1vPNK43pzCVX10+5MmiOerbBzC1vR6+sLB3FZewE= -github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd/go.mod h1:Evt/EIne46u9PtQbeTx2NTcqURpr5K4SvKtGmBuDPN8= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mdlayher/ethtool v0.1.0 h1:XAWHsmKhyPOo42qq/yTPb0eFBGUKKTR1rE0dVrWVQ0Y= +github.com/mdlayher/ethtool v0.1.0/go.mod h1:fBMLn2UhfRGtcH5ZFjr+6GUiHEjZsItFD7fSn7jbZVQ= +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.6.2/go.mod h1:O1HXX2sIWSMJ3Qn1BYZk1yZM+7iMki/uYGGiwGyq/iU= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= +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/wifi v0.1.0 h1:y8wYRUXwok5CtUZOXT3egghYesX0O79E3ALl+SIDm9Q= +github.com/mdlayher/wifi v0.1.0/go.mod h1:+gBYnZAMcUKHSFzMJXwlz7tLsEHgwDJ9DJCefhJM+gI= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= +github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.31.1 h1:d18hG4PkHnNAKNMOmFuXFaiY8Us0nird/2m60uS1AMs= -github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/exporter-toolkit v0.6.1 h1:Aqk75wQD92N9CqmTlZwjKwq6272nOGrWIbc8Z7+xQO0= -github.com/prometheus/exporter-toolkit v0.6.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.4-0.20211011103944-1a7a2bd3279f h1:ncXqc93eJV1Ncr3f6GA3MrIDNkNHvcPonRC2QgZaVkQ= -github.com/prometheus/procfs v0.7.4-0.20211011103944-1a7a2bd3279f/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/safchain/ethtool v0.0.0-20211027131506-00502cff1260 h1:okHnQYsz4hBxXvOi1x4dhnHgcL8JMCyyBPrsIfJBE58= -github.com/safchain/ethtool v0.0.0-20211027131506-00502cff1260/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ= +github.com/prometheus-community/go-runit v0.1.0 h1:uTWEj/Fn2RoLdfg/etSqwzgYNOYPrARx1BHUN052tGA= +github.com/prometheus-community/go-runit v0.1.0/go.mod h1:AvJ9Jo3gAFu2lbM4+qfjdpq30FfiLDJZKbQ015u08IQ= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= +github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0= +github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs= 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/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a h1:os5OBNhwOwybXZMNLqT96XqtjdTtwRFw2w08uluvNeI= -github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a/go.mod h1:LeFCbQYJ3KJlPs/FvPz2dy1tkpxyeNESVyCNNzRXFR0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= 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.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219203350-90b0e4468f99/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM= +howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= diff --git a/node_exporter.go b/node_exporter.go index 9a0e3d09f1..cc24f7dfba 100644 --- a/node_exporter.go +++ b/node_exporter.go @@ -20,11 +20,13 @@ import ( _ "net/http/pprof" "os" "os/user" + "runtime" "sort" "github.com/prometheus/common/promlog" "github.com/prometheus/common/promlog/flag" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" @@ -32,8 +34,8 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" + "github.com/prometheus/exporter-toolkit/web/kingpinflag" "github.com/prometheus/node_exporter/collector" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) // handler wraps an unfiltered http.Handler but uses a filtered handler, @@ -121,31 +123,39 @@ func (h *handler) innerHandler(filters ...string) (http.Handler, error) { if err := r.Register(nc); err != nil { return nil, fmt.Errorf("couldn't register node collector: %s", err) } - handler := promhttp.HandlerFor( - prometheus.Gatherers{h.exporterMetricsRegistry, r}, - promhttp.HandlerOpts{ - ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(h.logger)), "", 0), - ErrorHandling: promhttp.ContinueOnError, - MaxRequestsInFlight: h.maxRequests, - Registry: h.exporterMetricsRegistry, - }, - ) + + var handler http.Handler if h.includeExporterMetrics { + handler = promhttp.HandlerFor( + prometheus.Gatherers{h.exporterMetricsRegistry, r}, + promhttp.HandlerOpts{ + ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(h.logger)), "", 0), + ErrorHandling: promhttp.ContinueOnError, + MaxRequestsInFlight: h.maxRequests, + Registry: h.exporterMetricsRegistry, + }, + ) // Note that we have to use h.exporterMetricsRegistry here to // use the same promhttp metrics for all expositions. handler = promhttp.InstrumentMetricHandler( h.exporterMetricsRegistry, handler, ) + } else { + handler = promhttp.HandlerFor( + r, + promhttp.HandlerOpts{ + ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(h.logger)), "", 0), + ErrorHandling: promhttp.ContinueOnError, + MaxRequestsInFlight: h.maxRequests, + }, + ) } + return handler, nil } func main() { var ( - listenAddress = kingpin.Flag( - "web.listen-address", - "Address on which to expose metrics and web interface.", - ).Default(":9100").String() metricsPath = kingpin.Flag( "web.telemetry-path", "Path under which to expose metrics.", @@ -162,10 +172,10 @@ func main() { "collector.disable-defaults", "Set all collectors to disabled by default.", ).Default("false").Bool() - configFile = kingpin.Flag( - "web.config", - "[EXPERIMENTAL] Path to config yaml file that can enable TLS or authentication.", - ).Default("").String() + maxProcs = kingpin.Flag( + "runtime.gomaxprocs", "The target number of CPUs Go will run on (GOMAXPROCS)", + ).Envar("GOMAXPROCS").Default("1").Int() + toolkitFlags = kingpinflag.AddFlags(kingpin.CommandLine, ":9100") ) promlogConfig := &promlog.Config{} @@ -182,23 +192,34 @@ func main() { level.Info(logger).Log("msg", "Starting node_exporter", "version", version.Info()) level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext()) if user, err := user.Current(); err == nil && user.Uid == "0" { - level.Warn(logger).Log("msg", "Node Exporter is running as root user. This exporter is designed to run as unpriviledged user, root is not required.") + level.Warn(logger).Log("msg", "Node Exporter is running as root user. This exporter is designed to run as unprivileged user, root is not required.") } + runtime.GOMAXPROCS(*maxProcs) + level.Debug(logger).Log("msg", "Go MAXPROCS", "procs", runtime.GOMAXPROCS(0)) http.Handle(*metricsPath, newHandler(!*disableExporterMetrics, *maxRequests, logger)) - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(` - Node Exporter - -

Node Exporter

-

Metrics

- - `)) - }) - - level.Info(logger).Log("msg", "Listening on", "address", *listenAddress) - server := &http.Server{Addr: *listenAddress} - if err := web.ListenAndServe(server, *configFile, logger); err != nil { + if *metricsPath != "/" { + landingConfig := web.LandingConfig{ + Name: "Node Exporter", + Description: "Prometheus Node Exporter", + Version: version.Info(), + Links: []web.LandingLinks{ + { + Address: *metricsPath, + Text: "Metrics", + }, + }, + } + landingPage, err := web.NewLandingPage(landingConfig) + if err != nil { + level.Error(logger).Log("err", err) + os.Exit(1) + } + http.Handle("/", landingPage) + } + + server := &http.Server{} + if err := web.ListenAndServe(server, toolkitFlags, logger); err != nil { level.Error(logger).Log("err", err) os.Exit(1) } diff --git a/node_exporter_test.go b/node_exporter_test.go index f10db7c661..6fbbc7ee22 100644 --- a/node_exporter_test.go +++ b/node_exporter_test.go @@ -15,7 +15,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "net/http" "os" "os/exec" @@ -84,17 +84,17 @@ func TestHandlingOfDuplicatedMetrics(t *testing.T) { t.Skipf("node_exporter binary not available, try to run `make build` first: %s", err) } - dir, err := ioutil.TempDir("", "node-exporter") + dir, err := os.MkdirTemp("", "node-exporter") if err != nil { t.Fatal(err) } defer os.RemoveAll(dir) content := []byte("dummy_metric 1\n") - if err := ioutil.WriteFile(filepath.Join(dir, "a.prom"), content, 0600); err != nil { + if err := os.WriteFile(filepath.Join(dir, "a.prom"), content, 0600); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(dir, "b.prom"), content, 0600); err != nil { + if err := os.WriteFile(filepath.Join(dir, "b.prom"), content, 0600); err != nil { t.Fatal(err) } @@ -113,7 +113,7 @@ func queryExporter(address string) error { if err != nil { return err } - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) if err != nil { return err } diff --git a/scripts/errcheck_excludes.txt b/scripts/errcheck_excludes.txt deleted file mode 100644 index 14b824f85f..0000000000 --- a/scripts/errcheck_excludes.txt +++ /dev/null @@ -1,4 +0,0 @@ -// Used in HTTP handlers, any error is handled by the server itself. -(net/http.ResponseWriter).Write -// Never check for logger errors. -(github.com/go-kit/log.Logger).Log