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  }