master
go 80 lines 1.74 KB
Raw
1 package consul
2
3 import (
4 "math"
5 "time"
6
7 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/oldmetrix"
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 *Collector) collectNetworkRTT(mx map[string]int64) error {
26 req, err := c.createRequest(urlPathCoordinateNodes)
27 if err != nil {
28 return err
29 }
30
31 var coords []nodeCoordinates
32
33 if err := c.client().RequestJSON(req, &coords); err != nil {
34 return err
35 }
36
37 var thisNode nodeCoordinates
38 var ok bool
39
40 coords, thisNode, ok = removeNodeCoordinates(coords, c.cfg.Config.NodeName)
41 if !ok || len(coords) == 0 {
42 return nil
43 }
44
45 sum := oldmetrix.NewSummary()
46 for _, v := range coords {
47 d := calcDistance(thisNode, v)
48 sum.Observe(d.Seconds())
49 }
50 sum.WriteTo(mx, "network_lan_rtt", 1e9, 1)
51
52 return nil
53 }
54
55 func calcDistance(a, b nodeCoordinates) time.Duration {
56 // https://developer.hashicorp.com/consul/docs/architecture/coordinates#working-with-coordinates
57 sum := 0.0
58 for i := 0; i < len(a.Coord.Vec); i++ {
59 diff := a.Coord.Vec[i] - b.Coord.Vec[i]
60 sum += diff * diff
61 }
62
63 rtt := math.Sqrt(sum) + a.Coord.Height + b.Coord.Height
64
65 adjusted := rtt + a.Coord.Adjustment + b.Coord.Adjustment
66 if adjusted > 0.0 {
67 rtt = adjusted
68 }
69
70 return time.Duration(rtt * 1e9) // nanoseconds
71 }
72
73 func removeNodeCoordinates(coords []nodeCoordinates, node string) ([]nodeCoordinates, nodeCoordinates, bool) {
74 for i, v := range coords {
75 if v.Node == node {
76 return append(coords[:i], coords[i+1:]...), v, true
77 }
78 }
79 return coords, nodeCoordinates{}, false
80 }