2023-11-04 19:51:35 +00:00
//go:build windows
package time
import (
"errors"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/winversion"
"github.com/prometheus/client_golang/prometheus"
)
const Name = "time"
type Config struct { }
var ConfigDefaults = Config { }
2024-08-10 20:05:33 +00:00
// Collector is a Prometheus Collector for Perflib counter metrics.
2024-08-05 13:50:41 +00:00
type Collector struct {
2024-08-11 11:28:39 +00:00
config Config
2023-11-04 19:51:35 +00:00
2024-08-10 18:02:07 +00:00
clockFrequencyAdjustmentPPBTotal * prometheus . Desc
computedTimeOffset * prometheus . Desc
ntpClientTimeSourceCount * prometheus . Desc
ntpRoundTripDelay * prometheus . Desc
ntpServerIncomingRequestsTotal * prometheus . Desc
ntpServerOutgoingResponsesTotal * prometheus . Desc
2023-11-04 19:51:35 +00:00
}
2024-08-24 17:14:38 +00:00
func New ( config * Config ) * Collector {
2024-08-11 11:28:39 +00:00
if config == nil {
config = & ConfigDefaults
}
c := & Collector {
config : * config ,
}
2023-11-04 19:51:35 +00:00
return c
}
2024-08-05 13:50:41 +00:00
func NewWithFlags ( _ * kingpin . Application ) * Collector {
return & Collector { }
2023-11-04 19:51:35 +00:00
}
2024-08-05 13:50:41 +00:00
func ( c * Collector ) GetName ( ) string {
2023-11-04 19:51:35 +00:00
return Name
}
2024-08-24 17:14:38 +00:00
func ( c * Collector ) GetPerfCounter ( _ log . Logger ) ( [ ] string , error ) {
2023-11-04 19:51:35 +00:00
return [ ] string { "Windows Time Service" } , nil
}
2024-08-05 13:50:41 +00:00
func ( c * Collector ) Close ( ) error {
return nil
}
2024-08-24 17:14:38 +00:00
func ( c * Collector ) Build ( _ log . Logger ) error {
2023-11-04 19:51:35 +00:00
if winversion . WindowsVersionFloat <= 6.1 {
return errors . New ( "Windows version older than Server 2016 detected. The time collector will not run and should be disabled via CLI flags or configuration file" )
}
2024-08-10 18:02:07 +00:00
c . clockFrequencyAdjustmentPPBTotal = prometheus . NewDesc (
2023-11-04 19:51:35 +00:00
prometheus . BuildFQName ( types . Namespace , Name , "clock_frequency_adjustment_ppb_total" ) ,
"Total adjustment made to the local system clock frequency by W32Time in Parts Per Billion (PPB) units." ,
nil ,
nil ,
)
2024-08-10 18:02:07 +00:00
c . computedTimeOffset = prometheus . NewDesc (
2023-11-04 19:51:35 +00:00
prometheus . BuildFQName ( types . Namespace , Name , "computed_time_offset_seconds" ) ,
"Absolute time offset between the system clock and the chosen time source, in seconds" ,
nil ,
nil ,
)
2024-08-10 18:02:07 +00:00
c . ntpClientTimeSourceCount = prometheus . NewDesc (
2023-11-04 19:51:35 +00:00
prometheus . BuildFQName ( types . Namespace , Name , "ntp_client_time_sources" ) ,
"Active number of NTP Time sources being used by the client" ,
nil ,
nil ,
)
2024-08-10 18:02:07 +00:00
c . ntpRoundTripDelay = prometheus . NewDesc (
2023-11-04 19:51:35 +00:00
prometheus . BuildFQName ( types . Namespace , Name , "ntp_round_trip_delay_seconds" ) ,
"Roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds" ,
nil ,
nil ,
)
2024-08-10 18:02:07 +00:00
c . ntpServerOutgoingResponsesTotal = prometheus . NewDesc (
2023-11-04 19:51:35 +00:00
prometheus . BuildFQName ( types . Namespace , Name , "ntp_server_outgoing_responses_total" ) ,
"Total number of requests responded to by NTP server" ,
nil ,
nil ,
)
2024-08-10 18:02:07 +00:00
c . ntpServerIncomingRequestsTotal = prometheus . NewDesc (
2023-11-04 19:51:35 +00:00
prometheus . BuildFQName ( types . Namespace , Name , "ntp_server_incoming_requests_total" ) ,
"Total number of requests received by NTP server" ,
nil ,
nil ,
)
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
2024-08-24 17:14:38 +00:00
func ( c * Collector ) Collect ( ctx * types . ScrapeContext , logger log . Logger , ch chan <- prometheus . Metric ) error {
logger = log . With ( logger , "collector" , Name )
if err := c . collect ( ctx , logger , ch ) ; err != nil {
_ = level . Error ( logger ) . Log ( "msg" , "failed collecting time metrics" , "err" , err )
2023-11-04 19:51:35 +00:00
return err
}
return nil
}
2024-08-10 20:05:33 +00:00
// Perflib "Windows Time Service".
2023-11-04 19:51:35 +00:00
type windowsTime struct {
ClockFrequencyAdjustmentPPBTotal float64 ` perflib:"Clock Frequency Adjustment (ppb)" `
ComputedTimeOffset float64 ` perflib:"Computed Time Offset" `
NTPClientTimeSourceCount float64 ` perflib:"NTP Client Time Source Count" `
NTPRoundtripDelay float64 ` perflib:"NTP Roundtrip Delay" `
NTPServerIncomingRequestsTotal float64 ` perflib:"NTP Server Incoming Requests" `
NTPServerOutgoingResponsesTotal float64 ` perflib:"NTP Server Outgoing Responses" `
}
2024-08-24 17:14:38 +00:00
func ( c * Collector ) collect ( ctx * types . ScrapeContext , logger log . Logger , ch chan <- prometheus . Metric ) error {
logger = log . With ( logger , "collector" , Name )
2023-11-04 19:51:35 +00:00
var dst [ ] windowsTime // Single-instance class, array is required but will have single entry.
2024-08-24 17:14:38 +00:00
if err := perflib . UnmarshalObject ( ctx . PerfObjects [ "Windows Time Service" ] , & dst , logger ) ; err != nil {
2024-05-11 10:05:45 +00:00
return err
2023-11-04 19:51:35 +00:00
}
ch <- prometheus . MustNewConstMetric (
2024-08-10 18:02:07 +00:00
c . clockFrequencyAdjustmentPPBTotal ,
2023-11-04 19:51:35 +00:00
prometheus . CounterValue ,
dst [ 0 ] . ClockFrequencyAdjustmentPPBTotal ,
)
ch <- prometheus . MustNewConstMetric (
2024-08-10 18:02:07 +00:00
c . computedTimeOffset ,
2023-11-04 19:51:35 +00:00
prometheus . GaugeValue ,
dst [ 0 ] . ComputedTimeOffset / 1000000 , // microseconds -> seconds
)
ch <- prometheus . MustNewConstMetric (
2024-08-10 18:02:07 +00:00
c . ntpClientTimeSourceCount ,
2023-11-04 19:51:35 +00:00
prometheus . GaugeValue ,
dst [ 0 ] . NTPClientTimeSourceCount ,
)
ch <- prometheus . MustNewConstMetric (
2024-08-10 18:02:07 +00:00
c . ntpRoundTripDelay ,
2023-11-04 19:51:35 +00:00
prometheus . GaugeValue ,
dst [ 0 ] . NTPRoundtripDelay / 1000000 , // microseconds -> seconds
)
ch <- prometheus . MustNewConstMetric (
2024-08-10 18:02:07 +00:00
c . ntpServerIncomingRequestsTotal ,
2023-11-04 19:51:35 +00:00
prometheus . CounterValue ,
dst [ 0 ] . NTPServerIncomingRequestsTotal ,
)
ch <- prometheus . MustNewConstMetric (
2024-08-10 18:02:07 +00:00
c . ntpServerOutgoingResponsesTotal ,
2023-11-04 19:51:35 +00:00
prometheus . CounterValue ,
dst [ 0 ] . NTPServerOutgoingResponsesTotal ,
)
2024-05-11 10:05:45 +00:00
return nil
2023-11-04 19:51:35 +00:00
}