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 }