github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/prometheus/prometheus_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  	"time"
    23  
    24  	"github.com/stretchr/testify/require"
    25  
    26  	"github.com/inspektor-gadget/inspektor-gadget/pkg/prometheus/config"
    27  )
    28  
    29  // events that are generated in the test. Counters are incremented based on them and the metric
    30  // configuration
    31  var testEvents = []*stubEvent{
    32  	{Comm: "cat", Uid: 0, IntVal: 105, FloatVal: 201.2},
    33  	{Comm: "cat", Uid: 0, IntVal: 216, FloatVal: 423.3},
    34  	{Comm: "cat", Uid: 1000, IntVal: 327, FloatVal: 645.4},
    35  	{Comm: "ping", Uid: 0, IntVal: 428, FloatVal: 867.5},
    36  	{Comm: "ls", Uid: 1000, IntVal: 429, FloatVal: 1089.6},
    37  }
    38  
    39  func TestMetrics(t *testing.T) {
    40  	type testDefinition struct {
    41  		name        string
    42  		config      *config.Config
    43  		expectedErr bool
    44  
    45  		// outer key: metric name, inner key: attributes hash
    46  		expectedInt64Counters     map[string]map[string]int64
    47  		expectedFloat64Counters   map[string]map[string]float64
    48  		expectedInt64Gauges       map[string]map[string]int64
    49  		expectedFloat64Gauges     map[string]map[string]float64
    50  		expectedInt64Histograms   map[string]map[string]int64
    51  		expectedFloat64Histograms map[string]map[string]float64
    52  	}
    53  
    54  	tests := []testDefinition{
    55  		// Generic checks before
    56  		{
    57  			name: "wrong_metric_type",
    58  			config: &config.Config{
    59  				MetricsName: "wrong_metric_type",
    60  				Metrics: []config.Metric{
    61  					{
    62  						Name:     "wrong_metric_type",
    63  						Type:     "nonvalidtype",
    64  						Category: "trace",
    65  						Gadget:   "stubtracer",
    66  					},
    67  				},
    68  			},
    69  			expectedErr: true,
    70  		},
    71  		// Wrong configurations
    72  		{
    73  			name: "counter_wrong_gadget_name",
    74  			config: &config.Config{
    75  				MetricsName: "counter_wrong_gadget_name",
    76  				Metrics: []config.Metric{
    77  					{
    78  						Name:     "counter_wrong_gadget_name",
    79  						Type:     "counter",
    80  						Category: "trace",
    81  						Gadget:   "nonexisting",
    82  					},
    83  				},
    84  			},
    85  			expectedErr: true,
    86  		},
    87  		{
    88  			name: "counter_wrong_gadget_category",
    89  			config: &config.Config{
    90  				MetricsName: "counter_wrong_gadget_category",
    91  				Metrics: []config.Metric{
    92  					{
    93  						Name:     "counter_wrong_gadget_category",
    94  						Type:     "counter",
    95  						Category: "nonexisting",
    96  						Gadget:   "stubtracer",
    97  					},
    98  				},
    99  			},
   100  			expectedErr: true,
   101  		},
   102  		{
   103  			name: "counter_wrong_gadget_type",
   104  			config: &config.Config{
   105  				MetricsName: "counter_wrong_gadget_type",
   106  				Metrics: []config.Metric{
   107  					{
   108  						Name:     "counter_wrong_gadget_type",
   109  						Type:     "counter",
   110  						Category: "snapshot",
   111  						Gadget:   "stubsnapshotter",
   112  					},
   113  				},
   114  			},
   115  			expectedErr: true,
   116  		},
   117  		{
   118  			name: "counter_wrong_type_field",
   119  			config: &config.Config{
   120  				MetricsName: "counter_wrong_type_field",
   121  				Metrics: []config.Metric{
   122  					{
   123  						Name:     "counter_wrong_type_field",
   124  						Type:     "counter",
   125  						Category: "trace",
   126  						Gadget:   "stubtracer",
   127  						Field:    "comm",
   128  					},
   129  				},
   130  			},
   131  			expectedErr: true,
   132  		},
   133  		{
   134  			name: "counter_wrong_selector",
   135  			config: &config.Config{
   136  				MetricsName: "counter_wrong_selector",
   137  				Metrics: []config.Metric{
   138  					{
   139  						Name:     "counter_wrong_selector",
   140  						Type:     "counter",
   141  						Category: "trace",
   142  						Gadget:   "stubtracer",
   143  						Field:    "comm",
   144  						Selector: []string{"wrong:cat"},
   145  					},
   146  				},
   147  			},
   148  			expectedErr: true,
   149  		},
   150  		{
   151  			name: "counter_wrong_labels",
   152  			config: &config.Config{
   153  				MetricsName: "counter_wrong_labels",
   154  				Metrics: []config.Metric{
   155  					{
   156  						Name:     "counter_wrong_labels",
   157  						Type:     "counter",
   158  						Category: "trace",
   159  						Gadget:   "stubtracer",
   160  						Labels:   []string{"wrong"},
   161  					},
   162  				},
   163  			},
   164  			expectedErr: true,
   165  		},
   166  		// Check that counters are updated correctly
   167  		{
   168  			name: "counter_no_labels_nor_filtering",
   169  			config: &config.Config{
   170  				MetricsName: "counter_no_labels_nor_filtering",
   171  				Metrics: []config.Metric{
   172  					{
   173  						Name:     "counter_no_labels_nor_filtering",
   174  						Type:     "counter",
   175  						Category: "trace",
   176  						Gadget:   "stubtracer",
   177  					},
   178  				},
   179  			},
   180  			expectedInt64Counters: map[string]map[string]int64{
   181  				"counter_no_labels_nor_filtering": {"": 5},
   182  			},
   183  		},
   184  		{
   185  			name: "counter_filter_only_root_events",
   186  			config: &config.Config{
   187  				MetricsName: "counter_filter_only_root_events",
   188  				Metrics: []config.Metric{
   189  					{
   190  						Name:     "counter_filter_only_root_events",
   191  						Type:     "counter",
   192  						Category: "trace",
   193  						Gadget:   "stubtracer",
   194  						Selector: []string{"uid:0"},
   195  					},
   196  				},
   197  			},
   198  			expectedInt64Counters: map[string]map[string]int64{
   199  				"counter_filter_only_root_events": {"": 3},
   200  			},
   201  		},
   202  		{
   203  			name: "counter_filter_only_root_cat_events",
   204  			config: &config.Config{
   205  				MetricsName: "counter_filter_only_root_cat_events",
   206  				Metrics: []config.Metric{
   207  					{
   208  						Name:     "counter_filter_only_root_cat_events",
   209  						Type:     "counter",
   210  						Category: "trace",
   211  						Gadget:   "stubtracer",
   212  						Selector: []string{"uid:0", "comm:cat"},
   213  					},
   214  				},
   215  			},
   216  			expectedInt64Counters: map[string]map[string]int64{
   217  				"counter_filter_only_root_cat_events": {"": 2},
   218  			},
   219  		},
   220  		{
   221  			name: "counter_filter_uid_greater_than_0",
   222  			config: &config.Config{
   223  				MetricsName: "counter_filter_uid_greater_than_0",
   224  				Metrics: []config.Metric{
   225  					{
   226  						Name:     "counter_filter_uid_greater_than_0",
   227  						Type:     "counter",
   228  						Category: "trace",
   229  						Gadget:   "stubtracer",
   230  						Selector: []string{"uid:>0"},
   231  					},
   232  				},
   233  			},
   234  			expectedInt64Counters: map[string]map[string]int64{
   235  				"counter_filter_uid_greater_than_0": {"": 2},
   236  			},
   237  		},
   238  		{
   239  			name: "counter_aggregate_by_comm",
   240  			config: &config.Config{
   241  				MetricsName: "counter_aggregate_by_comm",
   242  				Metrics: []config.Metric{
   243  					{
   244  						Name:     "counter_aggregate_by_comm",
   245  						Type:     "counter",
   246  						Category: "trace",
   247  						Gadget:   "stubtracer",
   248  						Labels:   []string{"comm"},
   249  					},
   250  				},
   251  			},
   252  			expectedInt64Counters: map[string]map[string]int64{
   253  				"counter_aggregate_by_comm": {"comm=cat,": 3, "comm=ping,": 1, "comm=ls,": 1},
   254  			},
   255  		},
   256  		{
   257  			name: "counter_aggregate_by_uid",
   258  			config: &config.Config{
   259  				MetricsName: "counter_aggregate_by_uid",
   260  				Metrics: []config.Metric{
   261  					{
   262  						Name:     "counter_aggregate_by_uid",
   263  						Type:     "counter",
   264  						Category: "trace",
   265  						Gadget:   "stubtracer",
   266  						Labels:   []string{"uid"},
   267  					},
   268  				},
   269  			},
   270  			expectedInt64Counters: map[string]map[string]int64{
   271  				"counter_aggregate_by_uid": {"uid=0,": 3, "uid=1000,": 2},
   272  			},
   273  		},
   274  		{
   275  			name: "counter_aggregate_by_uid_and_comm",
   276  			config: &config.Config{
   277  				MetricsName: "counter_aggregate_by_uid_and_comm",
   278  				Metrics: []config.Metric{
   279  					{
   280  						Name:     "counter_aggregate_by_uid_and_comm",
   281  						Type:     "counter",
   282  						Category: "trace",
   283  						Gadget:   "stubtracer",
   284  						Labels:   []string{"uid", "comm"},
   285  					},
   286  				},
   287  			},
   288  			expectedInt64Counters: map[string]map[string]int64{
   289  				"counter_aggregate_by_uid_and_comm": {
   290  					"comm=cat,uid=0,":    2,
   291  					"comm=cat,uid=1000,": 1,
   292  					"comm=ping,uid=0,":   1,
   293  					"comm=ls,uid=1000,":  1,
   294  				},
   295  			},
   296  		},
   297  		{
   298  			name: "counter_aggregate_by_uid_and_filter_by_comm",
   299  			config: &config.Config{
   300  				MetricsName: "counter_aggregate_by_uid_and_filter_by_comm",
   301  				Metrics: []config.Metric{
   302  					{
   303  						Name:     "counter_aggregate_by_uid_and_filter_by_comm",
   304  						Type:     "counter",
   305  						Category: "trace",
   306  						Gadget:   "stubtracer",
   307  						Selector: []string{"comm:cat"},
   308  						Labels:   []string{"uid"},
   309  					},
   310  				},
   311  			},
   312  			expectedInt64Counters: map[string]map[string]int64{
   313  				"counter_aggregate_by_uid_and_filter_by_comm": {"uid=0,": 2, "uid=1000,": 1},
   314  			},
   315  		},
   316  		{
   317  			name: "counter_with_int_field",
   318  			config: &config.Config{
   319  				MetricsName: "counter_with_int_field",
   320  				Metrics: []config.Metric{
   321  					{
   322  						Name:     "counter_with_int_field",
   323  						Type:     "counter",
   324  						Category: "trace",
   325  						Gadget:   "stubtracer",
   326  						Field:    "intval",
   327  					},
   328  				},
   329  			},
   330  			expectedInt64Counters: map[string]map[string]int64{
   331  				"counter_with_int_field": {"": 105 + 216 + 327 + 428 + 429},
   332  			},
   333  		},
   334  		{
   335  			name: "counter_with_float_field",
   336  			config: &config.Config{
   337  				MetricsName: "counter_with_float_field",
   338  				Metrics: []config.Metric{
   339  					{
   340  						Name:     "counter_with_float_field",
   341  						Type:     "counter",
   342  						Category: "trace",
   343  						Gadget:   "stubtracer",
   344  						Field:    "floatval",
   345  					},
   346  				},
   347  			},
   348  			expectedFloat64Counters: map[string]map[string]float64{
   349  				"counter_with_float_field": {"": 201.2 + 423.3 + 645.4 + 867.5 + 1089.6},
   350  			},
   351  		},
   352  		{
   353  			name: "counter_with_float_field_aggregate_by_uid_and_filter_by_comm",
   354  			config: &config.Config{
   355  				MetricsName: "counter_with_float_field_aggregate_by_uid_and_filter_by_comm",
   356  				Metrics: []config.Metric{
   357  					{
   358  						Name:     "counter_with_float_field_aggregate_by_uid_and_filter_by_comm",
   359  						Type:     "counter",
   360  						Category: "trace",
   361  						Gadget:   "stubtracer",
   362  						Field:    "floatval",
   363  						Selector: []string{"comm:cat"},
   364  						Labels:   []string{"uid"},
   365  					},
   366  				},
   367  			},
   368  			expectedFloat64Counters: map[string]map[string]float64{
   369  				"counter_with_float_field_aggregate_by_uid_and_filter_by_comm": {"uid=0,": 201.2 + 423.3, "uid=1000,": 645.4},
   370  			},
   371  		},
   372  		// Multiple counters
   373  		{
   374  			name: "counter_multiple_mixed",
   375  			config: &config.Config{
   376  				MetricsName: "counter_multiple_mixed",
   377  				Metrics: []config.Metric{
   378  					{
   379  						Name:     "counter_multiple1",
   380  						Type:     "counter",
   381  						Category: "trace",
   382  						Gadget:   "stubtracer",
   383  						Field:    "floatval",
   384  					},
   385  					{
   386  						Name:     "counter_multiple2",
   387  						Type:     "counter",
   388  						Category: "trace",
   389  						Gadget:   "stubtracer",
   390  					},
   391  				},
   392  			},
   393  			expectedInt64Counters: map[string]map[string]int64{
   394  				"counter_multiple2": {"": 5},
   395  			},
   396  			expectedFloat64Counters: map[string]map[string]float64{
   397  				"counter_multiple1": {"": 201.2 + 423.3 + 645.4 + 867.5 + 1089.6},
   398  			},
   399  		},
   400  		// Gauges
   401  		{
   402  			name: "gauge_wrong_gadget_name",
   403  			config: &config.Config{
   404  				MetricsName: "gauge_wrong_gadget_name",
   405  				Metrics: []config.Metric{
   406  					{
   407  						Name:     "gauge_wrong_gadget_name",
   408  						Type:     "gauge",
   409  						Category: "snapshot",
   410  						Gadget:   "nonexisting",
   411  					},
   412  				},
   413  			},
   414  			expectedErr: true,
   415  		},
   416  		{
   417  			name: "gauge_wrong_gadget_category",
   418  			config: &config.Config{
   419  				MetricsName: "gauge_wrong_gadget_category",
   420  				Metrics: []config.Metric{
   421  					{
   422  						Name:     "gauge_wrong_gadget_category",
   423  						Type:     "gauge",
   424  						Category: "nonexisting",
   425  						Gadget:   "stubsnapshotter",
   426  					},
   427  				},
   428  			},
   429  			expectedErr: true,
   430  		},
   431  		{
   432  			name: "gauge_wrong_gadget_type",
   433  			config: &config.Config{
   434  				MetricsName: "gauge_wrong_gadget_type",
   435  				Metrics: []config.Metric{
   436  					{
   437  						Name:     "counter_wrong_gadget_type",
   438  						Type:     "gauge",
   439  						Category: "tracer",
   440  						Gadget:   "stubtracer",
   441  					},
   442  				},
   443  			},
   444  			expectedErr: true,
   445  		},
   446  		{
   447  			name: "gauge_no_labels_nor_filtering",
   448  			config: &config.Config{
   449  				MetricsName: "gauge_no_labels_nor_filtering",
   450  				Metrics: []config.Metric{
   451  					{
   452  						Name:     "gauge_no_labels_nor_filtering",
   453  						Type:     "gauge",
   454  						Category: "snapshot",
   455  						Gadget:   "stubsnapshotter",
   456  					},
   457  				},
   458  			},
   459  			expectedInt64Gauges: map[string]map[string]int64{
   460  				"gauge_no_labels_nor_filtering": {"": 5},
   461  			},
   462  		},
   463  		{
   464  			name: "gauge_filter_only_root_events",
   465  			config: &config.Config{
   466  				MetricsName: "gauge_filter_only_root_events",
   467  				Metrics: []config.Metric{
   468  					{
   469  						Name:     "gauge_filter_only_root_events",
   470  						Type:     "gauge",
   471  						Category: "snapshot",
   472  						Gadget:   "stubsnapshotter",
   473  						Selector: []string{"uid:0"},
   474  					},
   475  				},
   476  			},
   477  			expectedInt64Gauges: map[string]map[string]int64{
   478  				"gauge_filter_only_root_events": {"": 3},
   479  			},
   480  		},
   481  		{
   482  			name: "gauge_filter_only_root_cat_events",
   483  			config: &config.Config{
   484  				MetricsName: "gauge_filter_only_root_cat_events",
   485  				Metrics: []config.Metric{
   486  					{
   487  						Name:     "gauge_filter_only_root_cat_events",
   488  						Type:     "gauge",
   489  						Category: "snapshot",
   490  						Gadget:   "stubsnapshotter",
   491  						Selector: []string{"uid:0", "comm:cat"},
   492  					},
   493  				},
   494  			},
   495  			expectedInt64Gauges: map[string]map[string]int64{
   496  				"gauge_filter_only_root_cat_events": {"": 2},
   497  			},
   498  		},
   499  		{
   500  			name: "gauge_with_int_field",
   501  			config: &config.Config{
   502  				MetricsName: "gauge_with_int_field",
   503  				Metrics: []config.Metric{
   504  					{
   505  						Name:     "gauge_with_int_field",
   506  						Type:     "gauge",
   507  						Category: "snapshot",
   508  						Gadget:   "stubsnapshotter",
   509  						Field:    "intval",
   510  					},
   511  				},
   512  			},
   513  			expectedInt64Gauges: map[string]map[string]int64{
   514  				"gauge_with_int_field": {"": 105 + 216 + 327 + 428 + 429},
   515  			},
   516  		},
   517  		{
   518  			name: "gauge_with_float_field",
   519  			config: &config.Config{
   520  				MetricsName: "gauge_with_float_field",
   521  				Metrics: []config.Metric{
   522  					{
   523  						Name:     "gauge_with_float_field",
   524  						Type:     "gauge",
   525  						Category: "snapshot",
   526  						Gadget:   "stubsnapshotter",
   527  						Field:    "floatval",
   528  					},
   529  				},
   530  			},
   531  			expectedFloat64Gauges: map[string]map[string]float64{
   532  				"gauge_with_float_field": {"": 201.2 + 423.3 + 645.4 + 867.5 + 1089.6},
   533  			},
   534  		},
   535  		{
   536  			name: "gauge_multiple",
   537  			config: &config.Config{
   538  				MetricsName: "gauge_multiple",
   539  				Metrics: []config.Metric{
   540  					{
   541  						Name:     "gauge_no_labels_nor_filtering",
   542  						Type:     "gauge",
   543  						Category: "snapshot",
   544  						Gadget:   "stubsnapshotter",
   545  					},
   546  					{
   547  						Name:     "gauge_filter_only_root_events",
   548  						Type:     "gauge",
   549  						Category: "snapshot",
   550  						Gadget:   "stubsnapshotter",
   551  						Selector: []string{"uid:0"},
   552  					},
   553  				},
   554  			},
   555  			expectedInt64Gauges: map[string]map[string]int64{
   556  				"gauge_no_labels_nor_filtering": {"": 5},
   557  				"gauge_filter_only_root_events": {"": 3},
   558  			},
   559  		},
   560  		{
   561  			name: "histogram_missing_bucket_config",
   562  			config: &config.Config{
   563  				MetricsName: "histogram_missing_bucket_config",
   564  				Metrics: []config.Metric{
   565  					{
   566  						Name:     "histogram_missing_bucket_config",
   567  						Type:     "histogram",
   568  						Category: "trace",
   569  						Gadget:   "stubtracer",
   570  						Field:    "intval",
   571  					},
   572  				},
   573  			},
   574  			expectedErr: true,
   575  		},
   576  		{
   577  			name: "histrogram_invalid_bucket_config",
   578  			config: &config.Config{
   579  				MetricsName: "histrogram_invalid_bucket_config",
   580  				Metrics: []config.Metric{
   581  					{
   582  						Name:     "histrogram_invalid_bucket_config",
   583  						Type:     "histogram",
   584  						Category: "trace",
   585  						Gadget:   "stubtracer",
   586  						Field:    "intval",
   587  						Bucket: config.Bucket{
   588  							Type:       "invalid",
   589  							Max:        1,
   590  							Multiplier: 10,
   591  						},
   592  					},
   593  				},
   594  			},
   595  			expectedErr: true,
   596  		},
   597  		{
   598  			name: "histogram_int_field",
   599  			config: &config.Config{
   600  				MetricsName: "histogram_int_field",
   601  				Metrics: []config.Metric{
   602  					{
   603  						Name:     "histogram_int_field",
   604  						Type:     "histogram",
   605  						Category: "trace",
   606  						Gadget:   "stubtracer",
   607  						Field:    "intval",
   608  						Selector: []string{"uid:1000", "comm:cat"},
   609  						Bucket: config.Bucket{
   610  							Type:       "linear",
   611  							Max:        5,
   612  							Min:        0,
   613  							Multiplier: 1,
   614  						},
   615  					},
   616  				},
   617  			},
   618  			expectedInt64Histograms: map[string]map[string]int64{
   619  				"histogram_int_field": {"": 327},
   620  			},
   621  		},
   622  		{
   623  			name: "histogram_float_field",
   624  			config: &config.Config{
   625  				MetricsName: "histogram_float_field",
   626  				Metrics: []config.Metric{
   627  					{
   628  						Name:     "histogram_float_field",
   629  						Type:     "histogram",
   630  						Category: "trace",
   631  						Gadget:   "stubtracer",
   632  						Field:    "floatval",
   633  						Selector: []string{"uid:1000", "comm:cat"},
   634  						Bucket: config.Bucket{
   635  							Type:       "linear",
   636  							Max:        5,
   637  							Min:        0,
   638  							Multiplier: 1,
   639  						},
   640  					},
   641  				},
   642  			},
   643  			expectedFloat64Histograms: map[string]map[string]float64{
   644  				"histogram_float_field": {"": 645.4},
   645  			},
   646  		},
   647  		{
   648  			name: "histogram_multiple",
   649  			config: &config.Config{
   650  				MetricsName: "histogram_multiple",
   651  				Metrics: []config.Metric{
   652  					{
   653  						Name:     "histogram_int_field",
   654  						Type:     "histogram",
   655  						Category: "trace",
   656  						Gadget:   "stubtracer",
   657  						Field:    "intval",
   658  						Selector: []string{"uid:1000", "comm:cat"},
   659  						Bucket: config.Bucket{
   660  							Type:       "linear",
   661  							Max:        5,
   662  							Multiplier: 1,
   663  						},
   664  					},
   665  					{
   666  						Name:     "histogram_float_field",
   667  						Type:     "histogram",
   668  						Category: "trace",
   669  						Gadget:   "stubtracer",
   670  						Field:    "floatval",
   671  						Selector: []string{"uid:1000", "comm:cat"},
   672  						Bucket: config.Bucket{
   673  							Type:       "linear",
   674  							Max:        5,
   675  							Multiplier: 1,
   676  						},
   677  					},
   678  				},
   679  			},
   680  			expectedFloat64Histograms: map[string]map[string]float64{
   681  				"histogram_float_field": {"": 645.4},
   682  			},
   683  			expectedInt64Histograms: map[string]map[string]int64{
   684  				"histogram_int_field": {"": 327},
   685  			},
   686  		},
   687  	}
   688  
   689  	for _, test := range tests {
   690  		test := test
   691  		t.Run(test.name, func(t *testing.T) {
   692  			t.Parallel()
   693  
   694  			ctx, cancel := context.WithCancel(context.Background())
   695  			t.Cleanup(cancel)
   696  
   697  			wg := &sync.WaitGroup{}
   698  			wg.Add(len(test.config.Metrics))
   699  			ctx = context.WithValue(ctx, valuekey, wg)
   700  
   701  			test.config.MetricsName = test.name
   702  
   703  			meterProvider := NewStubMeterProvider(t)
   704  
   705  			cleanup, err := CreateMetrics(ctx, test.config, meterProvider)
   706  			if test.expectedErr {
   707  				require.Error(t, err)
   708  				return
   709  			}
   710  			require.Nil(t, err)
   711  			t.Cleanup(cleanup)
   712  
   713  			name := fmt.Sprintf("gadgets.inspektor-gadget.io/%s", test.config.MetricsName)
   714  			meter := meterProvider.meters[name]
   715  
   716  			require.Equal(t, len(test.expectedInt64Counters), len(meter.int64counters))
   717  			require.Equal(t, len(test.expectedFloat64Counters), len(meter.float64counters))
   718  			require.Equal(t, len(test.expectedInt64Gauges), len(meter.int64gauges))
   719  			require.Equal(t, len(test.expectedInt64Histograms), len(meter.int64histograms))
   720  			require.Equal(t, len(test.expectedFloat64Histograms), len(meter.float64histograms))
   721  
   722  			// Collect metrics: Update gauges
   723  			err = meter.Collect(ctx)
   724  			require.Nil(t, err, "failed to collect metrics")
   725  
   726  			// wait for the tracers to run
   727  			err = waitTimeout(wg, 5*time.Second)
   728  			require.Nil(t, err, "waiting timeout: %s", err)
   729  
   730  			// int64 counters
   731  			for name, expected := range test.expectedInt64Counters {
   732  				counter, ok := meter.int64counters[name]
   733  				require.True(t, ok, "int64 counter %q not found", name)
   734  
   735  				require.Equal(t, expected, counter.values, "counter values are wrong")
   736  			}
   737  
   738  			// float64 counters
   739  			for name, expected := range test.expectedFloat64Counters {
   740  				counter, ok := meter.float64counters[name]
   741  				require.True(t, ok, "float64 counter %q not found", name)
   742  
   743  				// require.Equal doesn't work because of float comparisons
   744  				require.InDeltaMapValues(t, expected, counter.values, 0.01, "counter values are wrong")
   745  			}
   746  
   747  			// int64 gauges
   748  			for name, expected := range test.expectedInt64Gauges {
   749  				gauge, ok := meter.int64gauges[name]
   750  				require.True(t, ok, "int64 gauge %q not found", name)
   751  
   752  				require.Equal(t, expected, gauge.values, "counter values are wrong")
   753  			}
   754  
   755  			// float64 gauges
   756  			for name, expected := range test.expectedFloat64Gauges {
   757  				gauge, ok := meter.float64gauges[name]
   758  				require.True(t, ok, "float gauge %q not found", name)
   759  
   760  				// require.Equal doesn't work because of float comparisons
   761  				require.InDeltaMapValues(t, expected, gauge.values, 0.01, "gauge values are wrong")
   762  			}
   763  
   764  			// int64 histograms
   765  			for name, expected := range test.expectedInt64Histograms {
   766  				histogram, ok := meter.int64histograms[name]
   767  				require.True(t, ok, "int64 histogram %q not found", name)
   768  
   769  				require.Equal(t, expected, histogram.values, "histogram values are wrong")
   770  			}
   771  
   772  			// float64 histograms
   773  			for name, expected := range test.expectedFloat64Histograms {
   774  				histogram, ok := meter.float64histograms[name]
   775  				require.True(t, ok, "float64 histogram %q not found", name)
   776  
   777  				// require.Equal doesn't work because of float comparisons
   778  				require.InDeltaMapValues(t, expected, histogram.values, 0.01, "histogram values are wrong")
   779  			}
   780  		})
   781  	}
   782  }
   783  
   784  // Based on https://github.com/embano1/waitgroup/blob/e5229ff7bc061f391c12f2be244bb50f030a6688/waitgroup.go#L27
   785  func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) error {
   786  	doneCh := make(chan struct{})
   787  	timer := time.NewTimer(timeout)
   788  	defer timer.Stop()
   789  
   790  	go func() {
   791  		wg.Wait()
   792  		close(doneCh)
   793  	}()
   794  
   795  	select {
   796  	case <-timer.C:
   797  		return fmt.Errorf("timed out")
   798  	case <-doneCh:
   799  		return nil
   800  	}
   801  }