From aa7157e27c4197f1a6fafa1ba68b91ef6f7024a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sun, 6 Apr 2025 11:57:14 +0200 Subject: [PATCH] system: Metric `windows_system_boot_time_timestamp` returns a UNIX timestamp again. (#1967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke Signed-off-by: Jan-Otto Kröpke (cherry picked from commit ba605cffcce3503645bb57542bb46662d23244d1) --- docs/collector.system.md | 4 +-- internal/collector/system/system.go | 37 +++++++++++++++++++++------ internal/collector/system/types.go | 1 - internal/headers/kernel32/kernel32.go | 15 ++++++++--- tools/e2e-output.txt | 4 ++- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/docs/collector.system.md b/docs/collector.system.md index 937c6734..438539d1 100644 --- a/docs/collector.system.md +++ b/docs/collector.system.md @@ -16,7 +16,7 @@ None | Name | Description | Type | Labels | |----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------| -| `windows_system_boot_time_timestamp_seconds` | Unix timestamp of last system boot | gauge | None | +| `windows_system_boot_time_timestamp` | Unix timestamp of last system boot | gauge | None | | `windows_system_context_switches_total` | Total number of [context switches](https://en.wikipedia.org/wiki/Context_switch) | counter | None | | `windows_system_exception_dispatches_total` | Total exceptions dispatched by the system | counter | None | | `windows_system_processes` | Number of process contexts currently loaded or running on the operating system | gauge | None | @@ -41,7 +41,7 @@ windows_system_processes{instance="localhost"} ## Useful queries Find hosts that have rebooted in the last 24 hours ``` -time() - windows_system_boot_time_timestamp_seconds < 86400 +time() - windows_system_boot_time_timestamp < 86400 ``` ## Alerting examples diff --git a/internal/collector/system/system.go b/internal/collector/system/system.go index c3818929..b574fcc0 100644 --- a/internal/collector/system/system.go +++ b/internal/collector/system/system.go @@ -18,8 +18,10 @@ package system import ( "fmt" "log/slog" + "time" "github.com/alecthomas/kingpin/v2" + "github.com/prometheus-community/windows_exporter/internal/headers/kernel32" "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/types" @@ -37,6 +39,8 @@ var ConfigDefaults = Config{} type Collector struct { config Config + bootTimeTimestamp float64 + perfDataCollector *pdh.Collector perfDataObject []perfDataCounterValues @@ -46,8 +50,10 @@ type Collector struct { processes *prometheus.Desc processesLimit *prometheus.Desc systemCallsTotal *prometheus.Desc - bootTime *prometheus.Desc - threads *prometheus.Desc + // Deprecated: Use windows_system_boot_time_timestamp instead + bootTimeSeconds *prometheus.Desc + bootTime *prometheus.Desc + threads *prometheus.Desc } func New(config *Config) *Collector { @@ -78,11 +84,17 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { c.bootTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "boot_time_timestamp_seconds"), + prometheus.BuildFQName(types.Namespace, Name, "boot_time_timestamp"), "Unix timestamp of system boot time", nil, nil, ) + c.bootTimeSeconds = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "boot_time_timestamp_seconds"), + "Deprecated: Use windows_system_boot_time_timestamp instead", + nil, + nil, + ) c.contextSwitchesTotal = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "context_switches_total"), "Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)", @@ -127,6 +139,8 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { nil, ) + c.bootTimeTimestamp = float64(time.Now().Unix() - int64(kernel32.GetTickCount64()/1000)) + var err error c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "System", nil) @@ -170,17 +184,24 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error { prometheus.CounterValue, c.perfDataObject[0].SystemCallsPerSec, ) - ch <- prometheus.MustNewConstMetric( - c.bootTime, - prometheus.GaugeValue, - c.perfDataObject[0].SystemUpTime, - ) ch <- prometheus.MustNewConstMetric( c.threads, prometheus.GaugeValue, c.perfDataObject[0].Threads, ) + ch <- prometheus.MustNewConstMetric( + c.bootTimeSeconds, + prometheus.GaugeValue, + c.bootTimeTimestamp, + ) + + ch <- prometheus.MustNewConstMetric( + c.bootTime, + prometheus.GaugeValue, + c.bootTimeTimestamp, + ) + // Windows has no defined limit, and is based off available resources. This currently isn't calculated by WMI and is set to default value. // https://techcommunity.microsoft.com/t5/windows-blog-archive/pushing-the-limits-of-windows-processes-and-threads/ba-p/723824 // https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem diff --git a/internal/collector/system/types.go b/internal/collector/system/types.go index 03c156fa..b6336a97 100644 --- a/internal/collector/system/types.go +++ b/internal/collector/system/types.go @@ -20,7 +20,6 @@ type perfDataCounterValues struct { ExceptionDispatchesPerSec float64 `perfdata:"Exception Dispatches/sec"` ProcessorQueueLength float64 `perfdata:"Processor Queue Length"` SystemCallsPerSec float64 `perfdata:"System Calls/sec"` - SystemUpTime float64 `perfdata:"System Up Time"` Processes float64 `perfdata:"Processes"` Threads float64 `perfdata:"Threads"` } diff --git a/internal/headers/kernel32/kernel32.go b/internal/headers/kernel32/kernel32.go index 092f9878..07ba6f73 100644 --- a/internal/headers/kernel32/kernel32.go +++ b/internal/headers/kernel32/kernel32.go @@ -23,10 +23,11 @@ import ( //nolint:gochecknoglobals var ( - kernel32 = windows.NewLazySystemDLL("kernel32.dll") + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - procGetDynamicTimeZoneInformationSys = kernel32.NewProc("GetDynamicTimeZoneInformation") - kernelLocalFileTimeToFileTime = kernel32.NewProc("LocalFileTimeToFileTime") + procGetDynamicTimeZoneInformationSys = modkernel32.NewProc("GetDynamicTimeZoneInformation") + procKernelLocalFileTimeToFileTime = modkernel32.NewProc("LocalFileTimeToFileTime") + procGetTickCount = modkernel32.NewProc("GetTickCount64") ) // SYSTEMTIME contains a date and time. @@ -70,9 +71,15 @@ func GetDynamicTimeZoneInformation() (DynamicTimezoneInformation, error) { } func LocalFileTimeToFileTime(localFileTime, utcFileTime *windows.Filetime) uint32 { - ret, _, _ := kernelLocalFileTimeToFileTime.Call( + ret, _, _ := procKernelLocalFileTimeToFileTime.Call( uintptr(unsafe.Pointer(localFileTime)), uintptr(unsafe.Pointer(utcFileTime))) return uint32(ret) } + +func GetTickCount64() uint64 { + ret, _, _ := procGetTickCount.Call() + + return uint64(ret) +} diff --git a/tools/e2e-output.txt b/tools/e2e-output.txt index 7b4e6f65..fcd2f3bc 100644 --- a/tools/e2e-output.txt +++ b/tools/e2e-output.txt @@ -389,7 +389,9 @@ windows_service_state{name="Themes",state="running"} 1 windows_service_state{name="Themes",state="start pending"} 0 windows_service_state{name="Themes",state="stop pending"} 0 windows_service_state{name="Themes",state="stopped"} 0 -# HELP windows_system_boot_time_timestamp_seconds Unix timestamp of system boot time +# HELP windows_system_boot_time_timestamp Unix timestamp of system boot time +# TYPE windows_system_boot_time_timestamp gauge +# HELP windows_system_boot_time_timestamp_seconds Deprecated: Use windows_system_boot_time_timestamp instead # TYPE windows_system_boot_time_timestamp_seconds gauge # HELP windows_system_context_switches_total Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec) # TYPE windows_system_context_switches_total counter