in cmd/ntpcheck/checker/stats.go [39:102]
func NewNTPStats(r *NTPCheckResult) (*NTPStats, error) {
if r.SysVars == nil {
return nil, errors.New("no system variables to output stats")
}
syspeer, err := r.FindSysPeer()
var delay, jitter, offset float64
var poll uint
var stratum int
if err != nil {
log.Warningf("Can't get system peer: %v", err)
// calculate averages like ntp_stats_ods.py did
total := len(r.Peers)
if total == 0 {
return nil, errors.New("no peers detected to output stats")
}
goodPeers, err := r.FindGoodPeers()
if err != nil {
return nil, errors.Wrap(err, "nothing to calculate stats from")
}
totalDelay := 0.0
totalJitter := 0.0
totalOffset := 0.0
bestPPoll := 0
bestHPoll := 0
bestStratum := 0
for _, p := range goodPeers {
totalDelay += p.Delay
totalJitter += p.Jitter
totalOffset += p.Offset
if bestPPoll != 0 && p.PPoll < bestPPoll {
bestPPoll = p.PPoll
}
if bestHPoll != 0 && p.HPoll < bestHPoll {
bestHPoll = p.HPoll
}
if bestStratum != 0 && p.Stratum < bestStratum {
bestStratum = p.Stratum
}
}
delay = totalDelay / float64(total)
jitter = totalJitter / float64(total)
offset = totalOffset / float64(total)
stratum = bestStratum
poll = uint(math.Min(float64(bestPPoll), float64(bestHPoll)))
} else {
delay = syspeer.Delay
jitter = syspeer.Jitter
poll = uint(math.Min(float64(syspeer.PPoll), float64(syspeer.HPoll)))
stratum = syspeer.Stratum
offset = syspeer.Offset
}
output := NTPStats{
PeerDelay: delay,
PeerPoll: 1 << poll, // hpoll and ppoll are stored in seconds as a power of two
PeerJitter: jitter,
PeerOffset: offset,
PeerStratum: stratum,
Frequency: r.SysVars.Frequency,
Correction: r.Correction,
// that's how ntpstat defines unsynchronized
StatError: r.LI == 3,
}
return &output, nil
}