Browse Source

Add clocksource metrics to time collector (#2197)

* Add clocksource metrics to time collector

This closes #1336

Signed-off-by: Johannes 'fish' Ziemke <github@freigeist.org>
pull/2208/head
Johannes 'fish' Ziemke 3 years ago committed by GitHub
parent
commit
85e20238e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      collector/fixtures/e2e-output.txt
  2. 20
      collector/fixtures/sys.ttar
  3. 32
      collector/time.go
  4. 48
      collector/time_linux.go
  5. 25
      collector/time_other.go
  6. 3
      end-to-end-test.sh

13
collector/fixtures/e2e-output.txt

@ -3010,6 +3010,7 @@ node_scrape_collector_success{collector="stat"} 1
node_scrape_collector_success{collector="tapestats"} 1 node_scrape_collector_success{collector="tapestats"} 1
node_scrape_collector_success{collector="textfile"} 1 node_scrape_collector_success{collector="textfile"} 1
node_scrape_collector_success{collector="thermal_zone"} 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="udp_queues"} 1
node_scrape_collector_success{collector="vmstat"} 1 node_scrape_collector_success{collector="vmstat"} 1
node_scrape_collector_success{collector="wifi"} 1 node_scrape_collector_success{collector="wifi"} 1
@ -3132,6 +3133,18 @@ node_textfile_scrape_error 0
# HELP node_thermal_zone_temp Zone temperature in Celsius # HELP node_thermal_zone_temp Zone temperature in Celsius
# TYPE node_thermal_zone_temp gauge # TYPE node_thermal_zone_temp gauge
node_thermal_zone_temp{type="cpu-thermal",zone="0"} 12.376 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. # HELP node_udp_queues Number of allocated memory in the kernel for UDP datagrams in bytes.
# TYPE node_udp_queues gauge # TYPE node_udp_queues gauge
node_udp_queues{ip="v4",queue="rx"} 0 node_udp_queues{ip="v4",queue="rx"} 0

20
collector/fixtures/sys.ttar

@ -3213,6 +3213,22 @@ Mode: 644
Directory: sys/devices/system Directory: sys/devices/system
Mode: 755 Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # 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 Directory: sys/devices/system/cpu
Mode: 755 Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -4702,7 +4718,3 @@ Lines: 1
20 20
Mode: 644 Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: sys/.unpacked
Lines: 0
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

32
collector/time.go

@ -25,9 +25,11 @@ import (
) )
type timeCollector struct { type timeCollector struct {
nowDesc *prometheus.Desc now typedDesc
zoneDesc *prometheus.Desc zone typedDesc
logger log.Logger clocksourcesAvailable typedDesc
clocksourceCurrent typedDesc
logger log.Logger
} }
func init() { func init() {
@ -39,16 +41,26 @@ func init() {
func NewTimeCollector(logger log.Logger) (Collector, error) { func NewTimeCollector(logger log.Logger) (Collector, error) {
const subsystem = "time" const subsystem = "time"
return &timeCollector{ return &timeCollector{
nowDesc: prometheus.NewDesc( now: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "seconds"), prometheus.BuildFQName(namespace, subsystem, "seconds"),
"System time in seconds since epoch (1970).", "System time in seconds since epoch (1970).",
nil, nil, nil, nil,
), ), prometheus.GaugeValue},
zoneDesc: prometheus.NewDesc( zone: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "zone_offset_seconds"), prometheus.BuildFQName(namespace, subsystem, "zone_offset_seconds"),
"System time zone offset in seconds.", "System time zone offset in seconds.",
[]string{"time_zone"}, nil, []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, logger: logger,
}, nil }, nil
} }
@ -59,8 +71,8 @@ func (c *timeCollector) Update(ch chan<- prometheus.Metric) error {
zone, zoneOffset := now.Zone() zone, zoneOffset := now.Zone()
level.Debug(c.logger).Log("msg", "Return time", "now", nowSec) 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) level.Debug(c.logger).Log("msg", "Zone offset", "offset", zoneOffset, "time_zone", zone)
ch <- prometheus.MustNewConstMetric(c.zoneDesc, prometheus.GaugeValue, float64(zoneOffset), zone) ch <- c.zone.mustNewConstMetric(float64(zoneOffset), zone)
return nil return c.update(ch)
} }

48
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 linux && !notime
// +build linux,!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
}

25
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
}

3
end-to-end-test.sh

@ -51,7 +51,6 @@ COLLECTORS
) )
disabled_collectors=$(cat << COLLECTORS disabled_collectors=$(cat << COLLECTORS
filesystem filesystem
time
timex timex
uname uname
COLLECTORS COLLECTORS
@ -61,7 +60,7 @@ cd "$(dirname $0)"
port="$((10000 + (RANDOM % 10000)))" port="$((10000 + (RANDOM % 10000)))"
tmpdir=$(mktemp -d /tmp/node_exporter_e2e_test.XXXXXX) 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))"
arch="$(uname -m)" arch="$(uname -m)"

Loading…
Cancel
Save