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