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

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package metrics
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"slices"
    10  
    11  	"github.com/prometheus/client_golang/prometheus"
    12  
    13  	dto "github.com/prometheus/client_model/go"
    14  )
    15  
    16  var (
    17  	_ MultiGatherer = (*prefixGatherer)(nil)
    18  
    19  	errDuplicateGatherer = errors.New("attempt to register duplicate gatherer")
    20  )
    21  
    22  // NewLabelGatherer returns a new MultiGatherer that merges metrics by adding a
    23  // new label.
    24  func NewLabelGatherer(labelName string) MultiGatherer {
    25  	return &labelGatherer{
    26  		labelName: labelName,
    27  	}
    28  }
    29  
    30  type labelGatherer struct {
    31  	multiGatherer
    32  
    33  	labelName string
    34  }
    35  
    36  func (g *labelGatherer) Register(labelValue string, gatherer prometheus.Gatherer) error {
    37  	g.lock.Lock()
    38  	defer g.lock.Unlock()
    39  
    40  	if slices.Contains(g.names, labelValue) {
    41  		return fmt.Errorf("%w: for %q with label %q",
    42  			errDuplicateGatherer,
    43  			g.labelName,
    44  			labelValue,
    45  		)
    46  	}
    47  
    48  	g.names = append(g.names, labelValue)
    49  	g.gatherers = append(g.gatherers, &labeledGatherer{
    50  		labelName:  g.labelName,
    51  		labelValue: labelValue,
    52  		gatherer:   gatherer,
    53  	})
    54  	return nil
    55  }
    56  
    57  type labeledGatherer struct {
    58  	labelName  string
    59  	labelValue string
    60  	gatherer   prometheus.Gatherer
    61  }
    62  
    63  func (g *labeledGatherer) Gather() ([]*dto.MetricFamily, error) {
    64  	// Gather returns partially filled metrics in the case of an error. So, it
    65  	// is expected to still return the metrics in the case an error is returned.
    66  	metricFamilies, err := g.gatherer.Gather()
    67  	for _, metricFamily := range metricFamilies {
    68  		for _, metric := range metricFamily.Metric {
    69  			metric.Label = append(metric.Label, &dto.LabelPair{
    70  				Name:  &g.labelName,
    71  				Value: &g.labelValue,
    72  			})
    73  		}
    74  	}
    75  	return metricFamilies, err
    76  }