github.com/netdata/go.d.plugin@v0.58.1/modules/consul/collect_net_rtt.go (about) 1 package consul 2 3 import ( 4 "math" 5 "time" 6 7 "github.com/netdata/go.d.plugin/pkg/metrics" 8 ) 9 10 const ( 11 // https://developer.hashicorp.com/consul/api-docs/coordinate#read-lan-coordinates-for-all-nodes 12 urlPathCoordinateNodes = "/v1/coordinate/nodes" 13 ) 14 15 type nodeCoordinates struct { 16 Node string 17 Coord struct { 18 Vec []float64 19 Error float64 20 Adjustment float64 21 Height float64 22 } 23 } 24 25 func (c *Consul) collectNetworkRTT(mx map[string]int64) error { 26 var coords []nodeCoordinates 27 28 if err := c.doOKDecode(urlPathCoordinateNodes, &coords); err != nil { 29 return err 30 } 31 32 var thisNode nodeCoordinates 33 var ok bool 34 35 coords, thisNode, ok = removeNodeCoordinates(coords, c.cfg.Config.NodeName) 36 if !ok || len(coords) == 0 { 37 return nil 38 } 39 40 sum := metrics.NewSummary() 41 for _, v := range coords { 42 d := calcDistance(thisNode, v) 43 sum.Observe(d.Seconds()) 44 } 45 sum.WriteTo(mx, "network_lan_rtt", 1e9, 1) 46 47 return nil 48 } 49 50 func calcDistance(a, b nodeCoordinates) time.Duration { 51 // https://developer.hashicorp.com/consul/docs/architecture/coordinates#working-with-coordinates 52 sum := 0.0 53 for i := 0; i < len(a.Coord.Vec); i++ { 54 diff := a.Coord.Vec[i] - b.Coord.Vec[i] 55 sum += diff * diff 56 } 57 58 rtt := math.Sqrt(sum) + a.Coord.Height + b.Coord.Height 59 60 adjusted := rtt + a.Coord.Adjustment + b.Coord.Adjustment 61 if adjusted > 0.0 { 62 rtt = adjusted 63 } 64 65 return time.Duration(rtt * 1e9) // nanoseconds 66 } 67 68 func removeNodeCoordinates(coords []nodeCoordinates, node string) ([]nodeCoordinates, nodeCoordinates, bool) { 69 for i, v := range coords { 70 if v.Node == node { 71 return append(coords[:i], coords[i+1:]...), v, true 72 } 73 } 74 return coords, nodeCoordinates{}, false 75 }