summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/consul/collect_net_rtt.go
blob: 1b1853719d15749d46e76696e6ecbb60f0b5fb34 (plain)
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
}