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  }