netdata/netdata

View on GitHub
src/go/collectors/go.d.plugin/modules/consul/collect_net_rtt.go

Summary

Maintainability
A
0 mins
Test Coverage
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
}