github.com/MetalBlockchain/metalgo@v1.11.9/api/metrics/prefix_gatherer_test.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 "testing" 8 9 "github.com/prometheus/client_golang/prometheus" 10 "github.com/stretchr/testify/require" 11 "google.golang.org/protobuf/proto" 12 13 dto "github.com/prometheus/client_model/go" 14 ) 15 16 func TestPrefixGatherer_Gather(t *testing.T) { 17 require := require.New(t) 18 19 gatherer := NewPrefixGatherer() 20 require.NotNil(gatherer) 21 22 registerA := prometheus.NewRegistry() 23 require.NoError(gatherer.Register("a", registerA)) 24 { 25 counterA := prometheus.NewCounter(counterOpts) 26 require.NoError(registerA.Register(counterA)) 27 } 28 29 registerB := prometheus.NewRegistry() 30 require.NoError(gatherer.Register("b", registerB)) 31 { 32 counterB := prometheus.NewCounter(counterOpts) 33 counterB.Inc() 34 require.NoError(registerB.Register(counterB)) 35 } 36 37 metrics, err := gatherer.Gather() 38 require.NoError(err) 39 require.Equal( 40 []*dto.MetricFamily{ 41 { 42 Name: proto.String("a_counter"), 43 Help: proto.String(counterOpts.Help), 44 Type: dto.MetricType_COUNTER.Enum(), 45 Metric: []*dto.Metric{ 46 { 47 Label: []*dto.LabelPair{}, 48 Counter: &dto.Counter{ 49 Value: proto.Float64(0), 50 }, 51 }, 52 }, 53 }, 54 { 55 Name: proto.String("b_counter"), 56 Help: proto.String(counterOpts.Help), 57 Type: dto.MetricType_COUNTER.Enum(), 58 Metric: []*dto.Metric{ 59 { 60 Label: []*dto.LabelPair{}, 61 Counter: &dto.Counter{ 62 Value: proto.Float64(1), 63 }, 64 }, 65 }, 66 }, 67 }, 68 metrics, 69 ) 70 } 71 72 func TestPrefixGatherer_Register(t *testing.T) { 73 firstPrefixedGatherer := &prefixedGatherer{ 74 prefix: "first", 75 gatherer: &testGatherer{}, 76 } 77 firstPrefixGatherer := func() *prefixGatherer { 78 return &prefixGatherer{ 79 multiGatherer: multiGatherer{ 80 names: []string{ 81 firstPrefixedGatherer.prefix, 82 }, 83 gatherers: prometheus.Gatherers{ 84 firstPrefixedGatherer, 85 }, 86 }, 87 } 88 } 89 secondPrefixedGatherer := &prefixedGatherer{ 90 prefix: "second", 91 gatherer: &testGatherer{ 92 mfs: []*dto.MetricFamily{{}}, 93 }, 94 } 95 secondPrefixGatherer := &prefixGatherer{ 96 multiGatherer: multiGatherer{ 97 names: []string{ 98 firstPrefixedGatherer.prefix, 99 secondPrefixedGatherer.prefix, 100 }, 101 gatherers: prometheus.Gatherers{ 102 firstPrefixedGatherer, 103 secondPrefixedGatherer, 104 }, 105 }, 106 } 107 108 tests := []struct { 109 name string 110 prefixGatherer *prefixGatherer 111 prefix string 112 gatherer prometheus.Gatherer 113 expectedErr error 114 expectedPrefixGatherer *prefixGatherer 115 }{ 116 { 117 name: "first registration", 118 prefixGatherer: &prefixGatherer{}, 119 prefix: firstPrefixedGatherer.prefix, 120 gatherer: firstPrefixedGatherer.gatherer, 121 expectedErr: nil, 122 expectedPrefixGatherer: firstPrefixGatherer(), 123 }, 124 { 125 name: "second registration", 126 prefixGatherer: firstPrefixGatherer(), 127 prefix: secondPrefixedGatherer.prefix, 128 gatherer: secondPrefixedGatherer.gatherer, 129 expectedErr: nil, 130 expectedPrefixGatherer: secondPrefixGatherer, 131 }, 132 { 133 name: "conflicts with previous registration", 134 prefixGatherer: firstPrefixGatherer(), 135 prefix: firstPrefixedGatherer.prefix, 136 gatherer: secondPrefixedGatherer.gatherer, 137 expectedErr: errOverlappingNamespaces, 138 expectedPrefixGatherer: firstPrefixGatherer(), 139 }, 140 } 141 for _, test := range tests { 142 t.Run(test.name, func(t *testing.T) { 143 require := require.New(t) 144 145 err := test.prefixGatherer.Register(test.prefix, test.gatherer) 146 require.ErrorIs(err, test.expectedErr) 147 require.Equal(test.expectedPrefixGatherer, test.prefixGatherer) 148 }) 149 } 150 } 151 152 func TestEitherIsPrefix(t *testing.T) { 153 tests := []struct { 154 name string 155 a string 156 b string 157 expected bool 158 }{ 159 { 160 name: "empty strings", 161 a: "", 162 b: "", 163 expected: true, 164 }, 165 { 166 name: "an empty string", 167 a: "", 168 b: "hello", 169 expected: true, 170 }, 171 { 172 name: "same strings", 173 a: "x", 174 b: "x", 175 expected: true, 176 }, 177 { 178 name: "different strings", 179 a: "x", 180 b: "y", 181 expected: false, 182 }, 183 { 184 name: "splits namespace", 185 a: "hello", 186 b: "hello_world", 187 expected: true, 188 }, 189 { 190 name: "is prefix before separator", 191 a: "hello", 192 b: "helloworld", 193 expected: false, 194 }, 195 } 196 for _, test := range tests { 197 t.Run(test.name, func(t *testing.T) { 198 require := require.New(t) 199 200 require.Equal(test.expected, eitherIsPrefix(test.a, test.b)) 201 require.Equal(test.expected, eitherIsPrefix(test.b, test.a)) 202 }) 203 } 204 }