github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/prometheus/stubmetrics_test.go (about) 1 // Copyright 2023 The Inspektor Gadget authors 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package prometheus 16 17 import ( 18 "context" 19 "fmt" 20 "sync" 21 "testing" 22 23 "go.opentelemetry.io/otel/attribute" 24 "go.opentelemetry.io/otel/metric" 25 "go.opentelemetry.io/otel/metric/embedded" 26 ) 27 28 func NewStubMeterProvider(t *testing.T) *stubMeterProvider { 29 return &stubMeterProvider{ 30 t: t, 31 meters: make(map[string]*stubMeter), 32 } 33 } 34 35 type stubMeterProvider struct { 36 embedded.MeterProvider 37 t *testing.T 38 meters map[string]*stubMeter 39 } 40 41 func (s *stubMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { 42 s.meters[name] = NewStubMeter(s.t) 43 return s.meters[name] 44 } 45 46 func NewStubMeter(t *testing.T) *stubMeter { 47 return &stubMeter{ 48 t: t, 49 int64counters: make(map[string]*stubInt64Counter), 50 float64counters: make(map[string]*stubFloat64Counter), 51 int64gauges: make(map[string]*stubInt64ObservableGauge), 52 float64gauges: make(map[string]*stubFloat64ObservableGauge), 53 int64histograms: make(map[string]*stubInt64Histogram), 54 float64histograms: make(map[string]*stubFloat64Histogram), 55 } 56 } 57 58 type stubMeter struct { 59 embedded.Meter 60 t *testing.T 61 62 int64counters map[string]*stubInt64Counter 63 float64counters map[string]*stubFloat64Counter 64 int64gauges map[string]*stubInt64ObservableGauge 65 float64gauges map[string]*stubFloat64ObservableGauge 66 int64histograms map[string]*stubInt64Histogram 67 float64histograms map[string]*stubFloat64Histogram 68 callbacks []metric.Callback 69 mu sync.Mutex 70 } 71 72 func (s *stubMeter) Int64Counter(name string, options ...metric.Int64CounterOption) (metric.Int64Counter, error) { 73 s.mu.Lock() 74 defer s.mu.Unlock() 75 76 c := &stubInt64Counter{ 77 values: make(map[string]int64), 78 } 79 s.int64counters[name] = c 80 return c, nil 81 } 82 83 func (s *stubMeter) Int64UpDownCounter(name string, options ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) { 84 return nil, nil 85 } 86 87 func (s *stubMeter) Int64Histogram(name string, options ...metric.Int64HistogramOption) (metric.Int64Histogram, error) { 88 s.mu.Lock() 89 defer s.mu.Unlock() 90 91 c := &stubInt64Histogram{ 92 values: make(map[string]int64), 93 } 94 s.int64histograms[name] = c 95 return c, nil 96 } 97 98 func (s *stubMeter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) { 99 return nil, nil 100 } 101 102 func (s *stubMeter) Int64ObservableUpDownCounter(name string, options ...metric.Int64ObservableUpDownCounterOption) (metric.Int64ObservableUpDownCounter, error) { 103 return nil, nil 104 } 105 106 func (s *stubMeter) Int64ObservableGauge(name string, options ...metric.Int64ObservableGaugeOption) (metric.Int64ObservableGauge, error) { 107 s.mu.Lock() 108 defer s.mu.Unlock() 109 110 c := &stubInt64ObservableGauge{ 111 values: make(map[string]int64), 112 } 113 s.int64gauges[name] = c 114 return c, nil 115 } 116 117 func (s *stubMeter) Float64Counter(name string, options ...metric.Float64CounterOption) (metric.Float64Counter, error) { 118 s.mu.Lock() 119 defer s.mu.Unlock() 120 121 c := &stubFloat64Counter{ 122 values: make(map[string]float64), 123 } 124 s.float64counters[name] = c 125 return c, nil 126 } 127 128 func (s *stubMeter) Float64UpDownCounter(name string, options ...metric.Float64UpDownCounterOption) (metric.Float64UpDownCounter, error) { 129 return nil, nil 130 } 131 132 func (s *stubMeter) Float64Histogram(name string, options ...metric.Float64HistogramOption) (metric.Float64Histogram, error) { 133 s.mu.Lock() 134 defer s.mu.Unlock() 135 136 c := &stubFloat64Histogram{ 137 values: make(map[string]float64), 138 } 139 s.float64histograms[name] = c 140 return c, nil 141 } 142 143 func (s *stubMeter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) { 144 return nil, nil 145 } 146 147 func (s *stubMeter) Float64ObservableUpDownCounter(name string, options ...metric.Float64ObservableUpDownCounterOption) (metric.Float64ObservableUpDownCounter, error) { 148 return nil, nil 149 } 150 151 func (s *stubMeter) Float64ObservableGauge(name string, options ...metric.Float64ObservableGaugeOption) (metric.Float64ObservableGauge, error) { 152 s.mu.Lock() 153 defer s.mu.Unlock() 154 155 c := &stubFloat64ObservableGauge{ 156 values: make(map[string]float64), 157 } 158 s.float64gauges[name] = c 159 return c, nil 160 } 161 162 type stubRegistration struct { 163 embedded.Registration 164 } 165 166 func (s *stubRegistration) Unregister() error { 167 return nil 168 } 169 170 func (s *stubMeter) RegisterCallback(callback metric.Callback, instruments ...metric.Observable) (metric.Registration, error) { 171 s.mu.Lock() 172 defer s.mu.Unlock() 173 174 s.callbacks = append(s.callbacks, callback) 175 176 return &stubRegistration{}, nil 177 } 178 179 // Collect all registered intruments. Only for testing purposes, not part of otel API. 180 func (s *stubMeter) Collect(ctx context.Context) error { 181 obs := &stubObserver{} 182 183 for _, callback := range s.callbacks { 184 callback(ctx, obs) 185 } 186 187 return nil 188 } 189 190 func attrsToString(kvs []attribute.KeyValue) string { 191 ret := "" 192 for _, kv := range kvs { 193 ret += fmt.Sprintf("%s=%s,", kv.Key, kv.Value.Emit()) 194 } 195 196 return ret 197 } 198 199 type stubInt64Counter struct { 200 embedded.Int64Counter 201 values map[string]int64 202 mu sync.Mutex 203 } 204 205 // Add records a change to the counter. 206 func (c *stubInt64Counter) Add(ctx context.Context, incr int64, options ...metric.AddOption) { 207 c.mu.Lock() 208 defer c.mu.Unlock() 209 210 attrs := metric.NewAddConfig(options).Attributes() 211 c.values[attrsToString(attrs.ToSlice())] += incr 212 } 213 214 type stubFloat64Counter struct { 215 embedded.Float64Counter 216 values map[string]float64 217 mu sync.Mutex 218 } 219 220 // Add records a change to the counter. 221 func (c *stubFloat64Counter) Add(ctx context.Context, incr float64, options ...metric.AddOption) { 222 c.mu.Lock() 223 defer c.mu.Unlock() 224 225 attrs := metric.NewAddConfig(options).Attributes() 226 c.values[attrsToString(attrs.ToSlice())] += incr 227 } 228 229 type stubInt64ObservableGauge struct { 230 embedded.Int64ObservableGauge 231 metric.Int64Observable 232 233 values map[string]int64 234 mu sync.Mutex 235 } 236 237 type stubFloat64ObservableGauge struct { 238 embedded.Float64ObservableGauge 239 metric.Float64Observable 240 241 values map[string]float64 242 mu sync.Mutex 243 } 244 245 type stubObserver struct { 246 embedded.Observer 247 } 248 249 func (o *stubObserver) ObserveFloat64(obsrv metric.Float64Observable, value float64, opts ...metric.ObserveOption) { 250 in, ok := obsrv.(*stubFloat64ObservableGauge) 251 if !ok { 252 panic("bad type passed in") 253 } 254 255 in.mu.Lock() 256 defer in.mu.Unlock() 257 258 attrs := metric.NewObserveConfig(opts).Attributes() 259 in.values[attrsToString(attrs.ToSlice())] = value 260 } 261 262 func (o *stubObserver) ObserveInt64(obsrv metric.Int64Observable, value int64, opts ...metric.ObserveOption) { 263 in, ok := obsrv.(*stubInt64ObservableGauge) 264 if !ok { 265 panic("bad type passed in") 266 } 267 268 in.mu.Lock() 269 defer in.mu.Unlock() 270 271 attrs := metric.NewObserveConfig(opts).Attributes() 272 in.values[attrsToString(attrs.ToSlice())] = value 273 } 274 275 type stubInt64Histogram struct { 276 embedded.Int64Histogram 277 values map[string]int64 278 mu sync.Mutex 279 } 280 281 // Record records a new measurement in the histogram. 282 func (h *stubInt64Histogram) Record(ctx context.Context, value int64, options ...metric.RecordOption) { 283 h.mu.Lock() 284 defer h.mu.Unlock() 285 286 attrs := metric.NewRecordConfig(options).Attributes() 287 h.values[attrsToString(attrs.ToSlice())] = value 288 } 289 290 type stubFloat64Histogram struct { 291 embedded.Float64Histogram 292 values map[string]float64 293 mu sync.Mutex 294 } 295 296 // Record records a new measurement in the histogram. 297 func (h *stubFloat64Histogram) Record(ctx context.Context, value float64, options ...metric.RecordOption) { 298 h.mu.Lock() 299 defer h.mu.Unlock() 300 301 attrs := metric.NewRecordConfig(options).Attributes() 302 h.values[attrsToString(attrs.ToSlice())] = value 303 }