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  }