...

Source file src/k8s.io/component-base/metrics/collector_test.go

Documentation: k8s.io/component-base/metrics

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package metrics
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  
    25  	"github.com/prometheus/client_golang/prometheus/testutil"
    26  	"github.com/stretchr/testify/assert"
    27  
    28  	apimachineryversion "k8s.io/apimachinery/pkg/version"
    29  )
    30  
    31  type testCustomCollector struct {
    32  	BaseStableCollector
    33  
    34  	descriptors []*Desc
    35  }
    36  
    37  func newTestCustomCollector(ds ...*Desc) *testCustomCollector {
    38  	c := &testCustomCollector{}
    39  	c.descriptors = append(c.descriptors, ds...)
    40  
    41  	return c
    42  }
    43  
    44  func (tc *testCustomCollector) DescribeWithStability(ch chan<- *Desc) {
    45  	for i := range tc.descriptors {
    46  		ch <- tc.descriptors[i]
    47  	}
    48  }
    49  
    50  func (tc *testCustomCollector) CollectWithStability(ch chan<- Metric) {
    51  	for i := range tc.descriptors {
    52  		ch <- NewLazyConstMetric(tc.descriptors[i], GaugeValue, 1, "value")
    53  	}
    54  }
    55  
    56  func TestBaseCustomCollector(t *testing.T) {
    57  	var currentVersion = apimachineryversion.Info{
    58  		Major:      "1",
    59  		Minor:      "17",
    60  		GitVersion: "v1.17.0-alpha-1.12345",
    61  	}
    62  
    63  	var (
    64  		alphaDesc = NewDesc("metric_alpha", "alpha metric", []string{"name"}, nil,
    65  			ALPHA, "")
    66  		internalDesc = NewDesc("metric_internal", "internal metrics", []string{"name"}, nil,
    67  			INTERNAL, "")
    68  		stableDesc = NewDesc("metric_stable", "stable metrics", []string{"name"}, nil,
    69  			STABLE, "")
    70  		deprecatedDesc = NewDesc("metric_deprecated", "stable deprecated metrics", []string{"name"}, nil,
    71  			STABLE, "1.17.0")
    72  		hiddenDesc = NewDesc("metric_hidden", "stable hidden metrics", []string{"name"}, nil,
    73  			STABLE, "1.16.0")
    74  	)
    75  
    76  	registry := newKubeRegistry(currentVersion)
    77  	customCollector := newTestCustomCollector(alphaDesc, internalDesc, stableDesc, deprecatedDesc, hiddenDesc)
    78  
    79  	if err := registry.CustomRegister(customCollector); err != nil {
    80  		t.Fatalf("register collector failed with err: %v", err)
    81  	}
    82  
    83  	expectedMetrics := `
    84          # HELP metric_alpha [ALPHA] alpha metric
    85          # TYPE metric_alpha gauge
    86          metric_alpha{name="value"} 1
    87  		# HELP metric_internal [INTERNAL] internal metrics
    88          # TYPE metric_internal gauge
    89          metric_internal{name="value"} 1
    90          # HELP metric_stable [STABLE] stable metrics
    91          # TYPE metric_stable gauge
    92          metric_stable{name="value"} 1
    93          # HELP metric_deprecated [STABLE] (Deprecated since 1.17.0) stable deprecated metrics
    94          # TYPE metric_deprecated gauge
    95          metric_deprecated{name="value"} 1
    96  	`
    97  
    98  	err := testutil.GatherAndCompare(registry, strings.NewReader(expectedMetrics), alphaDesc.fqName,
    99  		internalDesc.fqName, stableDesc.fqName, deprecatedDesc.fqName, hiddenDesc.fqName)
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  }
   104  
   105  func TestInvalidCustomCollector(t *testing.T) {
   106  	var currentVersion = apimachineryversion.Info{
   107  		Major:      "1",
   108  		Minor:      "17",
   109  		GitVersion: "v1.17.0-alpha-1.12345",
   110  	}
   111  	var namelessDesc = NewDesc("", "this is a nameless metric", nil, nil, ALPHA, "")
   112  	var duplicatedDescA = NewDesc("test_duplicated_metric", "this is a duplicated metric A", nil, nil, ALPHA, "")
   113  	var duplicatedDescB = NewDesc("test_duplicated_metric", "this is a duplicated metric B", nil, nil, ALPHA, "")
   114  
   115  	var tests = []struct {
   116  		name        string
   117  		descriptors []*Desc
   118  		panicStr    string
   119  	}{
   120  		{
   121  			name:        "nameless metric will be not allowed",
   122  			descriptors: []*Desc{namelessDesc},
   123  			panicStr:    "nameless metrics will be not allowed",
   124  		},
   125  		{
   126  			name:        "duplicated metric will be not allowed",
   127  			descriptors: []*Desc{duplicatedDescA, duplicatedDescB},
   128  			panicStr:    fmt.Sprintf("duplicate metrics (%s) will be not allowed", duplicatedDescA.fqName),
   129  		},
   130  	}
   131  
   132  	for _, test := range tests {
   133  		tc := test
   134  		t.Run(tc.name, func(t *testing.T) {
   135  			registry := newKubeRegistry(currentVersion)
   136  			customCollector := newTestCustomCollector(tc.descriptors...)
   137  			assert.Panics(t, func() {
   138  				registry.CustomMustRegister(customCollector)
   139  			}, tc.panicStr)
   140  		})
   141  	}
   142  }
   143  
   144  // TestCustomCollectorClearState guarantees `ClearState()` will fully clear a collector.
   145  // It is necessary because we may forget to clear some new-added fields in the future.
   146  func TestCustomCollectorClearState(t *testing.T) {
   147  	var currentVersion = parseVersion(apimachineryversion.Info{
   148  		Major:      "1",
   149  		Minor:      "17",
   150  		GitVersion: "v1.17.0-alpha-1.12345",
   151  	})
   152  
   153  	var (
   154  		alphaDesc = NewDesc("metric_alpha", "alpha metric", []string{"name"}, nil,
   155  			ALPHA, "")
   156  		stableDesc = NewDesc("metric_stable", "stable metrics", []string{"name"}, nil,
   157  			STABLE, "")
   158  		deprecatedDesc = NewDesc("metric_deprecated", "stable deprecated metrics", []string{"name"}, nil,
   159  			STABLE, "1.17.0")
   160  		hiddenDesc = NewDesc("metric_hidden", "stable hidden metrics", []string{"name"}, nil,
   161  			STABLE, "1.16.0")
   162  	)
   163  
   164  	benchmarkA := newTestCustomCollector(alphaDesc, stableDesc, deprecatedDesc, hiddenDesc)
   165  	benchmarkB := newTestCustomCollector(alphaDesc, stableDesc, deprecatedDesc, hiddenDesc)
   166  
   167  	if benchmarkA.Create(&currentVersion, benchmarkA) == false {
   168  		t.Fatal("collector should be created")
   169  	}
   170  	benchmarkA.ClearState()
   171  
   172  	if !reflect.DeepEqual(*benchmarkA, *benchmarkB) {
   173  		t.Fatal("custom collector state hasn't be fully cleared")
   174  	}
   175  }
   176  

View as plain text