github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/promutil/registry_test.go (about) 1 // Copyright 2022 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package promutil 15 16 import ( 17 "testing" 18 19 "github.com/prometheus/client_golang/prometheus" 20 "github.com/stretchr/testify/require" 21 ) 22 23 func TestNewRegistry(t *testing.T) { 24 t.Parallel() 25 26 reg := NewRegistry() 27 require.NotNil(t, reg.registry) 28 require.Len(t, reg.collectorByWorker, 0) 29 } 30 31 func TestGlobalMetric(t *testing.T) { 32 t.Parallel() 33 34 require.Len(t, globalMetricRegistry.collectorByWorker, 1) 35 require.Len(t, globalMetricRegistry.collectorByWorker[systemID], 2) 36 mfs, err := globalMetricGatherer.Gather() 37 require.NoError(t, err) 38 require.NotEmpty(t, mfs) 39 } 40 41 func TestMustRegister(t *testing.T) { 42 t.Parallel() 43 44 reg := NewRegistry() 45 require.NotNil(t, reg.registry) 46 47 // normal case, register successfully 48 reg.MustRegister("worker0", prometheus.NewCounter(prometheus.CounterOpts{ 49 Name: "counter1", 50 })) 51 reg.MustRegister("worker0", prometheus.NewCounter(prometheus.CounterOpts{ 52 Name: "counter2", 53 })) 54 reg.MustRegister("worker1", prometheus.NewCounter(prometheus.CounterOpts{ 55 Name: "counter3", 56 })) 57 require.Len(t, reg.collectorByWorker, 2) 58 require.Len(t, reg.collectorByWorker["worker0"], 2) 59 require.Len(t, reg.collectorByWorker["worker1"], 1) 60 61 // metrics name are same, but const labels value are different 62 reg.MustRegister("worker2", prometheus.NewCounter(prometheus.CounterOpts{ 63 Name: "counter4", 64 ConstLabels: prometheus.Labels{ 65 "k0": "v0", 66 }, 67 })) 68 reg.MustRegister("worker2", prometheus.NewCounter(prometheus.CounterOpts{ 69 Name: "counter4", 70 ConstLabels: prometheus.Labels{ 71 "k0": "v1", 72 }, 73 })) 74 require.Len(t, reg.collectorByWorker["worker2"], 2) 75 76 // metric name are different, but const lables are same 77 reg.MustRegister("worker3", prometheus.NewCounter(prometheus.CounterOpts{ 78 Name: "counter5", 79 ConstLabels: prometheus.Labels{ 80 "k0": "v0", 81 }, 82 })) 83 require.Len(t, reg.collectorByWorker["worker3"], 1) 84 85 // metric name + help + labels name are same, 86 reg.MustRegister("worker4", prometheus.NewCounterVec(prometheus.CounterOpts{ 87 Name: "counter6", 88 Help: "counter6 help", 89 ConstLabels: prometheus.Labels{ 90 "k0": "v0", 91 }, 92 }, []string{"label0", "label1"})) 93 reg.MustRegister("worker4", prometheus.NewCounterVec(prometheus.CounterOpts{ 94 Name: "counter6", 95 Help: "counter6 help", 96 ConstLabels: prometheus.Labels{ 97 "k0": "v3", 98 }, 99 }, []string{"label1", "label0"})) 100 require.Len(t, reg.collectorByWorker["worker4"], 2) 101 } 102 103 // prometheus metric name and label name only support [a-z][A-Z][0-9][_][:] 104 // label name can't have prefix '__' 105 func TestMustRegisterNotValidName(t *testing.T) { 106 t.Parallel() 107 108 defer func() { 109 err := recover() 110 require.NotNil(t, err) 111 require.Regexp(t, "not a valid metric name", err.(error).Error()) 112 }() 113 114 reg := NewRegistry() 115 require.NotNil(t, reg.registry) 116 117 // not a valid metric name 118 reg.MustRegister("worker", prometheus.NewCounter(prometheus.CounterOpts{ 119 Name: "counter-5", 120 })) 121 } 122 123 func TestMustRegisterNotValidLableName(t *testing.T) { 124 t.Parallel() 125 126 defer func() { 127 err := recover() 128 require.NotNil(t, err) 129 require.Regexp(t, "not a valid label name", err.(error).Error()) 130 }() 131 132 reg := NewRegistry() 133 require.NotNil(t, reg.registry) 134 135 // not a valid metric name 136 reg.MustRegister("worker", prometheus.NewCounter(prometheus.CounterOpts{ 137 Name: "counter5", 138 ConstLabels: prometheus.Labels{ 139 "__k0": "v3", 140 }, 141 })) 142 } 143 144 // metric name + const labels are duplicate 145 func TestMustRegisterFailDuplicateNameLabels(t *testing.T) { 146 t.Parallel() 147 148 defer func() { 149 err := recover() 150 require.NotNil(t, err) 151 require.Regexp(t, "duplicate metrics collector registration attempted", err.(error).Error()) 152 }() 153 154 reg := NewRegistry() 155 require.NotNil(t, reg.registry) 156 157 reg.MustRegister("worker", prometheus.NewCounter(prometheus.CounterOpts{ 158 Name: "counter5", 159 ConstLabels: prometheus.Labels{ 160 "k0": "v0", 161 }, 162 })) 163 reg.MustRegister("worker1", prometheus.NewCounter(prometheus.CounterOpts{ 164 Name: "counter5", 165 ConstLabels: prometheus.Labels{ 166 "k0": "v0", 167 }, 168 })) 169 } 170 171 // metric names are same, but help + labels name are inconsistent 172 func TestMustRegisterFailInconsistent(t *testing.T) { 173 t.Parallel() 174 175 defer func() { 176 err := recover() 177 require.NotNil(t, err) 178 require.Regexp(t, "a previously registered descriptor with the same fully-qualified name", err.(error).Error()) 179 }() 180 181 reg := NewRegistry() 182 require.NotNil(t, reg.registry) 183 184 reg.MustRegister("worker", prometheus.NewCounter(prometheus.CounterOpts{ 185 Name: "counter5", 186 ConstLabels: prometheus.Labels{ 187 "k0": "v0", 188 }, 189 })) 190 reg.MustRegister("worker1", prometheus.NewCounter(prometheus.CounterOpts{ 191 Name: "counter5", 192 ConstLabels: prometheus.Labels{ 193 "k1": "v0", 194 }, 195 })) 196 } 197 198 func TestUnregister(t *testing.T) { 199 t.Parallel() 200 201 reg := NewRegistry() 202 require.NotNil(t, reg.registry) 203 reg.MustRegister("worker0", prometheus.NewCounter(prometheus.CounterOpts{ 204 Name: "counter5", 205 ConstLabels: prometheus.Labels{ 206 "k0": "v0", 207 }, 208 })) 209 reg.MustRegister("worker0", prometheus.NewCounter(prometheus.CounterOpts{ 210 Name: "counter5", 211 ConstLabels: prometheus.Labels{ 212 "k0": "v1", 213 }, 214 })) 215 reg.MustRegister("worker1", prometheus.NewCounter(prometheus.CounterOpts{ 216 Name: "counter6", 217 ConstLabels: prometheus.Labels{ 218 "k0": "v1", 219 }, 220 })) 221 require.Len(t, reg.collectorByWorker, 2) 222 require.Len(t, reg.collectorByWorker["worker0"], 2) 223 require.Len(t, reg.collectorByWorker["worker1"], 1) 224 225 reg.Unregister("worker0") 226 require.Len(t, reg.collectorByWorker, 1) 227 require.Len(t, reg.collectorByWorker["worker0"], 0) 228 229 // re-register the same metric to check if it's unregister successfully 230 reg.MustRegister("worker0", prometheus.NewCounter(prometheus.CounterOpts{ 231 Name: "counter5", 232 ConstLabels: prometheus.Labels{ 233 "k0": "v0", 234 }, 235 })) 236 require.Len(t, reg.collectorByWorker, 2) 237 }