github.com/MetalBlockchain/metalgo@v1.11.9/tests/metrics.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package tests
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  
    12  	"github.com/MetalBlockchain/metalgo/api/metrics"
    13  
    14  	dto "github.com/prometheus/client_model/go"
    15  )
    16  
    17  // "metric name" -> "metric value"
    18  type NodeMetrics map[string]*dto.MetricFamily
    19  
    20  // URI -> "metric name" -> "metric value"
    21  type NodesMetrics map[string]NodeMetrics
    22  
    23  // GetNodeMetrics retrieves the specified metrics the provided node URI.
    24  func GetNodeMetrics(ctx context.Context, nodeURI string) (NodeMetrics, error) {
    25  	client := metrics.NewClient(nodeURI)
    26  	return client.GetMetrics(ctx)
    27  }
    28  
    29  // GetNodesMetrics retrieves the specified metrics for the provided node URIs.
    30  func GetNodesMetrics(ctx context.Context, nodeURIs []string) (NodesMetrics, error) {
    31  	metrics := make(NodesMetrics, len(nodeURIs))
    32  	for _, u := range nodeURIs {
    33  		var err error
    34  		metrics[u], err = GetNodeMetrics(ctx, u)
    35  		if err != nil {
    36  			return nil, fmt.Errorf("failed to retrieve metrics for %s: %w", u, err)
    37  		}
    38  	}
    39  	return metrics, nil
    40  }
    41  
    42  // GetMetricValue returns the value of the specified metric which has the
    43  // required labels.
    44  //
    45  // If multiple metrics match the provided labels, the first metric found is
    46  // returned.
    47  //
    48  // Only Counter and Gauge metrics are supported.
    49  func GetMetricValue(metrics NodeMetrics, name string, labels prometheus.Labels) (float64, bool) {
    50  	metricFamily, ok := metrics[name]
    51  	if !ok {
    52  		return 0, false
    53  	}
    54  
    55  	for _, metric := range metricFamily.Metric {
    56  		if !labelsMatch(metric, labels) {
    57  			continue
    58  		}
    59  
    60  		switch {
    61  		case metric.Gauge != nil:
    62  			return metric.Gauge.GetValue(), true
    63  		case metric.Counter != nil:
    64  			return metric.Counter.GetValue(), true
    65  		}
    66  	}
    67  	return 0, false
    68  }
    69  
    70  func labelsMatch(metric *dto.Metric, labels prometheus.Labels) bool {
    71  	var found int
    72  	for _, label := range metric.Label {
    73  		expectedValue, ok := labels[label.GetName()]
    74  		if !ok {
    75  			continue
    76  		}
    77  		if label.GetValue() != expectedValue {
    78  			return false
    79  		}
    80  		found++
    81  	}
    82  	return found == len(labels)
    83  }