github.com/netdata/go.d.plugin@v0.58.1/modules/ntpd/collect.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package ntpd 4 5 import ( 6 "fmt" 7 "net" 8 "strconv" 9 "time" 10 ) 11 12 const ( 13 precision = 1000000 14 ) 15 16 func (n *NTPd) collect() (map[string]int64, error) { 17 if n.client == nil { 18 client, err := n.newClient(n.Config) 19 if err != nil { 20 return nil, fmt.Errorf("creating NTP client: %v", err) 21 } 22 n.client = client 23 } 24 25 mx := make(map[string]int64) 26 27 if err := n.collectInfo(mx); err != nil { 28 return nil, err 29 } 30 31 if n.CollectPeers { 32 if now := time.Now(); now.Sub(n.findPeersTime) > n.findPeersEvery { 33 n.findPeersTime = now 34 if err := n.findPeers(); err != nil { 35 n.Warning(err) 36 } 37 } 38 n.collectPeersInfo(mx) 39 } 40 41 return mx, nil 42 } 43 44 func (n *NTPd) collectInfo(mx map[string]int64) error { 45 info, err := n.client.systemInfo() 46 if err != nil { 47 return fmt.Errorf("error on querying system info: %v", err) 48 } 49 50 for k, v := range info { 51 switch k { 52 case 53 "offset", 54 "sys_jitter", 55 "clk_jitter", 56 "frequency", 57 "clk_wander", 58 "rootdelay", 59 "rootdisp", 60 "stratum", 61 "tc", 62 "mintc", 63 "precision": 64 if val, err := strconv.ParseFloat(v, 64); err == nil { 65 mx[k] = int64(val * precision) 66 } 67 } 68 } 69 return nil 70 } 71 72 func (n *NTPd) collectPeersInfo(mx map[string]int64) { 73 for _, id := range n.peerIDs { 74 info, err := n.client.peerInfo(id) 75 if err != nil { 76 n.Warningf("error on querying NTP peer info id='%d': %v", id, err) 77 continue 78 } 79 80 addr, ok := info["srcadr"] 81 if !ok { 82 continue 83 } 84 85 for k, v := range info { 86 switch k { 87 case 88 "offset", 89 "delay", 90 "dispersion", 91 "jitter", 92 "xleave", 93 "rootdelay", 94 "rootdisp", 95 "stratum", 96 "hmode", 97 "pmode", 98 "hpoll", 99 "ppoll", 100 "precision": 101 if val, err := strconv.ParseFloat(v, 64); err == nil { 102 mx["peer_"+addr+"_"+k] = int64(val * precision) 103 } 104 } 105 } 106 } 107 } 108 109 func (n *NTPd) findPeers() error { 110 n.peerIDs = n.peerIDs[:0] 111 112 n.Debug("querying NTP peers") 113 peers, err := n.client.peerIDs() 114 if err != nil { 115 return fmt.Errorf("querying NTP peers: %v", err) 116 } 117 118 n.Debugf("found %d NTP peers (ids: %v)", len(peers), peers) 119 seen := make(map[string]bool) 120 121 for _, id := range peers { 122 info, err := n.client.peerInfo(id) 123 if err != nil { 124 n.Debugf("error on querying NTP peer info id='%d': %v", id, err) 125 continue 126 } 127 128 addr, ok := info["srcadr"] 129 if ip := net.ParseIP(addr); !ok || ip == nil || n.peerIPAddrFilter.Contains(ip) { 130 n.Debugf("skipping NTP peer id='%d', srcadr='%s'", id, addr) 131 continue 132 } 133 134 seen[addr] = true 135 136 if !n.peerAddr[addr] { 137 n.peerAddr[addr] = true 138 n.Debugf("new NTP peer id='%d', srcadr='%s': creating charts", id, addr) 139 n.addPeerCharts(addr) 140 } 141 142 n.peerIDs = append(n.peerIDs, id) 143 } 144 145 for addr := range n.peerAddr { 146 if !seen[addr] { 147 delete(n.peerAddr, addr) 148 n.Debugf("stale NTP peer srcadr='%s': removing charts", addr) 149 n.removePeerCharts(addr) 150 } 151 } 152 153 return nil 154 }