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 }