diff --git a/.circleci/config.yml b/.circleci/config.yml index d6e6b870ef..ab00b232d0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,10 +7,10 @@ executors: # should also be updated. golang: docker: - - image: cimg/go:1.20 + - image: cimg/go:1.21 arm: machine: - image: ubuntu-2004:current + image: ubuntu-2204:current resource_class: arm.medium jobs: @@ -42,7 +42,7 @@ jobs: - run: git diff --exit-code build: machine: - image: ubuntu-2004:202101-01 + image: ubuntu-2204:current parallelism: 3 steps: - prometheus/setup_environment @@ -58,7 +58,7 @@ jobs: destination: /build test_docker: machine: - image: ubuntu-2204:2022.04.2 + image: ubuntu-2204:current environment: DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.18-base REPO_PATH: github.com/prometheus/node_exporter diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 433f71b885..8ace97bde1 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -18,15 +18,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: go-version: 1.20.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@v3.4.0 + uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 with: - version: v1.53.3 + version: v1.54.2 diff --git a/.promu-cgo.yml b/.promu-cgo.yml index 975c6e3246..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.20 + version: 1.21 cgo: true repository: path: github.com/prometheus/node_exporter diff --git a/.promu.yml b/.promu.yml index f37f8502be..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.20 + version: 1.21 repository: path: github.com/prometheus/node_exporter build: diff --git a/Makefile.common b/Makefile.common index 0ce7ea4612..062a281856 100644 --- a/Makefile.common +++ b/Makefile.common @@ -61,7 +61,7 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_ SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.53.3 +GOLANGCI_LINT_VERSION ?= v1.54.2 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) diff --git a/README.md b/README.md index 0a0fbdfdc0..737519207d 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ buddyinfo | Exposes statistics of memory fragments as reported by /proc/buddyinf 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 diff --git a/collector/arp_linux.go b/collector/arp_linux.go index 8f42d380e8..e9d5e9da8f 100644 --- a/collector/arp_linux.go +++ b/collector/arp_linux.go @@ -17,11 +17,15 @@ package collector import ( + "errors" "fmt" + "net" "github.com/go-kit/log" + "github.com/jsimonetti/rtnetlink" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/procfs" + "golang.org/x/sys/unix" ) type arpCollector struct { @@ -29,6 +33,7 @@ type arpCollector struct { deviceFilter deviceFilter entries *prometheus.Desc logger log.Logger + config NodeCollectorConfig } func init() { @@ -38,6 +43,7 @@ func init() { type ArpConfig struct { DeviceInclude *string DeviceExclude *string + Netlink *bool } // NewARPCollector returns a new Collector exposing ARP stats. @@ -69,13 +75,65 @@ func getTotalArpEntries(deviceEntries []procfs.ARPEntry) map[string]uint32 { return entries } -func (c *arpCollector) Update(ch chan<- prometheus.Metric) error { - entries, err := c.fs.GatherARPEntries() +func getTotalArpEntriesRTNL() (map[string]uint32, error) { + conn, err := rtnetlink.Dial(nil) + if err != nil { + return nil, err + } + defer conn.Close() + + neighbors, err := conn.Neigh.List() if err != nil { - return fmt.Errorf("could not get ARP entries: %w", err) + return nil, err + } + + ifIndexEntries := make(map[uint32]uint32) + + 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]++ + } + } + + 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 + } + + enumEntries[iface.Name] = entryCount } - enumeratedEntry := getTotalArpEntries(entries) + return enumEntries, nil +} + +func (c *arpCollector) Update(ch chan<- prometheus.Metric) error { + var enumeratedEntry map[string]uint32 + + if *c.config.Arp.Netlink { + 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 enumeratedEntry { if c.deviceFilter.ignored(device) { 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_solaris.go b/collector/boot_time_solaris.go index 6782cd72a7..0dfc671bc8 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 cebf5b3029..faff82bedf 100644 --- a/collector/btrfs_linux.go +++ b/collector/btrfs_linux.go @@ -137,6 +137,7 @@ func (c *btrfsCollector) getIoctlStats() (map[string]*btrfsIoctlFsStats, error) "err", err) continue } + defer fs.Close() fsInfo, err := fs.Info() if err != nil { diff --git a/collector/cpu_linux.go b/collector/cpu_linux.go index f22f6876bb..12889fd347 100644 --- a/collector/cpu_linux.go +++ b/collector/cpu_linux.go @@ -37,6 +37,7 @@ type cpuCollector struct { fs procfs.FS cpu *prometheus.Desc cpuInfo *prometheus.Desc + cpuFrequencyHz *prometheus.Desc cpuFlagsInfo *prometheus.Desc cpuBugsInfo *prometheus.Desc cpuGuest *prometheus.Desc @@ -100,6 +101,11 @@ func NewCPUCollector(config NodeCollectorConfig, logger log.Logger) (Collector, "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.", @@ -202,6 +208,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("cpufreq key missing or nil value in collectorState map", err) + } 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 { diff --git a/collector/cpu_solaris.go b/collector/cpu_solaris.go index 702ba3f835..40a0ec0637 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/cpufreq_solaris.go b/collector/cpufreq_solaris.go index 50e2a9f9b9..481a6a80de 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 diff --git a/collector/diskstats_linux_test.go b/collector/diskstats_linux_test.go index bae0e7b70f..d1ae0c3f91 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 ( diff --git a/collector/diskstats_openbsd.go b/collector/diskstats_openbsd.go index 90814a007a..47bc8e0f31 100644 --- a/collector/diskstats_openbsd.go +++ b/collector/diskstats_openbsd.go @@ -11,8 +11,8 @@ // 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 diff --git a/collector/ethtool_linux_test.go b/collector/ethtool_linux_test.go index 035adbb55f..ecd0ba049c 100644 --- a/collector/ethtool_linux_test.go +++ b/collector/ethtool_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !noethtool +// +build !noethtool + package collector import ( diff --git a/collector/exec_bsd.go b/collector/exec_bsd.go index 06e31865b6..de2cf76197 100644 --- a/collector/exec_bsd.go +++ b/collector/exec_bsd.go @@ -49,31 +49,37 @@ func NewExecCollector(config NodeCollectorConfig, logger log.Logger) (Collector, name: "exec_context_switches_total", description: "Context switches since system boot. Resets at architecture unsigned integer.", mib: "vm.stats.sys.v_swtch", + labels: nil, }, { name: "exec_traps_total", description: "Traps since system boot. Resets at architecture unsigned integer.", mib: "vm.stats.sys.v_trap", + labels: nil, }, { name: "exec_system_calls_total", description: "System calls since system boot. Resets at architecture unsigned integer.", mib: "vm.stats.sys.v_syscall", }, + labels: nil, { name: "exec_device_interrupts_total", description: "Device interrupts since system boot. Resets at architecture unsigned integer.", mib: "vm.stats.sys.v_intr", + labels: nil, }, { name: "exec_software_interrupts_total", description: "Software interrupts since system boot. Resets at architecture unsigned integer.", mib: "vm.stats.sys.v_soft", + labels: nil, }, { name: "exec_forks_total", description: "Number of fork() calls since system boot. Resets at architecture unsigned integer.", mib: "vm.stats.vm.v_forks", + labels: nil, }, }, logger: logger, diff --git a/collector/fibrechannel_linux.go b/collector/fibrechannel_linux.go index 2e50ee3669..26426e7c2e 100644 --- a/collector/fibrechannel_linux.go +++ b/collector/fibrechannel_linux.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build linux && !nofibrechannel -// +build linux,!nofibrechannel +//go:build !nofibrechannel +// +build !nofibrechannel package collector diff --git a/collector/filefd_linux_test.go b/collector/filefd_linux_test.go index 37e16a4e09..f31a5c2c5e 100644 --- a/collector/filefd_linux_test.go +++ b/collector/filefd_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nofilefd +// +build !nofilefd + package collector import "testing" diff --git a/collector/filesystem_common.go b/collector/filesystem_common.go index b97d4b82f3..8d7d9c7dfa 100644 --- a/collector/filesystem_common.go +++ b/collector/filesystem_common.go @@ -181,6 +181,11 @@ func (c *filesystemCollector) Update(ch chan<- prometheus.Metric) error { c.deviceErrorDesc, prometheus.GaugeValue, s.deviceError, 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, + ) + if s.deviceError > 0 { continue } @@ -205,10 +210,6 @@ func (c *filesystemCollector) Update(ch chan<- prometheus.Metric) error { 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, - ) } return nil } diff --git a/collector/filesystem_linux.go b/collector/filesystem_linux.go index c6a924c84f..11a12b4178 100644 --- a/collector/filesystem_linux.go +++ b/collector/filesystem_linux.go @@ -102,6 +102,14 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) { } func (c *filesystemCollector) processStat(labels filesystemLabels) filesystemStats { + var ro float64 + for _, option := range strings.Split(labels.options, ",") { + if option == "ro" { + ro = 1 + break + } + } + success := make(chan struct{}) go stuckMountWatcher(c.config.Filesystem.MountTimeout, labels.mountPoint, success, c.logger) @@ -122,16 +130,10 @@ func (c *filesystemCollector) processStat(labels filesystemLabels) filesystemSta return filesystemStats{ labels: labels, deviceError: 1, + ro: ro, } } - var ro float64 - for _, option := range strings.Split(labels.options, ",") { - if option == "ro" { - ro = 1 - break - } - } return filesystemStats{ labels: labels, size: float64(buf.Blocks) * float64(buf.Bsize), diff --git a/collector/filesystem_linux_test.go b/collector/filesystem_linux_test.go index 07544dfc5c..8ce7650e3d 100644 --- a/collector/filesystem_linux_test.go +++ b/collector/filesystem_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nofilesystem +// +build !nofilesystem + package collector import ( diff --git a/collector/filesystem_openbsd.go b/collector/filesystem_openbsd.go index 16cd610dfd..1c1e479e1f 100644 --- a/collector/filesystem_openbsd.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 diff --git a/collector/infiniband_linux.go b/collector/infiniband_linux.go index 3fe28ab012..29f8804a41 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_test.go b/collector/interrupts_linux_test.go index 018983689f..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 ( 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_test.go b/collector/ipvs_linux_test.go index abb69c61f4..62fab68138 100644 --- a/collector/ipvs_linux_test.go +++ b/collector/ipvs_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !noipvs +// +build !noipvs + package collector import ( diff --git a/collector/loadavg_linux_test.go b/collector/loadavg_linux_test.go index d8e56fcebd..707fab62d4 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_test.go b/collector/logind_linux_test.go index e8d9cb02f1..5cfedff4db 100644 --- a/collector/logind_linux_test.go +++ b/collector/logind_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nologind +// +build !nologind + package collector import ( 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 index 7f4184799d..a1bd118523 100644 --- a/collector/meminfo_netbsd.go +++ b/collector/meminfo_netbsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build netbsd && !nomeminfo -// +build netbsd,!nomeminfo +//go:build !nomeminfo +// +build !nomeminfo package collector 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 6189a14106..67f3cb0064 100644 --- a/collector/memory_bsd.go +++ b/collector/memory_bsd.go @@ -69,18 +69,21 @@ func NewMemoryCollector(config NodeCollectorConfig, logger log.Logger) (Collecto description: "Recently used by userland", mib: "vm.stats.vm.v_active_count", conversion: fromPage, + labels: nil, }, { name: "inactive_bytes", description: "Not recently used by userland", mib: "vm.stats.vm.v_inactive_count", conversion: fromPage, + labels: nil, }, { name: "wired_bytes", description: "Locked in memory by kernel, mlock, etc", mib: "vm.stats.vm.v_wire_count", conversion: fromPage, + labels: nil, }, { name: "user_wired_bytes", @@ -88,42 +91,49 @@ func NewMemoryCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "vm.stats.vm.v_user_wire_count", conversion: fromPage, dataType: bsdSysctlTypeCLong, + labels: nil, }, { name: "cache_bytes", description: "Almost free, backed by swap or files, available for re-allocation", mib: "vm.stats.vm.v_cache_count", conversion: fromPage, + labels: nil, }, { name: "buffer_bytes", description: "Disk IO Cache entries for non ZFS filesystems, only usable by kernel", mib: "vfs.bufspace", dataType: bsdSysctlTypeCLong, + labels: nil, }, { name: "free_bytes", description: "Unallocated, available for allocation", mib: "vm.stats.vm.v_free_count", conversion: fromPage, + labels: nil, }, { name: "laundry_bytes", description: "Dirty not recently used by userland", mib: "vm.stats.vm.v_laundry_count", conversion: fromPage, + labels: nil, }, { name: "size_bytes", description: "Total physical memory size", mib: "vm.stats.vm.v_page_count", conversion: fromPage, + labels: nil, }, { name: "swap_size_bytes", description: "Total swap memory size", mib: mibSwapTotal, dataType: bsdSysctlTypeUint64, + labels: nil, }, // Descriptions via: top(1) { @@ -132,6 +142,7 @@ func NewMemoryCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "vm.stats.vm.v_swappgsin", valueType: prometheus.CounterValue, conversion: fromPage, + labels: nil, }, { name: "swap_out_bytes_total", @@ -139,6 +150,7 @@ func NewMemoryCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "vm.stats.vm.v_swappgsout", valueType: prometheus.CounterValue, conversion: fromPage, + labels: nil, }, }, }, nil diff --git a/collector/netdev_linux.go b/collector/netdev_linux.go index 1b9e91666f..afefd2bbb3 100644 --- a/collector/netdev_linux.go +++ b/collector/netdev_linux.go @@ -51,14 +51,53 @@ func parseNetlinkStats(links []rtnetlink.LinkMessage, filter *deviceFilter, logg metrics := netDevStats{} 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, + } + } if filter.ignored(name) { level.Debug(logger).Log("msg", "Ignoring device", "device", name) continue } + // Make sure we don't panic when accessing `stats` attributes below. + if stats == nil { + level.Debug(logger).Log("msg", "No netlink stats, skipping") + continue + } + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h#L42-L246 metrics[name] = map[string]uint64{ "receive_packets": stats.RXPackets, diff --git a/collector/netdev_linux_test.go b/collector/netdev_linux_test.go index ff5e1c22bf..7909d01821 100644 --- a/collector/netdev_linux_test.go +++ b/collector/netdev_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nonetdev +// +build !nonetdev + package collector import ( diff --git a/collector/netdev_openbsd.go b/collector/netdev_openbsd.go index 5d53678d9b..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 diff --git a/collector/netisr_freebsd.go b/collector/netisr_freebsd.go index d8e5dd35b1..4955728634 100644 --- a/collector/netisr_freebsd.go +++ b/collector/netisr_freebsd.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build freebsd && !nonetisr -// +build freebsd,!nonetisr +//go:build !nonetisr +// +build !nonetisr package collector @@ -45,6 +45,7 @@ func NewNetisrCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "net.isr.numthreads", dataType: bsdSysctlTypeUint32, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "maxprot", @@ -52,6 +53,7 @@ func NewNetisrCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "net.isr.maxprot", dataType: bsdSysctlTypeUint32, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "defaultqlimit", @@ -59,6 +61,7 @@ func NewNetisrCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "net.isr.defaultqlimit", dataType: bsdSysctlTypeUint32, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "maxqlimit", @@ -66,6 +69,7 @@ func NewNetisrCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "net.isr.maxqlimit", dataType: bsdSysctlTypeUint32, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "bindthreads", @@ -73,6 +77,7 @@ func NewNetisrCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "net.isr.bindthreads", dataType: bsdSysctlTypeUint32, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "maxthreads", @@ -80,6 +85,7 @@ func NewNetisrCollector(config NodeCollectorConfig, logger log.Logger) (Collecto mib: "net.isr.maxthreads", dataType: bsdSysctlTypeUint32, valueType: prometheus.GaugeValue, + labels: nil, }, }, logger: logger, 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/nvme_linux.go b/collector/nvme_linux.go index 506f1d04bb..bb528a0ecd 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/perf_linux_test.go b/collector/perf_linux_test.go index 141b6bf51c..e771ef9582 100644 --- a/collector/perf_linux_test.go +++ b/collector/perf_linux_test.go @@ -11,8 +11,8 @@ // 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 @@ -24,7 +24,6 @@ import ( "testing" "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" ) diff --git a/collector/qdisc_linux.go b/collector/qdisc_linux.go index d3f55b37fe..4e742a47ec 100644 --- a/collector/qdisc_linux.go +++ b/collector/qdisc_linux.go @@ -24,6 +24,7 @@ import ( "github.com/ema/qdisc" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" ) @@ -45,15 +46,35 @@ func init() { } type QdiscConfig struct { - Fixtures *string - DeviceInclude *string - DeviceExclude *string + Fixtures *string + DeviceInclude *string + OldDeviceInclude *string + DeviceExclude *string + OldDeviceExclude *string } // NewQdiscStatCollector returns a new Collector exposing queuing discipline statistics. func NewQdiscStatCollector(config NodeCollectorConfig, logger log.Logger) (Collector, error) { - if *config.Qdisc.DeviceExclude != "" && *config.Qdisc.DeviceInclude != "" { - return nil, fmt.Errorf("collector.qdisk.device-include and collector.qdisk.device-exclude are mutaly exclusive") + if *config.Qdisc.OldDeviceInclude != "" { + if *config.Qdisc.DeviceInclude == "" { + level.Warn(logger).Log("msg", "--collector.qdisk.device-include is DEPRECATED and will be removed in 2.0.0, use --collector.qdisc.device-include") + *config.Qdisc.DeviceInclude = *config.Qdisc.OldDeviceInclude + } else { + return nil, fmt.Errorf("--collector.qdisk.device-include and --collector.qdisc.device-include are mutually exclusive") + } + } + + if *config.Qdisc.OldDeviceExclude != "" { + if *config.Qdisc.DeviceExclude == "" { + level.Warn(logger).Log("msg", "--collector.qdisk.device-exclude is DEPRECATED and will be removed in 2.0.0, use --collector.qdisc.device-exclude") + *config.Qdisc.DeviceExclude = *config.Qdisc.OldDeviceExclude + } else { + return nil, fmt.Errorf("--collector.qdisk.device-exclude and --collector.qdisc.device-exclude are mutually exclusive") + } + } + + if *config.Qdisc.DeviceInclude != "" && *config.Qdisc.DeviceExclude != "" { + return nil, fmt.Errorf("collector.qdisc.device-include and collector.qdisc.device-exclude are mutaly exclusive") } return &qdiscStatCollector{ @@ -93,7 +114,7 @@ func NewQdiscStatCollector(config NodeCollectorConfig, logger log.Logger) (Colle []string{"device", "kind"}, nil, ), prometheus.GaugeValue}, logger: logger, - deviceFilter: newDeviceFilter(*config.Qdisc.DeviceExclude, *config.Qdisc.DeviceExclude), + deviceFilter: newDeviceFilter(*config.Qdisc.OldDeviceExclude, *config.Qdisc.DeviceInclude), config: config, }, nil } diff --git a/collector/selinux_linux.go b/collector/selinux_linux.go index fd00da5641..b5f5317fcd 100644 --- a/collector/selinux_linux.go +++ b/collector/selinux_linux.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build linux && !noselinux -// +build linux,!noselinux +//go:build !noselinux +// +build !noselinux package collector diff --git a/collector/slabinfo_linux.go b/collector/slabinfo_linux.go index 4e07038f7d..254337209d 100644 --- a/collector/slabinfo_linux.go +++ b/collector/slabinfo_linux.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build linux && !noslabinfo -// +build linux,!noslabinfo +//go:build !noslabinfo +// +build !noslabinfo package collector diff --git a/collector/sysctl_bsd.go b/collector/sysctl_bsd.go index 2ab248ed2e..df5c9f93f1 100644 --- a/collector/sysctl_bsd.go +++ b/collector/sysctl_bsd.go @@ -59,6 +59,9 @@ type bsdSysctl struct { // Post-retrieval conversion hooks conversion func(float64) float64 + + // Prometheus labels + labels prometheus.Labels } func (b bsdSysctl) Value() (float64, error) { diff --git a/collector/systemd_linux_test.go b/collector/systemd_linux_test.go index bfd733a7c0..2844eb7b2c 100644 --- a/collector/systemd_linux_test.go +++ b/collector/systemd_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !nosystemd +// +build !nosystemd + package collector import ( diff --git a/collector/tcpstat_linux_test.go b/collector/tcpstat_linux_test.go index 693f04fec5..e1bd090a79 100644 --- a/collector/tcpstat_linux_test.go +++ b/collector/tcpstat_linux_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !notcpstat +// +build !notcpstat + package collector import ( diff --git a/collector/textfile_test.go b/collector/textfile_test.go index d759dfaf95..95e5966f3e 100644 --- a/collector/textfile_test.go +++ b/collector/textfile_test.go @@ -11,6 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !notextfile +// +build !notextfile + package collector import ( diff --git a/collector/time_linux.go b/collector/time_linux.go index f3c502c114..760cf8fd5a 100644 --- a/collector/time_linux.go +++ b/collector/time_linux.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build linux && !notime -// +build linux,!notime +//go:build !notime +// +build !notime package collector diff --git a/collector/zfs_freebsd.go b/collector/zfs_freebsd.go index 3b07022529..22267d3b33 100644 --- a/collector/zfs_freebsd.go +++ b/collector/zfs_freebsd.go @@ -20,7 +20,10 @@ import ( "fmt" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" + + "golang.org/x/sys/unix" ) type zfsCollector struct { @@ -45,6 +48,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.abdstats.linear_cnt", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "abdstats_linear_data_bytes", @@ -52,6 +56,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.abdstats.linear_data_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "abdstats_scatter_chunk_waste_bytes", @@ -59,6 +64,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.abdstats.scatter_chunk_waste", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "abdstats_scatter_count_total", @@ -66,6 +72,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.abdstats.scatter_cnt", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "abdstats_scatter_data_bytes", @@ -73,6 +80,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.abdstats.scatter_data_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "abdstats_struct_bytes", @@ -80,6 +88,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.abdstats.struct_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_anon_bytes", @@ -87,6 +96,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.anon_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_c_bytes", @@ -94,6 +104,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.c", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_c_max_bytes", @@ -101,6 +112,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.c_max", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_c_min_bytes", @@ -108,6 +120,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.c_min", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_data_bytes", @@ -115,6 +128,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.data_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_demand_data_hits_total", @@ -122,6 +136,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.demand_data_hits", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_demand_data_misses_total", @@ -129,6 +144,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.demand_data_misses", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_demand_metadata_hits_total", @@ -136,6 +152,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.demand_metadata_hits", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_demand_metadata_misses_total", @@ -143,6 +160,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.demand_metadata_misses", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_hdr_bytes", @@ -150,6 +168,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.hdr_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_hits_total", @@ -157,6 +176,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.hits", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_misses_total", @@ -164,6 +184,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.misses", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_mfu_ghost_hits_total", @@ -171,6 +192,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.mfu_ghost_hits", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_mfu_ghost_size", @@ -178,6 +200,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.mfu_ghost_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_mfu_bytes", @@ -185,6 +208,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.mfu_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_mru_ghost_hits_total", @@ -192,6 +216,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.mru_ghost_hits", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "arcstats_mru_ghost_bytes", @@ -199,6 +224,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.mru_ghost_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_mru_bytes", @@ -206,6 +232,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.mru_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "arcstats_other_bytes", @@ -213,13 +240,37 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.other_size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, + // when FreeBSD 14.0+, `meta/pm/pd` install of `p`. { name: "arcstats_p_bytes", description: "ZFS ARC MRU target size", mib: "kstat.zfs.misc.arcstats.p", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, + }, + { + 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", @@ -227,6 +278,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.arcstats.size", dataType: bsdSysctlTypeUint64, valueType: prometheus.GaugeValue, + labels: nil, }, { name: "zfetchstats_hits_total", @@ -234,6 +286,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.zfetchstats.hits", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, { name: "zfetchstats_misses_total", @@ -241,6 +294,7 @@ func NewZfsCollector(config NodeCollectorConfig, logger log.Logger) (Collector, mib: "kstat.zfs.misc.zfetchstats.misses", dataType: bsdSysctlTypeUint64, valueType: prometheus.CounterValue, + labels: nil, }, }, logger: logger, @@ -251,7 +305,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( @@ -264,3 +320,42 @@ func (c *zfsCollector) Update(ch chan<- prometheus.Metric) error { return nil } + +func (c *zfsCollector) parseFreeBSDPoolObjsetStats() error { + + sysCtlMetrics := []string{ + "nunlinked", "nunlinks", "nread", "reads", "nwritten", "writes", + } + zfsPoolMibPrefix := "kstat.zfs.pool.dataset" + zfsDatasetsNames := []string{} + + zfsDatasets, err := unix.Sysctl(zfsPoolMibPrefix) + if err != nil { + return fmt.Errorf("couldn't get sysctl: %w", err) + } + + for dataset, _ := range zfsDatasets { + if strings.HasSuffix(dataset, ".dataset_name") { + zfsDatasetNames = append(zfsDatasetNames, strings.SplitAfter(dataset, ".")[3]) + } + } + + for zpoolDataset := range zfsDatasetsNames { + zfsDatasetLabels := map[string]string{ + "dataset": zpoolDataset, + "zpool": strings.SplitAfter(zpoolDataset, "/")[0], + } + for metric := range sysCtlMetrics { + c.sysctls = append(c.sysctls, bsdSysctl{ + name: fmt.SprintF("node_zfs_zpool_dataset_%s", metric), + description: fmt.SprintF("node_zfs_zpool_dataset_%s", metric), + mib: fmt.Sprintf("%s.%s.%s", zfsPoolMibPrefix, poolObj, metric), + dataType: bsdSysctlTypeUint64, + valueType: prometheus.CounterValue, + labels: zfsDatasetLabels, + }) + } + } + + return nil +} diff --git a/collector/zfs_linux.go b/collector/zfs_linux.go index a7348a56be..464ea2f131 100644 --- a/collector/zfs_linux.go +++ b/collector/zfs_linux.go @@ -104,7 +104,7 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error { return errZFSNotAvailable } - err = c.parsePoolObjsetFile(file, zpoolPath, func(poolName string, datasetName string, s zfsSysctl, v uint64) { + err = c.parseLinuxPoolObjsetFile(file, zpoolPath, func(poolName string, datasetName string, s zfsSysctl, v uint64) { ch <- c.constPoolObjsetMetric(poolName, datasetName, s, v) }) file.Close() @@ -220,7 +220,7 @@ func (c *zfsCollector) parsePoolProcfsFile(reader io.Reader, zpoolPath string, h return scanner.Err() } -func (c *zfsCollector) parsePoolObjsetFile(reader io.Reader, zpoolPath string, handler func(string, string, zfsSysctl, uint64)) error { +func (c *zfsCollector) parseLinuxPoolObjsetFile(reader io.Reader, zpoolPath string, handler func(string, string, zfsSysctl, uint64)) error { scanner := bufio.NewScanner(reader) parseLine := false diff --git a/collector/zfs_linux_test.go b/collector/zfs_linux_test.go index 69e4ed8fc1..f6ce8d9487 100644 --- a/collector/zfs_linux_test.go +++ b/collector/zfs_linux_test.go @@ -332,7 +332,7 @@ func TestZpoolObjsetParsing(t *testing.T) { t.Fatal(err) } - err = c.parsePoolObjsetFile(file, zpoolPath, func(poolName string, datasetName string, s zfsSysctl, v uint64) { + err = c.parseLinuxPoolObjsetFile(file, zpoolPath, func(poolName string, datasetName string, s zfsSysctl, v uint64) { if s != zfsSysctl("kstat.zfs.misc.objset.writes") { return } diff --git a/collector/zfs_solaris.go b/collector/zfs_solaris.go index b94f04dc73..721f265743 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/end-to-end-test.sh b/end-to-end-test.sh index 9aa2b7bfc1..c0b9d67af2 100755 --- a/end-to-end-test.sh +++ b/end-to-end-test.sh @@ -130,8 +130,9 @@ fi --collector.textfile.directory="collector/fixtures/textfile/two_metric_files/" \ --collector.wifi.fixtures="collector/fixtures/wifi" \ --collector.qdisc.fixtures="collector/fixtures/qdisc/" \ - --collector.qdisk.device-include="(wlan0|eth0)" \ + --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 \ diff --git a/go.mod b/go.mod index 9aa81a70ee..107f11c97e 100644 --- a/go.mod +++ b/go.mod @@ -4,17 +4,17 @@ go 1.19 require ( github.com/alecthomas/kingpin/v2 v2.3.2 - github.com/beevik/ntp v1.1.1 + github.com/beevik/ntp v1.3.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1 - github.com/ema/qdisc v0.0.0-20230120214811-5b708f463de3 + 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/josharian/native v1.1.0 - github.com/jsimonetti/rtnetlink v1.3.3 + github.com/jsimonetti/rtnetlink v1.3.5 github.com/lufia/iostat v1.2.1 github.com/mattn/go-xmlrpc v0.0.3 github.com/mdlayher/ethtool v0.1.0 @@ -26,10 +26,10 @@ require ( github.com/prometheus/client_model v0.4.0 github.com/prometheus/common v0.44.0 github.com/prometheus/exporter-toolkit v0.10.0 - github.com/prometheus/procfs v0.11.0 + github.com/prometheus/procfs v0.11.1 github.com/safchain/ethtool v0.3.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 - golang.org/x/sys v0.9.0 + golang.org/x/sys v0.12.0 howett.net/plist v1.0.0 ) @@ -53,9 +53,9 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.10.0 // indirect - golang.org/x/net v0.10.0 // indirect + golang.org/x/net v0.11.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sync v0.2.0 // indirect + golang.org/x/sync v0.3.0 // indirect golang.org/x/text v0.10.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/go.sum b/go.sum index 279497cbcc..f1ea4e190f 100644 --- a/go.sum +++ b/go.sum @@ -2,13 +2,13 @@ github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWr github.com/alecthomas/kingpin/v2 v2.3.2/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 v1.1.1 h1:ah1SrQMwiyL8eRpb7+Erm7l4PvXnZ/Dnh/gjGZXPvp0= -github.com/beevik/ntp v1.1.1/go.mod h1:br1ZC24XiJQWuIUdrmQT3Bf5jQXIOLaPT+MoAK9Vlk0= +github.com/beevik/ntp v1.3.0 h1:/w5VhpW5BGKS37vFm1p9oVk/t4HnnkKZAZIubHM6F7Q= +github.com/beevik/ntp v1.3.0/go.mod h1:vD6h1um4kzXpqmLTuu0cCLcC+NfvC0IC+ltmEDA8E78= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cilium/ebpf v0.10.0 h1:nk5HPMeoBXtOzbkZBWym+ZWq1GIiHUsBFXxwewXAHLQ= +github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= 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= @@ -19,8 +19,8 @@ github.com/dennwc/btrfs v0.0.0-20230312211831-a1f570bd01a1 h1:ue4Es4Xzz255hWQ7NA 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 v0.0.0-20230120214811-5b708f463de3 h1:Jrl8sD8wO34+EE1dV2vhOXrqFAZa/FILDnZRaV28+cw= -github.com/ema/qdisc v0.0.0-20230120214811-5b708f463de3/go.mod h1:FhIc0fLYi7f+lK5maMsesDqwYojIOh3VfRs8EVd5YJQ= +github.com/ema/qdisc v1.0.0 h1:EHLG08FVRbWLg8uRICa3xzC9Zm0m7HyMHfXobWFnXYg= +github.com/ema/qdisc v1.0.0/go.mod h1:FhIc0fLYi7f+lK5maMsesDqwYojIOh3VfRs8EVd5YJQ= 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= @@ -47,8 +47,8 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jsimonetti/rtnetlink v1.3.3 h1:ycpm3z8XlAzmaacVRjdUT3x6MM1o3YBXsXc7DXSRNCE= -github.com/jsimonetti/rtnetlink v1.3.3/go.mod h1:mW4xSP3wkiqWxHMlfG/gOufp3XnhAxu7EhfABmrWSh8= +github.com/jsimonetti/rtnetlink v1.3.5 h1:hVlNQNRlLDGZz31gBPicsG7Q53rnlsz1l1Ix/9XlpVA= +github.com/jsimonetti/rtnetlink v1.3.5/go.mod h1:0LFedyiTkebnd43tE4YAkWGIq9jQphow4CcwxaT2Y00= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -84,8 +84,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/exporter-toolkit v0.10.0 h1:yOAzZTi4M22ZzVxD+fhy1URTuNRj/36uQJJ5S8IPza8= github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= -github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= -github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= 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= @@ -120,16 +120,17 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -139,12 +140,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.3.0/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= diff --git a/kingpinconfig/flags.go b/kingpinconfig/flags.go index 07618b093f..9dd433b854 100644 --- a/kingpinconfig/flags.go +++ b/kingpinconfig/flags.go @@ -24,6 +24,7 @@ func AddFlags(a *kingpin.Application) collector.NodeCollectorConfig { config.Arp.DeviceInclude = a.Flag("collector.arp.device-include", "Regexp of arp devices to include (mutually exclusive to device-exclude).").String() config.Arp.DeviceExclude = a.Flag("collector.arp.device-exclude", "Regexp of arp devices to exclude (mutually exclusive to device-include).").String() + config.Arp.Netlink = a.Flag("collector.arp.netlink", "Use netlink to gather stats instead of /proc/net/arp.").Default("true").Bool() config.Bcache.PriorityStats = a.Flag("collector.bcache.priorityStats", "Expose expensive priority stats.").Bool() @@ -126,8 +127,10 @@ func AddFlags(a *kingpin.Application) collector.NodeCollectorConfig { config.PowerSupplyClass.IgnoredPowerSupplies = a.Flag("collector.powersupply.ignored-supplies", "Regexp of power supplies to ignore for powersupplyclass collector.").Default("^$").String() config.Qdisc.Fixtures = a.Flag("collector.qdisc.fixtures", "test fixtures to use for qdisc collector end-to-end testing").Default("").String() - config.Qdisc.DeviceInclude = a.Flag("collector.qdisk.device-include", "Regexp of qdisk devices to include (mutually exclusive to device-exclude).").String() - config.Qdisc.DeviceExclude = a.Flag("collector.qdisk.device-exclude", "Regexp of qdisk devices to exclude (mutually exclusive to device-include).").String() + config.Qdisc.DeviceInclude = a.Flag("collector.qdisc.device-include", "Regexp of qdisc devices to include (mutually exclusive to device-exclude).").String() + config.Qdisc.OldDeviceInclude = a.Flag("collector.qdisk.device-include", "DEPRECATED: Use collector.qdisc.device-include").Hidden().String() + config.Qdisc.DeviceExclude = a.Flag("collector.qdisc.device-exclude", "Regexp of qdisc devices to exclude (mutually exclusive to device-include).").String() + config.Qdisc.OldDeviceExclude = a.Flag("collector.qdisk.device-exclude", "DEPRECATED: Use collector.qdisc.device-exclude").Hidden().String() config.Rapl.ZoneLabel = a.Flag("collector.rapl.enable-zone-label", "Enables service unit metric unit_start_time_seconds").Bool()