github.com/google/cadvisor@v0.49.1/metrics/prometheus_test.go (about)

     1  // Copyright 2014 Google Inc. All Rights Reserved.
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package metrics
    16  
    17  import (
    18  	"errors"
    19  	"os"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/google/cadvisor/container"
    24  	info "github.com/google/cadvisor/info/v1"
    25  	v2 "github.com/google/cadvisor/info/v2"
    26  
    27  	"github.com/prometheus/client_golang/prometheus"
    28  	"github.com/prometheus/client_golang/prometheus/testutil"
    29  	"github.com/stretchr/testify/assert"
    30  	clock "k8s.io/utils/clock/testing"
    31  )
    32  
    33  var now = clock.NewFakeClock(time.Unix(1395066363, 0))
    34  
    35  func TestPrometheusCollector(t *testing.T) {
    36  	c := NewPrometheusCollector(testSubcontainersInfoProvider{}, func(container *info.ContainerInfo) map[string]string {
    37  		s := DefaultContainerLabels(container)
    38  		s["zone.name"] = "hello"
    39  		return s
    40  	}, container.AllMetrics, now, v2.RequestOptions{})
    41  	reg := prometheus.NewRegistry()
    42  	reg.MustRegister(c)
    43  
    44  	testPrometheusCollector(t, reg, "testdata/prometheus_metrics")
    45  }
    46  
    47  func TestPrometheusCollectorWithWhiteList(t *testing.T) {
    48  	c := NewPrometheusCollector(testSubcontainersInfoProvider{}, func(container *info.ContainerInfo) map[string]string {
    49  		whitelistedLabels := []string{
    50  			"no_one_match",
    51  		}
    52  		containerLabelFunc := BaseContainerLabels(whitelistedLabels)
    53  		s := containerLabelFunc(container)
    54  		s["zone.name"] = "hello"
    55  		return s
    56  	}, container.AllMetrics, now, v2.RequestOptions{})
    57  	reg := prometheus.NewRegistry()
    58  	reg.MustRegister(c)
    59  
    60  	testPrometheusCollector(t, reg, "testdata/prometheus_metrics_whitelist_filtered")
    61  }
    62  
    63  func TestPrometheusCollectorWithPerfAggregated(t *testing.T) {
    64  	metrics := container.MetricSet{
    65  		container.PerfMetrics: struct{}{},
    66  	}
    67  	c := NewPrometheusCollector(testSubcontainersInfoProvider{}, func(container *info.ContainerInfo) map[string]string {
    68  		s := DefaultContainerLabels(container)
    69  		s["zone.name"] = "hello"
    70  		return s
    71  	}, metrics, now, v2.RequestOptions{})
    72  	reg := prometheus.NewRegistry()
    73  	reg.MustRegister(c)
    74  
    75  	testPrometheusCollector(t, reg, "testdata/prometheus_metrics_perf_aggregated")
    76  }
    77  
    78  func testPrometheusCollector(t *testing.T, gatherer prometheus.Gatherer, metricsFile string) {
    79  	wantMetrics, err := os.Open(metricsFile)
    80  	if err != nil {
    81  		t.Fatalf("unable to read input test file %s", metricsFile)
    82  	}
    83  
    84  	err = testutil.GatherAndCompare(gatherer, wantMetrics)
    85  	if err != nil {
    86  		t.Fatalf("Metric comparison failed: %s", err)
    87  	}
    88  }
    89  
    90  func TestPrometheusCollector_scrapeFailure(t *testing.T) {
    91  	provider := &erroringSubcontainersInfoProvider{
    92  		successfulProvider: testSubcontainersInfoProvider{},
    93  		shouldFail:         true,
    94  	}
    95  
    96  	c := NewPrometheusCollector(provider, func(container *info.ContainerInfo) map[string]string {
    97  		s := DefaultContainerLabels(container)
    98  		s["zone.name"] = "hello"
    99  		return s
   100  	}, container.AllMetrics, now, v2.RequestOptions{})
   101  	reg := prometheus.NewRegistry()
   102  	reg.MustRegister(c)
   103  
   104  	testPrometheusCollector(t, reg, "testdata/prometheus_metrics_failure")
   105  
   106  	provider.shouldFail = false
   107  
   108  	testPrometheusCollector(t, reg, "testdata/prometheus_metrics")
   109  }
   110  
   111  func TestNewPrometheusCollectorWithPerf(t *testing.T) {
   112  	c := NewPrometheusCollector(&mockInfoProvider{}, mockLabelFunc, container.MetricSet{container.PerfMetrics: struct{}{}}, now, v2.RequestOptions{})
   113  	assert.Len(t, c.containerMetrics, 5)
   114  	names := []string{}
   115  	for _, m := range c.containerMetrics {
   116  		names = append(names, m.name)
   117  	}
   118  	assert.Contains(t, names, "container_last_seen")
   119  	assert.Contains(t, names, "container_perf_events_total")
   120  	assert.Contains(t, names, "container_perf_events_scaling_ratio")
   121  	assert.Contains(t, names, "container_perf_uncore_events_total")
   122  	assert.Contains(t, names, "container_perf_uncore_events_scaling_ratio")
   123  }
   124  
   125  func TestNewPrometheusCollectorWithRequestOptions(t *testing.T) {
   126  	p := mockInfoProvider{}
   127  	opts := v2.RequestOptions{
   128  		IdType: "docker",
   129  	}
   130  	c := NewPrometheusCollector(&p, mockLabelFunc, container.AllMetrics, now, opts)
   131  	ch := make(chan prometheus.Metric, 10)
   132  	c.Collect(ch)
   133  	assert.Equal(t, p.options, opts)
   134  }
   135  
   136  type mockInfoProvider struct {
   137  	options v2.RequestOptions
   138  }
   139  
   140  func (m *mockInfoProvider) GetRequestedContainersInfo(containerName string, options v2.RequestOptions) (map[string]*info.ContainerInfo, error) {
   141  	m.options = options
   142  	return map[string]*info.ContainerInfo{}, nil
   143  }
   144  
   145  func (m *mockInfoProvider) GetVersionInfo() (*info.VersionInfo, error) {
   146  	return nil, errors.New("not supported")
   147  }
   148  
   149  func (m *mockInfoProvider) GetMachineInfo() (*info.MachineInfo, error) {
   150  	return nil, errors.New("not supported")
   151  }
   152  
   153  func mockLabelFunc(*info.ContainerInfo) map[string]string {
   154  	return map[string]string{}
   155  }
   156  
   157  func TestGetPerCpuCorePerfEvents(t *testing.T) {
   158  	containerStats := &info.ContainerStats{
   159  		Timestamp: time.Unix(1395066367, 0),
   160  		PerfStats: []info.PerfStat{
   161  			{
   162  				PerfValue: info.PerfValue{
   163  					ScalingRatio: 1.0,
   164  					Value:        123,
   165  					Name:         "instructions",
   166  				},
   167  				Cpu: 0,
   168  			},
   169  			{
   170  				PerfValue: info.PerfValue{
   171  					ScalingRatio: 0.5,
   172  					Value:        456,
   173  					Name:         "instructions",
   174  				},
   175  				Cpu: 1,
   176  			},
   177  			{
   178  				PerfValue: info.PerfValue{
   179  					ScalingRatio: 0.7,
   180  					Value:        321,
   181  					Name:         "instructions_retired"},
   182  				Cpu: 0,
   183  			},
   184  			{
   185  				PerfValue: info.PerfValue{
   186  					ScalingRatio: 0.3,
   187  					Value:        789,
   188  					Name:         "instructions_retired"},
   189  				Cpu: 1,
   190  			},
   191  		},
   192  	}
   193  	metricVals := getPerCPUCorePerfEvents(containerStats)
   194  	assert.Equal(t, 4, len(metricVals))
   195  	values := []float64{}
   196  	for _, metric := range metricVals {
   197  		values = append(values, metric.value)
   198  	}
   199  	assert.Contains(t, values, 123.0)
   200  	assert.Contains(t, values, 456.0)
   201  	assert.Contains(t, values, 321.0)
   202  	assert.Contains(t, values, 789.0)
   203  }
   204  
   205  func TestGetPerCpuCoreScalingRatio(t *testing.T) {
   206  	containerStats := &info.ContainerStats{
   207  		Timestamp: time.Unix(1395066367, 0),
   208  		PerfStats: []info.PerfStat{
   209  			{
   210  				PerfValue: info.PerfValue{
   211  					ScalingRatio: 1.0,
   212  					Value:        123,
   213  					Name:         "instructions"},
   214  				Cpu: 0,
   215  			},
   216  			{
   217  				PerfValue: info.PerfValue{
   218  					ScalingRatio: 0.5,
   219  					Value:        456,
   220  					Name:         "instructions"},
   221  				Cpu: 1,
   222  			},
   223  			{
   224  				PerfValue: info.PerfValue{
   225  					ScalingRatio: 0.7,
   226  					Value:        321,
   227  					Name:         "instructions_retired"},
   228  				Cpu: 0,
   229  			},
   230  			{
   231  				PerfValue: info.PerfValue{
   232  					ScalingRatio: 0.3,
   233  					Value:        789,
   234  					Name:         "instructions_retired"},
   235  				Cpu: 1,
   236  			},
   237  		},
   238  	}
   239  	metricVals := getPerCPUCoreScalingRatio(containerStats)
   240  	assert.Equal(t, 4, len(metricVals))
   241  	values := []float64{}
   242  	for _, metric := range metricVals {
   243  		values = append(values, metric.value)
   244  	}
   245  	assert.Contains(t, values, 1.0)
   246  	assert.Contains(t, values, 0.5)
   247  	assert.Contains(t, values, 0.7)
   248  	assert.Contains(t, values, 0.3)
   249  }
   250  
   251  func TestGetAggCorePerfEvents(t *testing.T) {
   252  	containerStats := &info.ContainerStats{
   253  		Timestamp: time.Unix(1395066367, 0),
   254  		PerfStats: []info.PerfStat{
   255  			{
   256  				PerfValue: info.PerfValue{
   257  					ScalingRatio: 1.0,
   258  					Value:        123,
   259  					Name:         "instructions"},
   260  				Cpu: 0,
   261  			},
   262  			{
   263  				PerfValue: info.PerfValue{
   264  					ScalingRatio: 0.5,
   265  					Value:        456,
   266  					Name:         "instructions"},
   267  				Cpu: 1,
   268  			},
   269  			{
   270  				PerfValue: info.PerfValue{
   271  					ScalingRatio: 0.7,
   272  					Value:        321,
   273  					Name:         "instructions_retired"},
   274  				Cpu: 0,
   275  			},
   276  			{
   277  				PerfValue: info.PerfValue{
   278  					ScalingRatio: 0.3,
   279  					Value:        789,
   280  					Name:         "instructions_retired"},
   281  				Cpu: 1,
   282  			},
   283  		},
   284  	}
   285  	metricVals := getAggregatedCorePerfEvents(containerStats)
   286  	assert.Equal(t, 2, len(metricVals))
   287  	values := []float64{}
   288  	for _, metric := range metricVals {
   289  		values = append(values, metric.value)
   290  	}
   291  	assert.Contains(t, values, 579.0)
   292  	assert.Contains(t, values, 1110.0)
   293  }
   294  
   295  func TestGetMinCoreScalingRatio(t *testing.T) {
   296  	containerStats := &info.ContainerStats{
   297  		Timestamp: time.Unix(1395066367, 0),
   298  		PerfStats: []info.PerfStat{
   299  			{
   300  				PerfValue: info.PerfValue{
   301  					ScalingRatio: 1.0,
   302  					Value:        123,
   303  					Name:         "instructions"},
   304  				Cpu: 0,
   305  			},
   306  			{
   307  				PerfValue: info.PerfValue{
   308  					ScalingRatio: 0.5,
   309  					Value:        456,
   310  					Name:         "instructions"},
   311  				Cpu: 1,
   312  			},
   313  			{
   314  				PerfValue: info.PerfValue{
   315  					ScalingRatio: 0.7,
   316  					Value:        321,
   317  					Name:         "instructions_retired"},
   318  				Cpu: 0,
   319  			},
   320  			{
   321  				PerfValue: info.PerfValue{
   322  					ScalingRatio: 0.3,
   323  					Value:        789,
   324  					Name:         "instructions_retired"},
   325  				Cpu: 1,
   326  			},
   327  		},
   328  	}
   329  	metricVals := getMinCoreScalingRatio(containerStats)
   330  	assert.Equal(t, 2, len(metricVals))
   331  	values := []float64{}
   332  	for _, metric := range metricVals {
   333  		values = append(values, metric.value)
   334  	}
   335  	assert.Contains(t, values, 0.5)
   336  	assert.Contains(t, values, 0.3)
   337  }