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  }