diff --git a/CHANGELOG.md b/CHANGELOG.md index 28cefae4..c445503b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The cpufreq metrics now separate the `cpufreq` and `scaling` data based on what * [ENHANCEMENT] Add Infiniband counters #1120 * [FEATURE] Add a flag to disable exporter metrics #1148 * [FEATURE] Add kstat-based Solaris metrics for boottime, cpu and zfs collectors #1197 +* [FEATURE] Add uname collector for FreeBSD #1239 ## 0.17.0 / 2018-11-30 diff --git a/README.md b/README.md index 9066d85a..187e2758 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ stat | Exposes various statistics from `/proc/stat`. This includes boot time, fo textfile | Exposes statistics read from local disk. The `--collector.textfile.directory` flag must be set. | _any_ time | Exposes the current system time. | _any_ timex | Exposes selected adjtimex(2) system call stats. | Linux -uname | Exposes system information as provided by the uname system call. | Linux +uname | Exposes system information as provided by the uname system call. | FreeBSD, Linux 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 diff --git a/collector/uname.go b/collector/uname.go new file mode 100644 index 00000000..e9a633f9 --- /dev/null +++ b/collector/uname.go @@ -0,0 +1,72 @@ +// Copyright 2019 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. + +// +build freebsd linux +// +build !nouname + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +var unameDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "uname", "info"), + "Labeled system information as provided by the uname system call.", + []string{ + "sysname", + "release", + "version", + "machine", + "nodename", + "domainname", + }, + nil, +) + +type unameCollector struct{} +type uname struct { + SysName string + Release string + Version string + Machine string + NodeName string + DomainName string +} + +func init() { + registerCollector("uname", defaultEnabled, newUnameCollector) +} + +// NewUnameCollector returns new unameCollector. +func newUnameCollector() (Collector, error) { + return &unameCollector{}, nil +} + +func (c unameCollector) Update(ch chan<- prometheus.Metric) error { + uname, err := getUname() + if err != nil { + return err + } + + ch <- prometheus.MustNewConstMetric(unameDesc, prometheus.GaugeValue, 1, + uname.SysName, + uname.Release, + uname.Version, + uname.Machine, + uname.NodeName, + uname.DomainName, + ) + + return nil +} diff --git a/collector/uname_freebsd.go b/collector/uname_freebsd.go new file mode 100644 index 00000000..9e4a8ba4 --- /dev/null +++ b/collector/uname_freebsd.go @@ -0,0 +1,57 @@ +// Copyright 2019 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. + +// +build !nouname + +package collector + +import ( + "bytes" + "strings" + + "golang.org/x/sys/unix" +) + +func getUname() (uname, error) { + var utsname unix.Utsname + if err := unix.Uname(&utsname); err != nil { + return uname{}, err + } + + // We do a little bit of work here to emulate what happens in the Linux + // uname calls since FreeBSD uname doesn't have a Domainname. + nodename := string(utsname.Nodename[:bytes.IndexByte(utsname.Nodename[:], 0)]) + split := strings.SplitN(nodename, ".", 2) + + // We'll always have at least a single element in the array. We assume this + // is the hostname. + hostname := split[0] + + // If we have more than one element, we assume this is the domainname. + // Otherwise leave it to "(none)" like Linux. + domainname := "(none)" + if len(split) > 1 { + domainname = split[1] + } + + 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: hostname, + DomainName: domainname, + } + + return output, nil +} diff --git a/collector/uname_linux.go b/collector/uname_linux.go index 090180db..65de6297 100644 --- a/collector/uname_linux.go +++ b/collector/uname_linux.go @@ -18,49 +18,23 @@ package collector import ( "bytes" - "github.com/prometheus/client_golang/prometheus" - "golang.org/x/sys/unix" ) -var unameDesc = prometheus.NewDesc( - prometheus.BuildFQName(namespace, "uname", "info"), - "Labeled system information as provided by the uname system call.", - []string{ - "sysname", - "release", - "version", - "machine", - "nodename", - "domainname", - }, - nil, -) - -type unameCollector struct{} - -func init() { - registerCollector("uname", defaultEnabled, newUnameCollector) -} - -// NewUnameCollector returns new unameCollector. -func newUnameCollector() (Collector, error) { - return &unameCollector{}, nil -} - -func (c unameCollector) Update(ch chan<- prometheus.Metric) error { - var uname unix.Utsname - if err := unix.Uname(&uname); err != nil { - return err +func getUname() (uname, error) { + var utsname unix.Utsname + if err := unix.Uname(&utsname); err != nil { + return uname{}, err } - ch <- prometheus.MustNewConstMetric(unameDesc, prometheus.GaugeValue, 1, - string(uname.Sysname[:bytes.IndexByte(uname.Sysname[:], 0)]), - string(uname.Release[:bytes.IndexByte(uname.Release[:], 0)]), - string(uname.Version[:bytes.IndexByte(uname.Version[:], 0)]), - string(uname.Machine[:bytes.IndexByte(uname.Machine[:], 0)]), - string(uname.Nodename[:bytes.IndexByte(uname.Nodename[:], 0)]), - string(uname.Domainname[:bytes.IndexByte(uname.Domainname[:], 0)]), - ) - return nil + 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)]), + } + + return output, nil }