...

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

Documentation: k8s.io/component-base/metrics/testutil

     1  /*
     2  Copyright 2020 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 testutil
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"reflect"
    23  	"testing"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/google/go-cmp/cmp/cmpopts"
    27  	dto "github.com/prometheus/client_model/go"
    28  	"k8s.io/component-base/metrics"
    29  	"k8s.io/utils/pointer"
    30  )
    31  
    32  func samples2Histogram(samples []float64, upperBounds []float64) Histogram {
    33  	histogram := dto.Histogram{
    34  		SampleCount: uint64Ptr(0),
    35  		SampleSum:   pointer.Float64Ptr(0.0),
    36  	}
    37  
    38  	for _, ub := range upperBounds {
    39  		histogram.Bucket = append(histogram.Bucket, &dto.Bucket{
    40  			CumulativeCount: uint64Ptr(0),
    41  			UpperBound:      pointer.Float64Ptr(ub),
    42  		})
    43  	}
    44  
    45  	for _, sample := range samples {
    46  		for i, bucket := range histogram.Bucket {
    47  			if sample < *bucket.UpperBound {
    48  				*histogram.Bucket[i].CumulativeCount++
    49  			}
    50  		}
    51  		*histogram.SampleCount++
    52  		*histogram.SampleSum += sample
    53  	}
    54  	return Histogram{
    55  		&histogram,
    56  	}
    57  }
    58  
    59  func TestHistogramQuantile(t *testing.T) {
    60  	tests := []struct {
    61  		name    string
    62  		samples []float64
    63  		bounds  []float64
    64  		q50     float64
    65  		q90     float64
    66  		q99     float64
    67  	}{
    68  		{
    69  			name:    "Repeating numbers",
    70  			samples: []float64{0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 3, 3, 3, 3, 6, 6, 6, 6},
    71  			bounds:  []float64{1, 2, 4, 8},
    72  			q50:     2,
    73  			q90:     6.4,
    74  			q99:     7.84,
    75  		},
    76  		{
    77  			name:    "Random numbers",
    78  			samples: []float64{11, 67, 61, 21, 40, 36, 52, 63, 8, 3, 67, 35, 61, 1, 36, 58},
    79  			bounds:  []float64{10, 20, 40, 80},
    80  			q50:     40,
    81  			q90:     72,
    82  			q99:     79.2,
    83  		},
    84  		{
    85  			name:    "The last bucket is empty",
    86  			samples: []float64{6, 34, 30, 10, 20, 18, 26, 31, 4, 2, 33, 17, 30, 1, 18, 29},
    87  			bounds:  []float64{10, 20, 40, 80},
    88  			q50:     20,
    89  			q90:     36,
    90  			q99:     39.6,
    91  		},
    92  		{
    93  			name:    "The last bucket has positive infinity upper bound",
    94  			samples: []float64{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 500},
    95  			bounds:  []float64{10, 20, 40, math.Inf(1)},
    96  			q50:     5.3125,
    97  			q90:     9.5625,
    98  			q99:     40,
    99  		},
   100  	}
   101  
   102  	for _, test := range tests {
   103  		t.Run(test.name, func(t *testing.T) {
   104  			h := samples2Histogram(test.samples, test.bounds)
   105  			q50 := h.Quantile(0.5)
   106  			q90 := h.Quantile(0.9)
   107  			q99 := h.Quantile(0.99)
   108  			q999999 := h.Quantile(0.999999)
   109  
   110  			if q50 != test.q50 {
   111  				t.Errorf("Expected q50 to be %v, got %v instead", test.q50, q50)
   112  			}
   113  			if q90 != test.q90 {
   114  				t.Errorf("Expected q90 to be %v, got %v instead", test.q90, q90)
   115  			}
   116  			if q99 != test.q99 {
   117  				t.Errorf("Expected q99 to be %v, got %v instead", test.q99, q99)
   118  			}
   119  			lastUpperBound := test.bounds[len(test.bounds)-1]
   120  			if !(q999999 < lastUpperBound) {
   121  				t.Errorf("Expected q999999 to be less than %v, got %v instead", lastUpperBound, q999999)
   122  			}
   123  		})
   124  	}
   125  }
   126  
   127  func TestHistogramValidate(t *testing.T) {
   128  	tests := []struct {
   129  		name string
   130  		h    Histogram
   131  		err  error
   132  	}{
   133  		{
   134  			name: "nil SampleCount",
   135  			h: Histogram{
   136  				&dto.Histogram{},
   137  			},
   138  			err: fmt.Errorf("nil or empty histogram SampleCount"),
   139  		},
   140  		{
   141  			name: "empty SampleCount",
   142  			h: Histogram{
   143  				&dto.Histogram{
   144  					SampleCount: uint64Ptr(0),
   145  				},
   146  			},
   147  			err: fmt.Errorf("nil or empty histogram SampleCount"),
   148  		},
   149  		{
   150  			name: "nil SampleSum",
   151  			h: Histogram{
   152  				&dto.Histogram{
   153  					SampleCount: uint64Ptr(1),
   154  				},
   155  			},
   156  			err: fmt.Errorf("nil or empty histogram SampleSum"),
   157  		},
   158  		{
   159  			name: "empty SampleSum",
   160  			h: Histogram{
   161  				&dto.Histogram{
   162  					SampleCount: uint64Ptr(1),
   163  					SampleSum:   pointer.Float64Ptr(0.0),
   164  				},
   165  			},
   166  			err: fmt.Errorf("nil or empty histogram SampleSum"),
   167  		},
   168  		{
   169  			name: "nil bucket",
   170  			h: Histogram{
   171  				&dto.Histogram{
   172  					SampleCount: uint64Ptr(1),
   173  					SampleSum:   pointer.Float64Ptr(1.0),
   174  					Bucket: []*dto.Bucket{
   175  						nil,
   176  					},
   177  				},
   178  			},
   179  			err: fmt.Errorf("empty histogram bucket"),
   180  		},
   181  		{
   182  			name: "nil bucket UpperBound",
   183  			h: Histogram{
   184  				&dto.Histogram{
   185  					SampleCount: uint64Ptr(1),
   186  					SampleSum:   pointer.Float64Ptr(1.0),
   187  					Bucket: []*dto.Bucket{
   188  						{},
   189  					},
   190  				},
   191  			},
   192  			err: fmt.Errorf("nil or negative histogram bucket UpperBound"),
   193  		},
   194  		{
   195  			name: "negative bucket UpperBound",
   196  			h: Histogram{
   197  				&dto.Histogram{
   198  					SampleCount: uint64Ptr(1),
   199  					SampleSum:   pointer.Float64Ptr(1.0),
   200  					Bucket: []*dto.Bucket{
   201  						{UpperBound: pointer.Float64Ptr(-1.0)},
   202  					},
   203  				},
   204  			},
   205  			err: fmt.Errorf("nil or negative histogram bucket UpperBound"),
   206  		},
   207  		{
   208  			name: "valid histogram",
   209  			h: samples2Histogram(
   210  				[]float64{0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 3, 3, 3, 3, 6, 6, 6, 6},
   211  				[]float64{1, 2, 4, 8},
   212  			),
   213  		},
   214  	}
   215  
   216  	for _, test := range tests {
   217  		err := test.h.Validate()
   218  		if test.err != nil {
   219  			if err == nil || err.Error() != test.err.Error() {
   220  				t.Errorf("Expected %q error, got %q instead", test.err, err)
   221  			}
   222  		} else {
   223  			if err != nil {
   224  				t.Errorf("Expected error to be nil, got %q instead", err)
   225  			}
   226  		}
   227  	}
   228  }
   229  
   230  func TestLabelsMatch(t *testing.T) {
   231  	cases := []struct {
   232  		name          string
   233  		metric        *dto.Metric
   234  		labelFilter   map[string]string
   235  		expectedMatch bool
   236  	}{
   237  		{name: "metric labels and labelFilter have the same labels and values", metric: &dto.Metric{
   238  			Label: []*dto.LabelPair{
   239  				{Name: pointer.StringPtr("a"), Value: pointer.StringPtr("1")},
   240  				{Name: pointer.StringPtr("b"), Value: pointer.StringPtr("2")},
   241  				{Name: pointer.StringPtr("c"), Value: pointer.StringPtr("3")},
   242  			}}, labelFilter: map[string]string{
   243  			"a": "1",
   244  			"b": "2",
   245  			"c": "3",
   246  		}, expectedMatch: true},
   247  		{name: "metric labels contain all labelFilter labels, and labelFilter is a subset of metric labels", metric: &dto.Metric{
   248  			Label: []*dto.LabelPair{
   249  				{Name: pointer.StringPtr("a"), Value: pointer.StringPtr("1")},
   250  				{Name: pointer.StringPtr("b"), Value: pointer.StringPtr("2")},
   251  				{Name: pointer.StringPtr("c"), Value: pointer.StringPtr("3")},
   252  			}}, labelFilter: map[string]string{
   253  			"a": "1",
   254  			"b": "2",
   255  		}, expectedMatch: true},
   256  		{name: "metric labels don't have all labelFilter labels and value", metric: &dto.Metric{
   257  			Label: []*dto.LabelPair{
   258  				{Name: pointer.StringPtr("a"), Value: pointer.StringPtr("1")},
   259  				{Name: pointer.StringPtr("b"), Value: pointer.StringPtr("2")},
   260  			}}, labelFilter: map[string]string{
   261  			"a": "1",
   262  			"b": "2",
   263  			"c": "3",
   264  		}, expectedMatch: false},
   265  		{name: "The intersection of metric labels and labelFilter labels is empty", metric: &dto.Metric{
   266  			Label: []*dto.LabelPair{
   267  				{Name: pointer.StringPtr("aa"), Value: pointer.StringPtr("11")},
   268  				{Name: pointer.StringPtr("bb"), Value: pointer.StringPtr("22")},
   269  				{Name: pointer.StringPtr("cc"), Value: pointer.StringPtr("33")},
   270  			}}, labelFilter: map[string]string{
   271  			"a": "1",
   272  			"b": "2",
   273  			"c": "3",
   274  		}, expectedMatch: false},
   275  		{name: "metric labels have the same labels names but different values with labelFilter labels and value", metric: &dto.Metric{
   276  			Label: []*dto.LabelPair{
   277  				{Name: pointer.StringPtr("a"), Value: pointer.StringPtr("1")},
   278  				{Name: pointer.StringPtr("b"), Value: pointer.StringPtr("2")},
   279  				{Name: pointer.StringPtr("c"), Value: pointer.StringPtr("3")},
   280  			}}, labelFilter: map[string]string{
   281  			"a": "11",
   282  			"b": "2",
   283  			"c": "3",
   284  		}, expectedMatch: false},
   285  		{name: "metric labels contain label name but different values with labelFilter labels and value", metric: &dto.Metric{
   286  			Label: []*dto.LabelPair{
   287  				{Name: pointer.StringPtr("a"), Value: pointer.StringPtr("1")},
   288  				{Name: pointer.StringPtr("b"), Value: pointer.StringPtr("2")},
   289  				{Name: pointer.StringPtr("c"), Value: pointer.StringPtr("33")},
   290  				{Name: pointer.StringPtr("d"), Value: pointer.StringPtr("4")},
   291  			}}, labelFilter: map[string]string{
   292  			"a": "1",
   293  			"b": "2",
   294  			"c": "3",
   295  		}, expectedMatch: false},
   296  		{name: "metric labels is empty and labelFilter is not empty", metric: &dto.Metric{
   297  			Label: []*dto.LabelPair{}}, labelFilter: map[string]string{
   298  			"a": "1",
   299  			"b": "2",
   300  			"c": "3",
   301  		}, expectedMatch: false},
   302  		{name: "metric labels is not empty and labelFilter is empty", metric: &dto.Metric{
   303  			Label: []*dto.LabelPair{
   304  				{Name: pointer.StringPtr("a"), Value: pointer.StringPtr("1")},
   305  				{Name: pointer.StringPtr("b"), Value: pointer.StringPtr("2")},
   306  			}}, labelFilter: map[string]string{}, expectedMatch: true},
   307  	}
   308  	for _, tt := range cases {
   309  		t.Run(tt.name, func(t *testing.T) {
   310  			got := LabelsMatch(tt.metric, tt.labelFilter)
   311  			if got != tt.expectedMatch {
   312  				t.Errorf("Expected %v, got %v instead", tt.expectedMatch, got)
   313  			}
   314  		})
   315  	}
   316  }
   317  
   318  func TestHistogramVec_GetAggregatedSampleCount(t *testing.T) {
   319  	tests := []struct {
   320  		name string
   321  		vec  HistogramVec
   322  		want uint64
   323  	}{
   324  		{
   325  			name: "nil case",
   326  			want: 0,
   327  		},
   328  		{
   329  			name: "zero case",
   330  			vec: HistogramVec{
   331  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(0), SampleSum: pointer.Float64Ptr(0.0)}},
   332  			},
   333  			want: 0,
   334  		},
   335  		{
   336  			name: "standard case",
   337  			vec: HistogramVec{
   338  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(1), SampleSum: pointer.Float64Ptr(2.0)}},
   339  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(2), SampleSum: pointer.Float64Ptr(4.0)}},
   340  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(4), SampleSum: pointer.Float64Ptr(8.0)}},
   341  			},
   342  			want: 7,
   343  		},
   344  		{
   345  			name: "mixed case",
   346  			vec: HistogramVec{
   347  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(1), SampleSum: pointer.Float64Ptr(2.0)}},
   348  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(0), SampleSum: pointer.Float64Ptr(0.0)}},
   349  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(2), SampleSum: pointer.Float64Ptr(4.0)}},
   350  			},
   351  			want: 3,
   352  		},
   353  	}
   354  
   355  	for _, tt := range tests {
   356  		t.Run(tt.name, func(t *testing.T) {
   357  			if got := tt.vec.GetAggregatedSampleCount(); got != tt.want {
   358  				t.Errorf("GetAggregatedSampleCount() = %v, want %v", got, tt.want)
   359  			}
   360  		})
   361  	}
   362  }
   363  
   364  func TestHistogramVec_GetAggregatedSampleSum(t *testing.T) {
   365  	tests := []struct {
   366  		name string
   367  		vec  HistogramVec
   368  		want float64
   369  	}{
   370  		{
   371  			name: "nil case",
   372  			want: 0.0,
   373  		},
   374  		{
   375  			name: "zero case",
   376  			vec: HistogramVec{
   377  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(0), SampleSum: pointer.Float64Ptr(0.0)}},
   378  			},
   379  			want: 0.0,
   380  		},
   381  		{
   382  			name: "standard case",
   383  			vec: HistogramVec{
   384  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(1), SampleSum: pointer.Float64Ptr(2.0)}},
   385  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(2), SampleSum: pointer.Float64Ptr(4.0)}},
   386  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(4), SampleSum: pointer.Float64Ptr(8.0)}},
   387  			},
   388  			want: 14.0,
   389  		},
   390  		{
   391  			name: "mixed case",
   392  			vec: HistogramVec{
   393  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(1), SampleSum: pointer.Float64Ptr(2.0)}},
   394  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(0), SampleSum: pointer.Float64Ptr(0.0)}},
   395  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(2), SampleSum: pointer.Float64Ptr(4.0)}},
   396  			},
   397  			want: 6.0,
   398  		},
   399  	}
   400  	for _, tt := range tests {
   401  		t.Run(tt.name, func(t *testing.T) {
   402  			if got := tt.vec.GetAggregatedSampleSum(); got != tt.want {
   403  				t.Errorf("GetAggregatedSampleSum() = %v, want %v", got, tt.want)
   404  			}
   405  		})
   406  	}
   407  }
   408  
   409  func TestHistogramVec_Quantile(t *testing.T) {
   410  	tests := []struct {
   411  		name     string
   412  		samples  [][]float64
   413  		bounds   []float64
   414  		quantile float64
   415  		want     []float64
   416  	}{
   417  		{
   418  			name: "duplicated histograms",
   419  			samples: [][]float64{
   420  				{0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 3, 3, 3, 3, 6, 6, 6, 6},
   421  				{0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 3, 3, 3, 3, 6, 6, 6, 6},
   422  				{0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 3, 3, 3, 3, 6, 6, 6, 6},
   423  			},
   424  			bounds: []float64{1, 2, 4, 8},
   425  			want:   []float64{2, 6.4, 7.2, 7.84},
   426  		},
   427  		{
   428  			name: "random numbers",
   429  			samples: [][]float64{
   430  				{8, 35, 47, 61, 56, 69, 66, 74, 35, 69, 5, 38, 58, 40, 36, 12},
   431  				{79, 44, 57, 46, 11, 8, 53, 77, 13, 35, 38, 47, 73, 16, 26, 29},
   432  				{51, 76, 22, 55, 20, 63, 59, 66, 34, 58, 64, 16, 79, 7, 58, 28},
   433  			},
   434  			bounds: []float64{10, 20, 40, 80},
   435  			want:   []float64{44.44, 72.89, 76.44, 79.29},
   436  		},
   437  		{
   438  			name: "single histogram",
   439  			samples: [][]float64{
   440  				{6, 34, 30, 10, 20, 18, 26, 31, 4, 2, 33, 17, 30, 1, 18, 29},
   441  			},
   442  			bounds: []float64{10, 20, 40, 80},
   443  			want:   []float64{20, 36, 38, 39.6},
   444  		},
   445  	}
   446  	for _, tt := range tests {
   447  		t.Run(tt.name, func(t *testing.T) {
   448  			var vec HistogramVec
   449  			for _, sample := range tt.samples {
   450  				histogram := samples2Histogram(sample, tt.bounds)
   451  				vec = append(vec, &histogram)
   452  			}
   453  			var got []float64
   454  			for _, q := range []float64{0.5, 0.9, 0.95, 0.99} {
   455  				got = append(got, math.Round(vec.Quantile(q)*100)/100)
   456  			}
   457  			if !reflect.DeepEqual(got, tt.want) {
   458  				t.Errorf("Quantile() = %v, want %v", got, tt.want)
   459  			}
   460  		})
   461  	}
   462  }
   463  
   464  func TestHistogramVec_Validate(t *testing.T) {
   465  	tests := []struct {
   466  		name string
   467  		vec  HistogramVec
   468  		want error
   469  	}{
   470  		{
   471  			name: "nil SampleCount",
   472  			vec: HistogramVec{
   473  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(1), SampleSum: pointer.Float64Ptr(1.0)}},
   474  				&Histogram{&dto.Histogram{SampleSum: pointer.Float64Ptr(2.0)}},
   475  			},
   476  			want: fmt.Errorf("nil or empty histogram SampleCount"),
   477  		},
   478  		{
   479  			name: "valid HistogramVec",
   480  			vec: HistogramVec{
   481  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(1), SampleSum: pointer.Float64Ptr(1.0)}},
   482  				&Histogram{&dto.Histogram{SampleCount: uint64Ptr(2), SampleSum: pointer.Float64Ptr(2.0)}},
   483  			},
   484  		},
   485  		{
   486  			name: "different bucket size",
   487  			vec: HistogramVec{
   488  				&Histogram{&dto.Histogram{
   489  					SampleCount: uint64Ptr(4),
   490  					SampleSum:   pointer.Float64Ptr(10.0),
   491  					Bucket: []*dto.Bucket{
   492  						{CumulativeCount: uint64Ptr(1), UpperBound: pointer.Float64Ptr(1)},
   493  						{CumulativeCount: uint64Ptr(2), UpperBound: pointer.Float64Ptr(2)},
   494  						{CumulativeCount: uint64Ptr(5), UpperBound: pointer.Float64Ptr(4)},
   495  					},
   496  				}},
   497  				&Histogram{&dto.Histogram{
   498  					SampleCount: uint64Ptr(3),
   499  					SampleSum:   pointer.Float64Ptr(8.0),
   500  					Bucket: []*dto.Bucket{
   501  						{CumulativeCount: uint64Ptr(1), UpperBound: pointer.Float64Ptr(2)},
   502  						{CumulativeCount: uint64Ptr(3), UpperBound: pointer.Float64Ptr(4)},
   503  					},
   504  				}},
   505  			},
   506  			want: fmt.Errorf("found different bucket size: expect 3, but got 2 at index 1"),
   507  		},
   508  	}
   509  	for _, tt := range tests {
   510  		t.Run(tt.name, func(t *testing.T) {
   511  			if got := tt.vec.Validate(); fmt.Sprintf("%v", got) != fmt.Sprintf("%v", tt.want) {
   512  				t.Errorf("Validate() = %v, want %v", got, tt.want)
   513  			}
   514  		})
   515  	}
   516  }
   517  
   518  func TestGetHistogramVecFromGatherer(t *testing.T) {
   519  	tests := []struct {
   520  		name    string
   521  		lvMap   map[string]string
   522  		wantVec HistogramVec
   523  	}{
   524  		{
   525  			name:  "filter with one label",
   526  			lvMap: map[string]string{"label1": "value1-0"},
   527  			wantVec: HistogramVec{
   528  				&Histogram{&dto.Histogram{
   529  					SampleCount: uint64Ptr(1),
   530  					SampleSum:   pointer.Float64Ptr(1.5),
   531  					Bucket: []*dto.Bucket{
   532  						{CumulativeCount: uint64Ptr(0), UpperBound: pointer.Float64Ptr(0.5)},
   533  						{CumulativeCount: uint64Ptr(1), UpperBound: pointer.Float64Ptr(2.0)},
   534  						{CumulativeCount: uint64Ptr(1), UpperBound: pointer.Float64Ptr(5.0)},
   535  					},
   536  				}},
   537  				&Histogram{&dto.Histogram{
   538  					SampleCount: uint64Ptr(1),
   539  					SampleSum:   pointer.Float64Ptr(2.5),
   540  					Bucket: []*dto.Bucket{
   541  						{CumulativeCount: uint64Ptr(0), UpperBound: pointer.Float64Ptr(0.5)},
   542  						{CumulativeCount: uint64Ptr(0), UpperBound: pointer.Float64Ptr(2.0)},
   543  						{CumulativeCount: uint64Ptr(1), UpperBound: pointer.Float64Ptr(5.0)},
   544  					},
   545  				}},
   546  			},
   547  		},
   548  		{
   549  			name:  "filter with two labels",
   550  			lvMap: map[string]string{"label1": "value1-0", "label2": "value2-1"},
   551  			wantVec: HistogramVec{
   552  				&Histogram{&dto.Histogram{
   553  					SampleCount: uint64Ptr(1),
   554  					SampleSum:   pointer.Float64Ptr(2.5),
   555  					Bucket: []*dto.Bucket{
   556  						{CumulativeCount: uint64Ptr(0), UpperBound: pointer.Float64Ptr(0.5)},
   557  						{CumulativeCount: uint64Ptr(0), UpperBound: pointer.Float64Ptr(2.0)},
   558  						{CumulativeCount: uint64Ptr(1), UpperBound: pointer.Float64Ptr(5.0)},
   559  					},
   560  				}},
   561  			},
   562  		},
   563  	}
   564  	for _, tt := range tests {
   565  		t.Run(tt.name, func(t *testing.T) {
   566  			buckets := []float64{.5, 2, 5}
   567  			// HistogramVec has two labels defined.
   568  			labels := []string{"label1", "label2"}
   569  			HistogramOpts := &metrics.HistogramOpts{
   570  				Namespace: "namespace",
   571  				Name:      "metric_test_name",
   572  				Subsystem: "subsystem",
   573  				Help:      "histogram help message",
   574  				Buckets:   buckets,
   575  			}
   576  			vec := metrics.NewHistogramVec(HistogramOpts, labels)
   577  			// Use local registry
   578  			var registry = metrics.NewKubeRegistry()
   579  			var gather metrics.Gatherer = registry
   580  			registry.MustRegister(vec)
   581  			// Observe two metrics with same value for label1 but different value of label2.
   582  			vec.WithLabelValues("value1-0", "value2-0").Observe(1.5)
   583  			vec.WithLabelValues("value1-0", "value2-1").Observe(2.5)
   584  			vec.WithLabelValues("value1-1", "value2-0").Observe(3.5)
   585  			vec.WithLabelValues("value1-1", "value2-1").Observe(4.5)
   586  			metricName := fmt.Sprintf("%s_%s_%s", HistogramOpts.Namespace, HistogramOpts.Subsystem, HistogramOpts.Name)
   587  			histogramVec, _ := GetHistogramVecFromGatherer(gather, metricName, tt.lvMap)
   588  			if diff := cmp.Diff(tt.wantVec, histogramVec, cmpopts.IgnoreFields(dto.Histogram{}, "state", "sizeCache", "unknownFields"), cmpopts.IgnoreFields(dto.Bucket{}, "state", "sizeCache", "unknownFields")); diff != "" {
   589  				t.Errorf("Got unexpected HistogramVec (-want +got):\n%s", diff)
   590  			}
   591  		})
   592  	}
   593  }
   594  

View as plain text