Files

80 lines
2.0 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package tests
import (
"context"
"fmt"
"github.com/luxfi/metric"
"github.com/luxfi/node/service/metrics"
)
// "metric name" -> "metric value"
type NodeMetrics map[string]*metric.MetricFamily
// URI -> "metric name" -> "metric value"
type NodesMetrics map[string]NodeMetrics
// GetNodeMetrics retrieves the specified metrics the provided node URI.
func GetNodeMetrics(ctx context.Context, nodeURI string) (NodeMetrics, error) {
client := metrics.NewClient(nodeURI)
return client.GetMetrics(ctx)
}
// GetNodesMetrics retrieves the specified metrics for the provided node URIs.
func GetNodesMetrics(ctx context.Context, nodeURIs []string) (NodesMetrics, error) {
metrics := make(NodesMetrics, len(nodeURIs))
for _, u := range nodeURIs {
var err error
metrics[u], err = GetNodeMetrics(ctx, u)
if err != nil {
return nil, fmt.Errorf("failed to retrieve metrics for %s: %w", u, err)
}
}
return metrics, nil
}
// GetMetricValue returns the value of the specified metric which has the
// required labels.
//
// If multiple metrics match the provided labels, the first metric found is
// returned.
//
// Only Counter and Gauge metrics are supported.
func GetMetricValue(metrics NodeMetrics, name string, labels metric.Labels) (float64, bool) {
metricFamily, ok := metrics[name]
if !ok {
return 0, false
}
for _, m := range metricFamily.Metrics {
if !labelsMatch(m, labels) {
continue
}
// For counters and gauges, Value holds the current value
switch metricFamily.Type {
case metric.MetricTypeCounter, metric.MetricTypeGauge:
return m.Value.Value, true
}
}
return 0, false
}
func labelsMatch(m metric.Metric, labels metric.Labels) bool {
var found int
for _, label := range m.Labels {
expectedValue, ok := labels[label.Name]
if !ok {
continue
}
if label.Value != expectedValue {
return false
}
found++
}
return found == len(labels)
}