From 58ab0144afa51d12b1526e6e5a1b452df711e41b Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sat, 13 Nov 2021 10:46:14 +0100 Subject: [PATCH] Use SysctlTimeval for boottime collector on BSD Use SysctlTimeval from the golang.org/x/sys/unix package to simplify the implementation of the boottime collector for the BSDs and allows to build it without cgo. Tested on macOS 11.6, FreeBSD 13 and OpenBSD 7. Signed-off-by: Tobias Klauser --- collector/boot_time_bsd.go | 24 +++++------ collector/boot_time_openbsd_amd64.go | 62 ---------------------------- collector/sysctl_bsd.go | 25 ----------- 3 files changed, 11 insertions(+), 100 deletions(-) delete mode 100644 collector/boot_time_openbsd_amd64.go diff --git a/collector/boot_time_bsd.go b/collector/boot_time_bsd.go index f6eea02d..8a9c17b3 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 c8e9d65c..00000000 --- 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/sysctl_bsd.go b/collector/sysctl_bsd.go index 03a878f7..2ab248ed 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 {