github.com/galamsiva2020/kubernetes-heapster-monitoring@v0.0.0-20210823134957-3c1baa7c1e70/metrics/sources/summary/summary_test.go (about) 1 // Copyright 2015 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 summary 16 17 import ( 18 "encoding/json" 19 "net" 20 "net/http/httptest" 21 "strconv" 22 "strings" 23 "testing" 24 "time" 25 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 util "k8s.io/client-go/util/testing" 30 "k8s.io/heapster/metrics/core" 31 "k8s.io/heapster/metrics/sources/kubelet" 32 stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" 33 ) 34 35 const ( 36 // Offsets from seed value in generated container stats. 37 offsetCPUUsageCores = iota 38 offsetCPUUsageCoreSeconds 39 offsetMemPageFaults 40 offsetMemMajorPageFaults 41 offsetMemUsageBytes 42 offsetMemRSSBytes 43 offsetMemWorkingSetBytes 44 offsetNetRxBytes 45 offsetNetRxErrors 46 offsetNetTxBytes 47 offsetNetTxErrors 48 offsetFsUsed 49 offsetFsCapacity 50 offsetFsAvailable 51 offsetAcceleratorMemoryTotal 52 offsetAcceleratorMemoryUsed 53 offsetAcceleratorDutyCycle 54 ) 55 56 const ( 57 seedNode = 0 58 seedRuntime = 100 59 seedKubelet = 200 60 seedMisc = 300 61 seedPod0 = 1000 62 seedPod0Container0 = 2000 63 seedPod0Container1 = 2001 64 seedPod1 = 3000 65 seedPod1Container = 4000 66 seedPod2 = 5000 67 seedPod2Container0 = 6000 68 seedPod2Container1 = 7000 69 seedPod3Container0 = 9000 70 seedPod4 = 10000 71 seedPod4Container0 = 11000 72 seedPod5 = 12000 73 seedPod5Container0 = 13000 74 ) 75 76 const ( 77 namespace0 = "test0" 78 namespace1 = "test1" 79 80 pName0 = "pod0" 81 pName1 = "pod1" 82 pName2 = "pod0" // ensure pName2 conflicts with pName0, but is in a different namespace 83 pName3 = "pod2" 84 pName4 = "pod4" // Regression test for #1838 85 pName5 = "pod5" 86 87 cName00 = "c0" 88 cName01 = "c1" 89 cName10 = "c0" // ensure cName10 conflicts with cName02, but is in a different pod 90 cName20 = "c1" // ensure cName20 conflicts with cName01, but is in a different pod + namespace 91 cName21 = "runtime" // ensure that runtime containers are not renamed 92 cName30 = "c3" 93 cName40 = "c4" // Running, with cpu / memory stats 94 cName41 = "c4" // Terminated, has no CPU / Memory stats 95 cName42 = "c4" // Terminated, has blank CPU / Memory stats 96 cName50 = "c5" 97 ) 98 99 var ( 100 availableFsBytes = uint64(1130) 101 usedFsBytes = uint64(13340) 102 totalFsBytes = uint64(2153) 103 freeInode = uint64(10440) 104 usedInode = uint64(103520) 105 totalInode = uint64(103620) 106 scrapeTime = time.Now() 107 startTime = time.Now().Add(-time.Minute) 108 ) 109 110 var nodeInfo = NodeInfo{ 111 NodeName: "test", 112 HostName: "test-hostname", 113 HostID: "1234567890", 114 KubeletVersion: "1.2", 115 } 116 117 type fakeSource struct { 118 scraped bool 119 } 120 121 func (f *fakeSource) Name() string { return "fake" } 122 func (f *fakeSource) ScrapeMetrics(start, end time.Time) (*core.DataBatch, error) { 123 f.scraped = true 124 return nil, nil 125 } 126 127 func testingSummaryMetricsSource() *summaryMetricsSource { 128 return &summaryMetricsSource{ 129 node: nodeInfo, 130 kubeletClient: &kubelet.KubeletClient{}, 131 } 132 } 133 134 func TestDecodeSummaryMetrics(t *testing.T) { 135 136 ms := testingSummaryMetricsSource() 137 summary := stats.Summary{ 138 Node: stats.NodeStats{ 139 NodeName: nodeInfo.NodeName, 140 StartTime: metav1.NewTime(startTime), 141 CPU: genTestSummaryCPU(seedNode), 142 Memory: genTestSummaryMemory(seedNode), 143 Network: genTestSummaryNetwork(seedNode), 144 SystemContainers: []stats.ContainerStats{ 145 genTestSummaryContainer(stats.SystemContainerKubelet, seedKubelet), 146 genTestSummaryContainer(stats.SystemContainerRuntime, seedRuntime), 147 genTestSummaryContainer(stats.SystemContainerMisc, seedMisc), 148 }, 149 Fs: genTestSummaryFsStats(seedNode), 150 }, 151 Pods: []stats.PodStats{{ 152 PodRef: stats.PodReference{ 153 Name: pName0, 154 Namespace: namespace0, 155 }, 156 StartTime: metav1.NewTime(startTime), 157 Network: genTestSummaryNetwork(seedPod0), 158 EphemeralStorage: genTestSummaryFsStats(seedPod0), 159 CPU: genTestSummaryCPU(seedPod0), 160 Memory: genTestSummaryMemory(seedPod0), 161 Containers: []stats.ContainerStats{ 162 genTestSummaryContainer(cName00, seedPod0Container0), 163 genTestSummaryContainer(cName01, seedPod0Container1), 164 genTestSummaryTerminatedContainer(cName00, seedPod0Container0), 165 }, 166 }, { 167 PodRef: stats.PodReference{ 168 Name: pName1, 169 Namespace: namespace0, 170 }, 171 StartTime: metav1.NewTime(startTime), 172 Network: genTestSummaryNetwork(seedPod1), 173 Containers: []stats.ContainerStats{ 174 genTestSummaryContainer(cName10, seedPod1Container), 175 }, 176 VolumeStats: []stats.VolumeStats{{ 177 Name: "A", 178 FsStats: *genTestSummaryFsStats(seedPod1), 179 }, { 180 Name: "B", 181 FsStats: *genTestSummaryFsStats(seedPod1), 182 }}, 183 }, { 184 PodRef: stats.PodReference{ 185 Name: pName2, 186 Namespace: namespace1, 187 }, 188 StartTime: metav1.NewTime(startTime), 189 Network: genTestSummaryNetwork(seedPod2), 190 Containers: []stats.ContainerStats{ 191 genTestSummaryContainer(cName20, seedPod2Container0), 192 genTestSummaryContainer(cName21, seedPod2Container1), 193 }, 194 }, { 195 PodRef: stats.PodReference{ 196 Name: pName3, 197 Namespace: namespace0, 198 }, 199 Containers: []stats.ContainerStats{ 200 genTestSummaryContainer(cName30, seedPod3Container0), 201 }, 202 VolumeStats: []stats.VolumeStats{{ 203 Name: "C", 204 FsStats: stats.FsStats{ 205 AvailableBytes: &availableFsBytes, 206 UsedBytes: &usedFsBytes, 207 CapacityBytes: &totalFsBytes, 208 InodesFree: &freeInode, 209 InodesUsed: &usedInode, 210 Inodes: &totalInode, 211 }, 212 }, 213 }, 214 }, { 215 PodRef: stats.PodReference{ 216 Name: pName4, 217 Namespace: namespace0, 218 }, 219 StartTime: metav1.NewTime(startTime), 220 Network: genTestSummaryNetwork(seedPod4), 221 Containers: []stats.ContainerStats{ 222 genTestSummaryContainer(cName40, seedPod4Container0), 223 genTestSummaryTerminatedContainerNoStats(cName41), 224 genTestSummaryTerminatedContainerBlankStats(cName42), 225 }, 226 }, { 227 PodRef: stats.PodReference{ 228 Name: pName5, 229 Namespace: namespace0, 230 }, 231 Network: genTestSummaryNetwork(seedPod5), 232 StartTime: metav1.NewTime(startTime), 233 Containers: []stats.ContainerStats{ 234 genTestSummaryContainerWithAccelerator(cName50, seedPod5Container0), 235 }, 236 }}, 237 } 238 239 containerFs := []string{"/", "logs"} 240 expectations := []struct { 241 key string 242 setType string 243 seed int64 244 cpu bool 245 memory bool 246 network bool 247 accelerators bool 248 ephemeralstorage bool 249 containerEphemeralstorage bool 250 fs []string 251 }{{ 252 key: core.NodeKey(nodeInfo.NodeName), 253 setType: core.MetricSetTypeNode, 254 seed: seedNode, 255 cpu: true, 256 memory: true, 257 network: true, 258 ephemeralstorage: true, 259 fs: []string{"/"}, 260 }, { 261 key: core.NodeContainerKey(nodeInfo.NodeName, "kubelet"), 262 setType: core.MetricSetTypeSystemContainer, 263 seed: seedKubelet, 264 cpu: true, 265 memory: true, 266 }, { 267 key: core.NodeContainerKey(nodeInfo.NodeName, "docker-daemon"), 268 setType: core.MetricSetTypeSystemContainer, 269 seed: seedRuntime, 270 cpu: true, 271 memory: true, 272 }, { 273 key: core.NodeContainerKey(nodeInfo.NodeName, "system"), 274 setType: core.MetricSetTypeSystemContainer, 275 seed: seedMisc, 276 cpu: true, 277 memory: true, 278 }, { 279 key: core.PodKey(namespace0, pName0), 280 setType: core.MetricSetTypePod, 281 seed: seedPod0, 282 network: true, 283 cpu: true, 284 memory: true, 285 ephemeralstorage: true, 286 }, { 287 key: core.PodKey(namespace0, pName1), 288 setType: core.MetricSetTypePod, 289 seed: seedPod1, 290 network: true, 291 fs: []string{"Volume:A", "Volume:B"}, 292 }, { 293 key: core.PodKey(namespace1, pName2), 294 setType: core.MetricSetTypePod, 295 seed: seedPod2, 296 network: true, 297 }, { 298 key: core.PodKey(namespace0, pName4), 299 setType: core.MetricSetTypePod, 300 seed: seedPod4, 301 network: true, 302 }, { 303 key: core.PodKey(namespace0, pName5), 304 setType: core.MetricSetTypePod, 305 seed: seedPod5, 306 network: true, 307 }, { 308 key: core.PodContainerKey(namespace0, pName0, cName00), 309 setType: core.MetricSetTypePodContainer, 310 seed: seedPod0Container0, 311 cpu: true, 312 memory: true, 313 containerEphemeralstorage: true, 314 fs: containerFs, 315 }, { 316 key: core.PodContainerKey(namespace0, pName0, cName01), 317 setType: core.MetricSetTypePodContainer, 318 seed: seedPod0Container1, 319 cpu: true, 320 memory: true, 321 fs: containerFs, 322 }, { 323 key: core.PodContainerKey(namespace0, pName1, cName10), 324 setType: core.MetricSetTypePodContainer, 325 seed: seedPod1Container, 326 cpu: true, 327 memory: true, 328 fs: containerFs, 329 }, { 330 key: core.PodContainerKey(namespace1, pName2, cName20), 331 setType: core.MetricSetTypePodContainer, 332 seed: seedPod2Container0, 333 cpu: true, 334 memory: true, 335 fs: containerFs, 336 }, { 337 key: core.PodContainerKey(namespace1, pName2, cName21), 338 setType: core.MetricSetTypePodContainer, 339 seed: seedPod2Container1, 340 cpu: true, 341 memory: true, 342 fs: containerFs, 343 }, { 344 key: core.PodContainerKey(namespace0, pName3, cName30), 345 setType: core.MetricSetTypePodContainer, 346 seed: seedPod3Container0, 347 cpu: true, 348 memory: true, 349 fs: containerFs, 350 }, { 351 key: core.PodContainerKey(namespace0, pName4, cName40), 352 setType: core.MetricSetTypePodContainer, 353 seed: seedPod4Container0, 354 cpu: true, 355 memory: true, 356 fs: containerFs, 357 }, { 358 key: core.PodContainerKey(namespace0, pName5, cName50), 359 setType: core.MetricSetTypePodContainer, 360 seed: seedPod5Container0, 361 cpu: true, 362 accelerators: true, 363 }} 364 365 metrics := ms.decodeSummary(&summary) 366 for _, e := range expectations { 367 m, ok := metrics[e.key] 368 if !assert.True(t, ok, "missing metric %q", e.key) { 369 continue 370 } 371 assert.Equal(t, m.Labels[core.LabelMetricSetType.Key], e.setType, e.key) 372 assert.Equal(t, m.CollectionStartTime, startTime, e.key) 373 assert.Equal(t, m.ScrapeTime, scrapeTime, e.key) 374 if e.cpu { 375 checkIntMetric(t, m, e.key, core.MetricCpuUsage, e.seed+offsetCPUUsageCoreSeconds) 376 } 377 if e.memory { 378 checkIntMetric(t, m, e.key, core.MetricMemoryUsage, e.seed+offsetMemUsageBytes) 379 checkIntMetric(t, m, e.key, core.MetricMemoryWorkingSet, e.seed+offsetMemWorkingSetBytes) 380 checkIntMetric(t, m, e.key, core.MetricMemoryRSS, e.seed+offsetMemRSSBytes) 381 checkIntMetric(t, m, e.key, core.MetricMemoryPageFaults, e.seed+offsetMemPageFaults) 382 checkIntMetric(t, m, e.key, core.MetricMemoryMajorPageFaults, e.seed+offsetMemMajorPageFaults) 383 } 384 if e.network { 385 checkIntMetric(t, m, e.key, core.MetricNetworkRx, e.seed+offsetNetRxBytes) 386 checkIntMetric(t, m, e.key, core.MetricNetworkRxErrors, e.seed+offsetNetRxErrors) 387 checkIntMetric(t, m, e.key, core.MetricNetworkTx, e.seed+offsetNetTxBytes) 388 checkIntMetric(t, m, e.key, core.MetricNetworkTxErrors, e.seed+offsetNetTxErrors) 389 } 390 if e.accelerators { 391 checkAcceleratorMetric(t, m, e.key, core.MetricAcceleratorMemoryTotal, e.seed+offsetAcceleratorMemoryTotal) 392 checkAcceleratorMetric(t, m, e.key, core.MetricAcceleratorMemoryUsed, e.seed+offsetAcceleratorMemoryUsed) 393 checkAcceleratorMetric(t, m, e.key, core.MetricAcceleratorDutyCycle, e.seed+offsetAcceleratorDutyCycle) 394 } 395 if e.ephemeralstorage { 396 checkIntMetric(t, m, e.key, core.MetricEphemeralStorageUsage, e.seed+offsetFsUsed) 397 } 398 if e.containerEphemeralstorage { 399 checkIntMetric(t, m, e.key, core.MetricEphemeralStorageUsage, 2*(e.seed+offsetFsUsed)) 400 } 401 for _, label := range e.fs { 402 checkFsMetric(t, m, e.key, label, core.MetricFilesystemAvailable, e.seed+offsetFsAvailable) 403 checkFsMetric(t, m, e.key, label, core.MetricFilesystemLimit, e.seed+offsetFsCapacity) 404 checkFsMetric(t, m, e.key, label, core.MetricFilesystemUsage, e.seed+offsetFsUsed) 405 } 406 delete(metrics, e.key) 407 } 408 409 // Verify volume information labeled metrics 410 var volumeInformationMetricsKey = core.PodKey(namespace0, pName3) 411 var mappedVolumeStats = map[string]int64{} 412 for _, labeledMetric := range metrics[volumeInformationMetricsKey].LabeledMetrics { 413 assert.True(t, strings.HasPrefix("Volume:C", labeledMetric.Labels["resource_id"])) 414 mappedVolumeStats[labeledMetric.Name] = labeledMetric.IntValue 415 } 416 417 assert.True(t, mappedVolumeStats["filesystem/available"] == int64(availableFsBytes)) 418 assert.True(t, mappedVolumeStats["filesystem/usage"] == int64(usedFsBytes)) 419 assert.True(t, mappedVolumeStats["filesystem/limit"] == int64(totalFsBytes)) 420 421 delete(metrics, volumeInformationMetricsKey) 422 423 for k, v := range metrics { 424 assert.Fail(t, "unexpected metric", "%q: %+v", k, v) 425 } 426 } 427 428 func genTestSummaryTerminatedContainer(name string, seed int) stats.ContainerStats { 429 return stats.ContainerStats{ 430 Name: name, 431 StartTime: metav1.NewTime(startTime.Add(-time.Minute)), 432 CPU: genTestSummaryZeroCPU(seed), 433 Memory: genTestSummaryZeroMemory(seed), 434 Rootfs: genTestSummaryFsStats(seed), 435 Logs: genTestSummaryFsStats(seed), 436 } 437 } 438 439 func genTestSummaryTerminatedContainerNoStats(name string) stats.ContainerStats { 440 return stats.ContainerStats{ 441 Name: name, 442 StartTime: metav1.NewTime(startTime.Add(-time.Minute)), 443 } 444 } 445 446 func genTestSummaryTerminatedContainerBlankStats(name string) stats.ContainerStats { 447 return stats.ContainerStats{ 448 Name: name, 449 StartTime: metav1.NewTime(startTime.Add(-time.Minute)), 450 CPU: genTestSummaryBlankCPU(), 451 Memory: genTestSummaryBlankMemory(), 452 } 453 } 454 455 func genTestSummaryContainer(name string, seed int) stats.ContainerStats { 456 return stats.ContainerStats{ 457 Name: name, 458 StartTime: metav1.NewTime(startTime), 459 CPU: genTestSummaryCPU(seed), 460 Memory: genTestSummaryMemory(seed), 461 Rootfs: genTestSummaryFsStats(seed), 462 Logs: genTestSummaryFsStats(seed), 463 } 464 } 465 466 func genTestSummaryContainerWithAccelerator(name string, seed int) stats.ContainerStats { 467 return stats.ContainerStats{ 468 Name: name, 469 StartTime: metav1.NewTime(startTime), 470 CPU: genTestSummaryCPU(seed), 471 Accelerators: genTestSummaryAccelerator(seed), 472 } 473 } 474 475 func genTestSummaryAccelerator(seed int) []stats.AcceleratorStats { 476 return []stats.AcceleratorStats{ 477 { 478 Make: "nvidia", 479 Model: "Tesla P100", 480 ID: "GPU-deadbeef-1234-5678-90ab-feedfacecafe", 481 MemoryTotal: *uint64Val(seed, offsetAcceleratorMemoryTotal), 482 MemoryUsed: *uint64Val(seed, offsetAcceleratorMemoryUsed), 483 DutyCycle: *uint64Val(seed, offsetAcceleratorDutyCycle), 484 }, 485 } 486 } 487 488 func genTestSummaryZeroCPU(seed int) *stats.CPUStats { 489 cpu := stats.CPUStats{ 490 Time: metav1.NewTime(scrapeTime), 491 UsageNanoCores: uint64Val(seed, -seed), 492 UsageCoreNanoSeconds: uint64Val(seed, offsetCPUUsageCoreSeconds), 493 } 494 *cpu.UsageCoreNanoSeconds *= uint64(time.Millisecond.Nanoseconds()) 495 return &cpu 496 } 497 498 func genTestSummaryCPU(seed int) *stats.CPUStats { 499 cpu := stats.CPUStats{ 500 Time: metav1.NewTime(scrapeTime), 501 UsageNanoCores: uint64Val(seed, offsetCPUUsageCores), 502 UsageCoreNanoSeconds: uint64Val(seed, offsetCPUUsageCoreSeconds), 503 } 504 *cpu.UsageNanoCores *= uint64(time.Millisecond.Nanoseconds()) 505 return &cpu 506 } 507 508 func genTestSummaryBlankCPU() *stats.CPUStats { 509 return &stats.CPUStats{ 510 Time: metav1.NewTime(scrapeTime), 511 } 512 } 513 514 func genTestSummaryZeroMemory(seed int) *stats.MemoryStats { 515 return &stats.MemoryStats{ 516 Time: metav1.NewTime(scrapeTime), 517 UsageBytes: uint64Val(seed, offsetMemUsageBytes), 518 WorkingSetBytes: uint64Val(seed, offsetMemWorkingSetBytes), 519 RSSBytes: uint64Val(seed, -seed), 520 PageFaults: uint64Val(seed, offsetMemPageFaults), 521 MajorPageFaults: uint64Val(seed, offsetMemMajorPageFaults), 522 } 523 } 524 525 func genTestSummaryMemory(seed int) *stats.MemoryStats { 526 return &stats.MemoryStats{ 527 Time: metav1.NewTime(scrapeTime), 528 UsageBytes: uint64Val(seed, offsetMemUsageBytes), 529 WorkingSetBytes: uint64Val(seed, offsetMemWorkingSetBytes), 530 RSSBytes: uint64Val(seed, offsetMemRSSBytes), 531 PageFaults: uint64Val(seed, offsetMemPageFaults), 532 MajorPageFaults: uint64Val(seed, offsetMemMajorPageFaults), 533 } 534 } 535 536 func genTestSummaryBlankMemory() *stats.MemoryStats { 537 return &stats.MemoryStats{ 538 Time: metav1.NewTime(scrapeTime), 539 } 540 } 541 542 func genTestSummaryNetwork(seed int) *stats.NetworkStats { 543 return &stats.NetworkStats{ 544 Time: metav1.NewTime(scrapeTime), 545 InterfaceStats: stats.InterfaceStats{ 546 RxBytes: uint64Val(seed, offsetNetRxBytes), 547 RxErrors: uint64Val(seed, offsetNetRxErrors), 548 TxBytes: uint64Val(seed, offsetNetTxBytes), 549 TxErrors: uint64Val(seed, offsetNetTxErrors), 550 }, 551 } 552 } 553 554 func genTestSummaryFsStats(seed int) *stats.FsStats { 555 return &stats.FsStats{ 556 AvailableBytes: uint64Val(seed, offsetFsAvailable), 557 CapacityBytes: uint64Val(seed, offsetFsCapacity), 558 UsedBytes: uint64Val(seed, offsetFsUsed), 559 } 560 } 561 562 // Convenience function for taking the address of a uint64 literal. 563 func uint64Val(seed, offset int) *uint64 { 564 val := uint64(seed + offset) 565 return &val 566 } 567 568 func checkIntMetric(t *testing.T, metrics *core.MetricSet, key string, metric core.Metric, value int64) { 569 m, ok := metrics.MetricValues[metric.Name] 570 if !assert.True(t, ok, "missing %q:%q", key, metric.Name) { 571 return 572 } 573 assert.Equal(t, value, m.IntValue, "%q:%q", key, metric.Name) 574 } 575 576 func checkFsMetric(t *testing.T, metrics *core.MetricSet, key, label string, metric core.Metric, value int64) { 577 for _, m := range metrics.LabeledMetrics { 578 if m.Name == metric.Name && m.Labels[core.LabelResourceID.Key] == label { 579 assert.Equal(t, value, m.IntValue, "%q:%q[%s]", key, metric.Name, label) 580 return 581 } 582 } 583 assert.Fail(t, "missing filesystem metric", "%q:[%q]:%q", key, metric.Name, label) 584 } 585 586 func checkAcceleratorMetric(t *testing.T, metrics *core.MetricSet, key string, metric core.Metric, value int64) { 587 for _, m := range metrics.LabeledMetrics { 588 if m.Name == metric.Name { 589 assert.Equal(t, value, m.IntValue, "%q:%q", key, metric.Name) 590 return 591 } 592 } 593 assert.Fail(t, "missing accelerator metric", "%q:[%q]", key, metric.Name) 594 } 595 596 func TestScrapeSummaryMetrics(t *testing.T) { 597 summary := stats.Summary{ 598 Node: stats.NodeStats{ 599 NodeName: nodeInfo.NodeName, 600 StartTime: metav1.NewTime(startTime), 601 }, 602 } 603 data, err := json.Marshal(&summary) 604 require.NoError(t, err) 605 606 server := httptest.NewServer(&util.FakeHandler{ 607 StatusCode: 200, 608 ResponseBody: string(data), 609 T: t, 610 }) 611 defer server.Close() 612 613 ms := testingSummaryMetricsSource() 614 split := strings.SplitN(strings.Replace(server.URL, "http://", "", 1), ":", 2) 615 ms.node.IP = net.ParseIP(split[0]) 616 ms.node.Port, err = strconv.Atoi(split[1]) 617 require.NoError(t, err) 618 619 res, err := ms.ScrapeMetrics(time.Now(), time.Now()) 620 assert.Nil(t, err, "scrape error") 621 assert.Equal(t, res.MetricSets["node:test"].Labels[core.LabelMetricSetType.Key], core.MetricSetTypeNode) 622 }