...

Source file src/k8s.io/component-base/metrics/gauge_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  	"strings"
    21  	"testing"
    22  
    23  	"github.com/blang/semver/v4"
    24  	"github.com/prometheus/client_golang/prometheus/testutil"
    25  	"github.com/stretchr/testify/assert"
    26  
    27  	apimachineryversion "k8s.io/apimachinery/pkg/version"
    28  )
    29  
    30  func TestGauge(t *testing.T) {
    31  	v115 := semver.MustParse("1.15.0")
    32  	var tests = []struct {
    33  		desc string
    34  		*GaugeOpts
    35  		registryVersion     *semver.Version
    36  		expectedMetricCount int
    37  		expectedHelp        string
    38  	}{
    39  		{
    40  			desc: "Test non deprecated",
    41  			GaugeOpts: &GaugeOpts{
    42  				Namespace: "namespace",
    43  				Name:      "metric_test_name",
    44  				Subsystem: "subsystem",
    45  				Help:      "gauge help",
    46  			},
    47  			registryVersion:     &v115,
    48  			expectedMetricCount: 1,
    49  			expectedHelp:        "[ALPHA] gauge help",
    50  		},
    51  		{
    52  			desc: "Test deprecated",
    53  			GaugeOpts: &GaugeOpts{
    54  				Namespace:         "namespace",
    55  				Name:              "metric_test_name",
    56  				Subsystem:         "subsystem",
    57  				Help:              "gauge help",
    58  				DeprecatedVersion: "1.15.0",
    59  			},
    60  			registryVersion:     &v115,
    61  			expectedMetricCount: 1,
    62  			expectedHelp:        "[ALPHA] (Deprecated since 1.15.0) gauge help",
    63  		},
    64  		{
    65  			desc: "Test hidden",
    66  			GaugeOpts: &GaugeOpts{
    67  				Namespace:         "namespace",
    68  				Name:              "metric_test_name",
    69  				Subsystem:         "subsystem",
    70  				Help:              "gauge help",
    71  				DeprecatedVersion: "1.14.0",
    72  			},
    73  			registryVersion:     &v115,
    74  			expectedMetricCount: 0,
    75  			expectedHelp:        "gauge help",
    76  		},
    77  	}
    78  
    79  	for _, test := range tests {
    80  		t.Run(test.desc, func(t *testing.T) {
    81  			registry := newKubeRegistry(apimachineryversion.Info{
    82  				Major:      "1",
    83  				Minor:      "15",
    84  				GitVersion: "v1.15.0-alpha-1.12345",
    85  			})
    86  			c := NewGauge(test.GaugeOpts)
    87  			registry.MustRegister(c)
    88  
    89  			ms, err := registry.Gather()
    90  			assert.Equalf(t, test.expectedMetricCount, len(ms), "Got %v metrics, Want: %v metrics", len(ms), test.expectedMetricCount)
    91  			assert.Nil(t, err, "Gather failed %v", err)
    92  
    93  			for _, metric := range ms {
    94  				assert.Equalf(t, test.expectedHelp, metric.GetHelp(), "Got %s as help message, want %s", metric.GetHelp(), test.expectedHelp)
    95  			}
    96  
    97  			// let's increment the counter and verify that the metric still works
    98  			c.Set(100)
    99  			c.Set(101)
   100  			expected := 101
   101  			ms, err = registry.Gather()
   102  			assert.Nil(t, err, "Gather failed %v", err)
   103  
   104  			for _, mf := range ms {
   105  				for _, m := range mf.GetMetric() {
   106  					assert.Equalf(t, expected, int(m.GetGauge().GetValue()), "Got %v, wanted %v as the count", m.GetGauge().GetValue(), expected)
   107  					t.Logf("%v\n", m.GetGauge().GetValue())
   108  				}
   109  			}
   110  		})
   111  	}
   112  }
   113  
   114  func TestGaugeVec(t *testing.T) {
   115  	v115 := semver.MustParse("1.15.0")
   116  	var tests = []struct {
   117  		desc string
   118  		*GaugeOpts
   119  		labels              []string
   120  		registryVersion     *semver.Version
   121  		expectedMetricCount int
   122  		expectedHelp        string
   123  	}{
   124  		{
   125  			desc: "Test non deprecated",
   126  			GaugeOpts: &GaugeOpts{
   127  				Namespace: "namespace",
   128  				Name:      "metric_test_name",
   129  				Subsystem: "subsystem",
   130  				Help:      "gauge help",
   131  			},
   132  			labels:              []string{"label_a", "label_b"},
   133  			registryVersion:     &v115,
   134  			expectedMetricCount: 1,
   135  			expectedHelp:        "[ALPHA] gauge help",
   136  		},
   137  		{
   138  			desc: "Test deprecated",
   139  			GaugeOpts: &GaugeOpts{
   140  				Namespace:         "namespace",
   141  				Name:              "metric_test_name",
   142  				Subsystem:         "subsystem",
   143  				Help:              "gauge help",
   144  				DeprecatedVersion: "1.15.0",
   145  			},
   146  			labels:              []string{"label_a", "label_b"},
   147  			registryVersion:     &v115,
   148  			expectedMetricCount: 1,
   149  			expectedHelp:        "[ALPHA] (Deprecated since 1.15.0) gauge help",
   150  		},
   151  		{
   152  			desc: "Test hidden",
   153  			GaugeOpts: &GaugeOpts{
   154  				Namespace:         "namespace",
   155  				Name:              "metric_test_name",
   156  				Subsystem:         "subsystem",
   157  				Help:              "gauge help",
   158  				DeprecatedVersion: "1.14.0",
   159  			},
   160  			labels:              []string{"label_a", "label_b"},
   161  			registryVersion:     &v115,
   162  			expectedMetricCount: 0,
   163  			expectedHelp:        "gauge help",
   164  		},
   165  	}
   166  
   167  	for _, test := range tests {
   168  		t.Run(test.desc, func(t *testing.T) {
   169  			registry := newKubeRegistry(apimachineryversion.Info{
   170  				Major:      "1",
   171  				Minor:      "15",
   172  				GitVersion: "v1.15.0-alpha-1.12345",
   173  			})
   174  			c := NewGaugeVec(test.GaugeOpts, test.labels)
   175  			registry.MustRegister(c)
   176  			c.WithLabelValues("1", "2").Set(1.0)
   177  			ms, err := registry.Gather()
   178  			assert.Equalf(t, test.expectedMetricCount, len(ms), "Got %v metrics, Want: %v metrics", len(ms), test.expectedMetricCount)
   179  			assert.Nil(t, err, "Gather failed %v", err)
   180  			for _, metric := range ms {
   181  				assert.Equalf(t, test.expectedHelp, metric.GetHelp(), "Got %s as help message, want %s", metric.GetHelp(), test.expectedHelp)
   182  			}
   183  
   184  			// let's increment the counter and verify that the metric still works
   185  			c.WithLabelValues("1", "3").Set(1.0)
   186  			c.WithLabelValues("2", "3").Set(1.0)
   187  			ms, err = registry.Gather()
   188  			assert.Nil(t, err, "Gather failed %v", err)
   189  
   190  			for _, mf := range ms {
   191  				assert.Equalf(t, 3, len(mf.GetMetric()), "Got %v metrics, wanted 3 as the count", len(mf.GetMetric()))
   192  			}
   193  		})
   194  	}
   195  }
   196  
   197  func TestGaugeFunc(t *testing.T) {
   198  	currentVersion := apimachineryversion.Info{
   199  		Major:      "1",
   200  		Minor:      "17",
   201  		GitVersion: "v1.17.0-alpha-1.12345",
   202  	}
   203  
   204  	var function = func() float64 {
   205  		return 1
   206  	}
   207  
   208  	var tests = []struct {
   209  		desc string
   210  		*GaugeOpts
   211  		expectedMetrics string
   212  	}{
   213  		{
   214  			desc: "Test non deprecated",
   215  			GaugeOpts: &GaugeOpts{
   216  				Namespace: "namespace",
   217  				Subsystem: "subsystem",
   218  				Name:      "metric_non_deprecated",
   219  				Help:      "gauge help",
   220  			},
   221  			expectedMetrics: `
   222  # HELP namespace_subsystem_metric_non_deprecated [ALPHA] gauge help
   223  # TYPE namespace_subsystem_metric_non_deprecated gauge
   224  namespace_subsystem_metric_non_deprecated 1
   225  			`,
   226  		},
   227  		{
   228  			desc: "Test deprecated",
   229  			GaugeOpts: &GaugeOpts{
   230  				Namespace:         "namespace",
   231  				Subsystem:         "subsystem",
   232  				Name:              "metric_deprecated",
   233  				Help:              "gauge help",
   234  				DeprecatedVersion: "1.17.0",
   235  			},
   236  			expectedMetrics: `
   237  # HELP namespace_subsystem_metric_deprecated [ALPHA] (Deprecated since 1.17.0) gauge help
   238  # TYPE namespace_subsystem_metric_deprecated gauge
   239  namespace_subsystem_metric_deprecated 1
   240  `,
   241  		},
   242  		{
   243  			desc: "Test hidden",
   244  			GaugeOpts: &GaugeOpts{
   245  				Namespace:         "namespace",
   246  				Subsystem:         "subsystem",
   247  				Name:              "metric_hidden",
   248  				Help:              "gauge help",
   249  				DeprecatedVersion: "1.16.0",
   250  			},
   251  			expectedMetrics: "",
   252  		},
   253  	}
   254  
   255  	for _, test := range tests {
   256  		tc := test
   257  		t.Run(test.desc, func(t *testing.T) {
   258  			registry := newKubeRegistry(currentVersion)
   259  			gauge := newGaugeFunc(tc.GaugeOpts, function, parseVersion(currentVersion))
   260  			if gauge != nil { // hidden metrics will not be initialize, register is not allowed
   261  				registry.RawMustRegister(gauge)
   262  			}
   263  
   264  			metricName := BuildFQName(tc.GaugeOpts.Namespace, tc.GaugeOpts.Subsystem, tc.GaugeOpts.Name)
   265  			if err := testutil.GatherAndCompare(registry, strings.NewReader(tc.expectedMetrics), metricName); err != nil {
   266  				t.Fatal(err)
   267  			}
   268  		})
   269  	}
   270  }
   271  
   272  func TestGaugeWithLabelValueAllowList(t *testing.T) {
   273  	labelAllowValues := map[string]string{
   274  		"namespace_subsystem_metric_allowlist_test,label_a": "allowed",
   275  	}
   276  	labels := []string{"label_a", "label_b"}
   277  	opts := &GaugeOpts{
   278  		Namespace: "namespace",
   279  		Name:      "metric_allowlist_test",
   280  		Subsystem: "subsystem",
   281  	}
   282  	var tests = []struct {
   283  		desc               string
   284  		labelValues        [][]string
   285  		expectMetricValues map[string]float64
   286  	}{
   287  		{
   288  			desc:        "Test no unexpected input",
   289  			labelValues: [][]string{{"allowed", "b1"}, {"allowed", "b2"}},
   290  			expectMetricValues: map[string]float64{
   291  				"allowed b1": 100.0,
   292  				"allowed b2": 100.0,
   293  			},
   294  		},
   295  		{
   296  			desc:        "Test unexpected input",
   297  			labelValues: [][]string{{"allowed", "b1"}, {"not_allowed", "b1"}},
   298  			expectMetricValues: map[string]float64{
   299  				"allowed b1":    100.0,
   300  				"unexpected b1": 100.0,
   301  			},
   302  		},
   303  	}
   304  
   305  	for _, test := range tests {
   306  		t.Run(test.desc, func(t *testing.T) {
   307  			SetLabelAllowListFromCLI(labelAllowValues)
   308  			registry := newKubeRegistry(apimachineryversion.Info{
   309  				Major:      "1",
   310  				Minor:      "15",
   311  				GitVersion: "v1.15.0-alpha-1.12345",
   312  			})
   313  			g := NewGaugeVec(opts, labels)
   314  			registry.MustRegister(g)
   315  
   316  			for _, lv := range test.labelValues {
   317  				g.WithLabelValues(lv...).Set(100.0)
   318  			}
   319  			mfs, err := registry.Gather()
   320  			assert.Nil(t, err, "Gather failed %v", err)
   321  
   322  			for _, mf := range mfs {
   323  				if *mf.Name != BuildFQName(opts.Namespace, opts.Subsystem, opts.Name) {
   324  					continue
   325  				}
   326  				mfMetric := mf.GetMetric()
   327  
   328  				for _, m := range mfMetric {
   329  					var aValue, bValue string
   330  					for _, l := range m.Label {
   331  						if *l.Name == "label_a" {
   332  							aValue = *l.Value
   333  						}
   334  						if *l.Name == "label_b" {
   335  							bValue = *l.Value
   336  						}
   337  					}
   338  					labelValuePair := aValue + " " + bValue
   339  					expectedValue, ok := test.expectMetricValues[labelValuePair]
   340  					assert.True(t, ok, "Got unexpected label values, lable_a is %v, label_b is %v", aValue, bValue)
   341  					actualValue := m.GetGauge().GetValue()
   342  					assert.Equalf(t, expectedValue, actualValue, "Got %v, wanted %v as the gauge while setting label_a to %v and label b to %v", actualValue, expectedValue, aValue, bValue)
   343  				}
   344  			}
   345  		})
   346  	}
   347  }
   348  

View as plain text