tsweb/varz: add node_boot_time_seconds expvar
Export the machine's boot time (the btime line from Linux's /proc/stat) as node_boot_time_seconds, named to match what Prometheus's node exporter uses for the same value. Combined with process_start_unix_time, this can be used to distinguish process restarts from whole node restarts. The value is parsed once per process lifetime, not per scrape, and the metric is only published when a value is available, so non-Linux systems don't export a bogus zero. Updates tailscale/corp#44743 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I5f53186b97bb1482bd1a5387c0910b0ae26544ff
This commit is contained in:
committed by
Brad Fitzpatrick
parent
16f600df8c
commit
0e79b322a9
@@ -42,8 +42,34 @@ func init() {
|
|||||||
expvar.Publish("go_version", StaticStringVar(runtime.Version()))
|
expvar.Publish("go_version", StaticStringVar(runtime.Version()))
|
||||||
expvar.Publish("counter_uptime_sec", expvar.Func(func() any { return int64(Uptime().Seconds()) }))
|
expvar.Publish("counter_uptime_sec", expvar.Func(func() any { return int64(Uptime().Seconds()) }))
|
||||||
expvar.Publish("gauge_goroutines", expvar.Func(func() any { return runtime.NumGoroutine() }))
|
expvar.Publish("gauge_goroutines", expvar.Func(func() any { return runtime.NumGoroutine() }))
|
||||||
|
if v := nodeBootTime(); v != 0 {
|
||||||
|
var vi any = v // box once
|
||||||
|
// The name matches what Prometheus's node exporter uses
|
||||||
|
// for the same value.
|
||||||
|
expvar.Publish("node_boot_time_seconds", expvar.Func(func() any { return vi }))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nodeBootTime returns the machine's boot time in Unix seconds,
|
||||||
|
// as reported by the "btime" line of Linux's /proc/stat.
|
||||||
|
// It returns 0 if unavailable, such as on non-Linux systems.
|
||||||
|
var nodeBootTime = sync.OnceValue(func() int64 {
|
||||||
|
stat, err := os.ReadFile("/proc/stat")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for line := range strings.Lines(string(stat)) {
|
||||||
|
if rest, ok := strings.CutPrefix(line, "btime "); ok {
|
||||||
|
sec, err := strconv.ParseInt(strings.TrimSpace(rest), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return sec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gaugePrefix = "gauge_"
|
gaugePrefix = "gauge_"
|
||||||
counterPrefix = "counter_"
|
counterPrefix = "counter_"
|
||||||
|
|||||||
Reference in New Issue
Block a user