github.com/galamsiva2020/kubernetes-heapster-monitoring@v0.0.0-20210823134957-3c1baa7c1e70/metrics/sinks/hawkular/driver_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 hawkular 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "io/ioutil" 21 "net/http" 22 "net/http/httptest" 23 "net/url" 24 "strconv" 25 "strings" 26 "sync" 27 "testing" 28 "time" 29 30 "github.com/hawkular/hawkular-client-go/metrics" 31 "k8s.io/heapster/metrics/core" 32 33 assert "github.com/stretchr/testify/require" 34 ) 35 36 func dummySink() *hawkularSink { 37 return &hawkularSink{ 38 expReg: make(map[string]*expiringItem), 39 models: make(map[string]*metrics.MetricDefinition), 40 } 41 } 42 43 func TestDescriptorTransform(t *testing.T) { 44 45 hSink := dummySink() 46 47 ld := core.LabelDescriptor{ 48 Key: "k1", 49 Description: "d1", 50 } 51 smd := core.MetricDescriptor{ 52 Name: "test/metric/1", 53 Units: core.UnitsBytes, 54 ValueType: core.ValueInt64, 55 Type: core.MetricGauge, 56 Labels: []core.LabelDescriptor{ld}, 57 } 58 59 md := hSink.descriptorToDefinition(&smd) 60 61 assert.Equal(t, smd.Name, md.ID) 62 assert.Equal(t, 3, len(md.Tags)) // descriptorTag, unitsTag, typesTag, k1 63 64 assert.Equal(t, smd.Units.String(), md.Tags[unitsTag]) 65 assert.Equal(t, "d1", md.Tags["k1_description"]) 66 67 smd.Type = core.MetricCumulative 68 69 md = hSink.descriptorToDefinition(&smd) 70 assert.EqualValues(t, md.Type, metrics.Counter) 71 } 72 73 func TestMetricTransform(t *testing.T) { 74 hSink := dummySink() 75 76 l := make(map[string]string) 77 l["spooky"] = "notvisible" 78 l[core.LabelHostname.Key] = "localhost" 79 l[core.LabelHostID.Key] = "localhost" 80 l[core.LabelContainerName.Key] = "docker" 81 l[core.LabelPodId.Key] = "aaaa-bbbb-cccc-dddd" 82 l[core.LabelNodename.Key] = "myNode" 83 84 metricName := "test/metric/1" 85 labeledMetricNameA := "test/labeledmetric/A" 86 labeledMetricNameB := "test/labeledmetric/B" 87 88 metricSet := core.MetricSet{ 89 Labels: l, 90 MetricValues: map[string]core.MetricValue{ 91 metricName: { 92 ValueType: core.ValueInt64, 93 MetricType: core.MetricGauge, 94 IntValue: 123456, 95 }, 96 }, 97 LabeledMetrics: []core.LabeledMetric{ 98 { 99 Name: labeledMetricNameA, 100 Labels: map[string]string{ 101 core.LabelResourceID.Key: "XYZ", 102 }, 103 MetricValue: core.MetricValue{ 104 MetricType: core.MetricGauge, 105 FloatValue: 124.456, 106 }, 107 }, 108 { 109 Name: labeledMetricNameB, 110 MetricValue: core.MetricValue{ 111 MetricType: core.MetricGauge, 112 FloatValue: 454, 113 }, 114 }, 115 }, 116 } 117 118 metricSet.LabeledMetrics = append(metricSet.LabeledMetrics, metricValueToLabeledMetric(metricSet.MetricValues)...) 119 120 now := time.Now() 121 // 122 m, err := hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[2], now) 123 assert.NoError(t, err) 124 125 assert.Equal(t, fmt.Sprintf("%s/%s/%s", metricSet.Labels[core.LabelContainerName.Key], 126 metricSet.Labels[core.LabelPodId.Key], metricName), m.ID) 127 128 assert.Equal(t, 1, len(m.Data)) 129 _, ok := m.Data[0].Value.(float64) 130 assert.True(t, ok, "Value should have been converted to float64") 131 132 delete(l, core.LabelPodId.Key) 133 134 // 135 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[2], now) 136 assert.NoError(t, err) 137 138 assert.Equal(t, fmt.Sprintf("%s/%s/%s", metricSet.Labels[core.LabelContainerName.Key], metricSet.Labels[core.LabelNodename.Key], metricName), m.ID) 139 140 // 141 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 142 assert.NoError(t, err) 143 144 assert.Equal(t, fmt.Sprintf("%s/%s/%s/%s", metricSet.Labels[core.LabelContainerName.Key], 145 metricSet.Labels[core.LabelNodename.Key], labeledMetricNameA, 146 metricSet.LabeledMetrics[0].Labels[core.LabelResourceID.Key]), m.ID) 147 148 // 149 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[1], now) 150 assert.NoError(t, err) 151 assert.Equal(t, fmt.Sprintf("%s/%s/%s", metricSet.Labels[core.LabelContainerName.Key], 152 metricSet.Labels[core.LabelNodename.Key], labeledMetricNameB), m.ID) 153 } 154 155 func TestMetricIds(t *testing.T) { 156 hSink := dummySink() 157 158 l := make(map[string]string) 159 l["spooky"] = "notvisible" 160 l[core.LabelHostname.Key] = "localhost" 161 l[core.LabelHostID.Key] = "localhost" 162 l[core.LabelContainerName.Key] = "docker" 163 l[core.LabelPodId.Key] = "aaaa-bbbb-cccc-dddd" 164 l[core.LabelNodename.Key] = "myNode" 165 l[core.LabelNamespaceName.Key] = "myNamespace" 166 167 metricName := "test/metric/nodeType" 168 169 metricSet := core.MetricSet{ 170 Labels: l, 171 MetricValues: map[string]core.MetricValue{ 172 metricName: { 173 ValueType: core.ValueInt64, 174 MetricType: core.MetricGauge, 175 IntValue: 123456, 176 }, 177 }, 178 } 179 metricSet.LabeledMetrics = metricValueToLabeledMetric(metricSet.MetricValues) 180 181 now := time.Now() 182 // 183 m, err := hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 184 assert.NoError(t, err) 185 assert.Equal(t, fmt.Sprintf("%s/%s/%s", metricSet.Labels[core.LabelContainerName.Key], metricSet.Labels[core.LabelPodId.Key], metricName), m.ID) 186 187 // 188 metricSet.Labels[core.LabelMetricSetType.Key] = core.MetricSetTypeNode 189 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 190 assert.NoError(t, err) 191 assert.Equal(t, fmt.Sprintf("%s/%s/%s", "machine", metricSet.Labels[core.LabelNodename.Key], metricName), m.ID) 192 193 // 194 metricSet.Labels[core.LabelMetricSetType.Key] = core.MetricSetTypePod 195 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 196 assert.NoError(t, err) 197 assert.Equal(t, fmt.Sprintf("%s/%s/%s", core.MetricSetTypePod, metricSet.Labels[core.LabelPodId.Key], metricName), m.ID) 198 199 // 200 metricSet.Labels[core.LabelMetricSetType.Key] = core.MetricSetTypePodContainer 201 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 202 assert.NoError(t, err) 203 assert.Equal(t, fmt.Sprintf("%s/%s/%s", metricSet.Labels[core.LabelContainerName.Key], metricSet.Labels[core.LabelPodId.Key], metricName), m.ID) 204 205 // 206 metricSet.Labels[core.LabelMetricSetType.Key] = core.MetricSetTypeSystemContainer 207 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 208 assert.NoError(t, err) 209 assert.Equal(t, fmt.Sprintf("%s/%s/%s/%s", core.MetricSetTypeSystemContainer, metricSet.Labels[core.LabelContainerName.Key], metricSet.Labels[core.LabelPodId.Key], metricName), m.ID) 210 211 // 212 metricSet.Labels[core.LabelMetricSetType.Key] = core.MetricSetTypeCluster 213 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 214 assert.NoError(t, err) 215 assert.Equal(t, fmt.Sprintf("%s/%s", core.MetricSetTypeCluster, metricName), m.ID) 216 217 // 218 metricSet.Labels[core.LabelMetricSetType.Key] = core.MetricSetTypeNamespace 219 m, err = hSink.pointToLabeledMetricHeader(&metricSet, metricSet.LabeledMetrics[0], now) 220 assert.NoError(t, err) 221 assert.Equal(t, fmt.Sprintf("%s/%s/%s", core.MetricSetTypeNamespace, metricSet.Labels[core.LabelNamespaceName.Key], metricName), m.ID) 222 223 } 224 225 func TestRecentTest(t *testing.T) { 226 hSink := dummySink() 227 228 modelT := make(map[string]string) 229 230 id := "test.name" 231 modelT[descriptorTag] = "d" 232 modelT[groupTag] = id 233 modelT["hep"+descriptionTag] = "n" 234 235 model := metrics.MetricDefinition{ 236 ID: id, 237 Tags: modelT, 238 } 239 240 liveT := make(map[string]string) 241 for k, v := range modelT { 242 liveT[k] = v 243 } 244 245 live := metrics.MetricDefinition{ 246 ID: "test/" + id, 247 Tags: liveT, 248 } 249 250 assert.True(t, hSink.recent(&live, &model), "Tags are equal, live is newest") 251 252 delete(liveT, "hep"+descriptionTag) 253 live.Tags = liveT 254 255 assert.False(t, hSink.recent(&live, &model), "Tags are not equal, live isn't recent") 256 257 } 258 259 func TestParseFiltersErrors(t *testing.T) { 260 _, err := parseFilters([]string{"(missingcommand)"}) 261 assert.Error(t, err) 262 263 _, err = parseFilters([]string{"missingeverything"}) 264 assert.Error(t, err) 265 266 _, err = parseFilters([]string{"labelstart:^missing$)"}) 267 assert.Error(t, err) 268 269 _, err = parseFilters([]string{"label(endmissing"}) 270 assert.Error(t, err) 271 272 _, err = parseFilters([]string{"label(wrongsyntax)"}) 273 assert.Error(t, err) 274 } 275 276 // Integration tests 277 func integSink(uri string) (*hawkularSink, error) { 278 279 u, err := url.Parse(uri) 280 if err != nil { 281 return nil, err 282 } 283 284 sink := &hawkularSink{ 285 uri: u, 286 } 287 if err = sink.init(); err != nil { 288 return nil, err 289 } 290 291 return sink, nil 292 } 293 294 // Test that Definitions is called for Gauges & Counters 295 // Test that we have single registered model 296 // Test that the tags for metric is updated.. 297 func TestRegister(t *testing.T) { 298 m := &sync.Mutex{} 299 // definitionsCalled := make(map[string]bool) 300 updateTagsCalled := false 301 requests := 0 302 303 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 304 m.Lock() 305 defer m.Unlock() 306 w.Header().Set("Content-Type", "application/json") 307 308 if strings.Contains(r.RequestURI, "tenants") { 309 fmt.Fprintln(w, `[{ "id": "test-heapster"},{"id": "fgahj-fgas-basf-gegsg" }]`) 310 } else { 311 tenant := r.Header.Get("Hawkular-Tenant") 312 if tenant != "test-heapster" { 313 requests++ 314 w.WriteHeader(http.StatusNoContent) 315 return 316 } 317 if strings.Contains(r.RequestURI, "metrics?tags=descriptor_name%3A%2A") || strings.Contains(r.RequestURI, "openshift") { 318 requests++ 319 fmt.Fprintln(w, `[{ "id": "test.create.gauge.1", "tenantId": "test-heapster", "type": "gauge", "tags": { "descriptor_name": "test/metric/1" } }]`) 320 } else if strings.Contains(r.RequestURI, "/tags") && r.Method == "PUT" { 321 updateTagsCalled = true 322 defer r.Body.Close() 323 b, err := ioutil.ReadAll(r.Body) 324 assert.NoError(t, err) 325 326 tags := make(map[string]string) 327 err = json.Unmarshal(b, &tags) 328 assert.NoError(t, err) 329 330 _, kt1 := tags["k1_description"] 331 _, dt := tags["descriptor_name"] 332 333 assert.True(t, kt1, "k1_description tag is missing") 334 assert.True(t, dt, "descriptor_name is missing") 335 336 w.WriteHeader(http.StatusOK) 337 } 338 } 339 })) 340 defer s.Close() 341 342 hSink, err := integSink(s.URL + "?tenant=test-heapster") 343 assert.NoError(t, err) 344 345 md := make([]core.MetricDescriptor, 0, 1) 346 ld := core.LabelDescriptor{ 347 Key: "k1", 348 Description: "d1", 349 } 350 smd := core.MetricDescriptor{ 351 Name: "test/metric/1", 352 Units: core.UnitsBytes, 353 ValueType: core.ValueInt64, 354 Type: core.MetricGauge, 355 Labels: []core.LabelDescriptor{ld}, 356 } 357 smdg := core.MetricDescriptor{ 358 Name: "test/metric/2", 359 Units: core.UnitsBytes, 360 ValueType: core.ValueFloat, 361 Type: core.MetricCumulative, 362 Labels: []core.LabelDescriptor{}, 363 } 364 365 md = append(md, smd, smdg) 366 367 err = hSink.Register(md) 368 assert.NoError(t, err) 369 370 assert.Equal(t, 2, len(hSink.models)) 371 assert.Equal(t, 1, len(hSink.expReg)) 372 373 assert.True(t, updateTagsCalled, "Updating outdated tags was not called") 374 assert.Equal(t, 1, requests) 375 376 // Try without pre caching 377 updateTagsCalled = false 378 379 hSink, err = integSink(s.URL + "?tenant=test-heapster&disablePreCache=true") 380 assert.NoError(t, err) 381 382 err = hSink.Register(md) 383 assert.NoError(t, err) 384 385 assert.Equal(t, 2, len(hSink.models)) 386 assert.Equal(t, 0, len(hSink.expReg)) 387 388 assert.False(t, updateTagsCalled, "Updating outdated tags was called") 389 } 390 391 // Store timeseries with both gauges and cumulatives 392 func TestStoreTimeseries(t *testing.T) { 393 m := &sync.Mutex{} 394 ids := make([]string, 0, 2) 395 calls := make([]string, 0, 2) 396 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 397 m.Lock() 398 defer m.Unlock() 399 calls = append(calls, r.RequestURI) 400 w.Header().Set("Content-Type", "application/json") 401 402 typ := r.RequestURI[strings.Index(r.RequestURI, "hawkular/metrics/")+17:] 403 typ = typ[:len(typ)-4] 404 405 switch typ { 406 case "counters": 407 assert.Equal(t, "test-label", r.Header.Get("Hawkular-Tenant")) 408 break 409 case "gauges": 410 assert.Equal(t, "test-heapster", r.Header.Get("Hawkular-Tenant")) 411 break 412 default: 413 assert.FailNow(t, "Unrecognized type "+typ) 414 } 415 416 defer r.Body.Close() 417 b, err := ioutil.ReadAll(r.Body) 418 assert.NoError(t, err) 419 420 mH := []metrics.MetricHeader{} 421 err = json.Unmarshal(b, &mH) 422 assert.NoError(t, err) 423 424 assert.Equal(t, 1, len(mH)) 425 426 ids = append(ids, mH[0].ID) 427 })) 428 defer s.Close() 429 430 hSink, err := integSink(s.URL + "?tenant=test-heapster&labelToTenant=projectId") 431 assert.NoError(t, err) 432 433 l := make(map[string]string) 434 l["projectId"] = "test-label" 435 l[core.LabelContainerName.Key] = "test-container" 436 l[core.LabelPodId.Key] = "test-podid" 437 438 lg := make(map[string]string) 439 lg[core.LabelContainerName.Key] = "test-container" 440 lg[core.LabelPodId.Key] = "test-podid" 441 442 metricSet1 := core.MetricSet{ 443 Labels: l, 444 MetricValues: map[string]core.MetricValue{ 445 "test/metric/1": { 446 ValueType: core.ValueInt64, 447 MetricType: core.MetricCumulative, 448 IntValue: 123456, 449 }, 450 }, 451 } 452 453 metricSet2 := core.MetricSet{ 454 Labels: lg, 455 MetricValues: map[string]core.MetricValue{ 456 "test/metric/2": { 457 ValueType: core.ValueFloat, 458 MetricType: core.MetricGauge, 459 FloatValue: 123.456, 460 }, 461 }, 462 } 463 464 data := core.DataBatch{ 465 Timestamp: time.Now(), 466 MetricSets: map[string]*core.MetricSet{ 467 "pod1": &metricSet1, 468 "pod2": &metricSet2, 469 }, 470 } 471 472 hSink.ExportData(&data) 473 assert.Equal(t, 2, len(calls)) 474 assert.Equal(t, 2, len(ids)) 475 476 assert.NotEqual(t, ids[0], ids[1]) 477 } 478 479 func TestTags(t *testing.T) { 480 m := &sync.Mutex{} 481 calls := make([]string, 0, 2) 482 serverTags := make(map[string]string) 483 // how many times tags have been updated 484 tagsUpdated := 0 485 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 486 m.Lock() 487 defer m.Unlock() 488 calls = append(calls, r.RequestURI) 489 w.Header().Set("Content-Type", "application/json") 490 491 defer r.Body.Close() 492 b, err := ioutil.ReadAll(r.Body) 493 assert.NoError(t, err) 494 495 if strings.HasSuffix(r.RequestURI, "/tags") { 496 err := json.Unmarshal(b, &serverTags) 497 assert.NoError(t, err) 498 tagsUpdated++ 499 } 500 })) 501 defer s.Close() 502 503 hSink, err := integSink(s.URL + "?tenant=test-heapster&labelToTenant=projectId") 504 assert.NoError(t, err) 505 506 l := make(map[string]string) 507 l["projectId"] = "test-label" 508 l[core.LabelContainerName.Key] = "test-container" 509 l[core.LabelPodId.Key] = "test-podid" 510 l[core.LabelLabels.Key] = "testLabelA:testValueA,testLabelB:testValueB" 511 512 labeledMetric := core.LabeledMetric{ 513 Name: "test/metric/A", 514 Labels: map[string]string{ 515 core.LabelResourceID.Key: "XYZ", 516 }, 517 MetricValue: core.MetricValue{ 518 MetricType: core.MetricGauge, 519 FloatValue: 124.456, 520 }, 521 } 522 523 metricSet := core.MetricSet{ 524 Labels: l, 525 LabeledMetrics: []core.LabeledMetric{labeledMetric}, 526 MetricValues: map[string]core.MetricValue{ 527 "test/metric/A": { 528 ValueType: core.ValueInt64, 529 MetricType: core.MetricCumulative, 530 IntValue: 123456, 531 }, 532 }, 533 } 534 535 smd := core.MetricDescriptor{ 536 Name: "test/metric/A", 537 Units: core.UnitsBytes, 538 ValueType: core.ValueInt64, 539 Type: core.MetricGauge, 540 Labels: []core.LabelDescriptor{}, 541 } 542 543 //register the metric definitions 544 hSink.Register([]core.MetricDescriptor{smd}) 545 //register the metrics themselves 546 wg := &sync.WaitGroup{} 547 hSink.registerLabeledIfNecessaryInline(&metricSet, labeledMetric, wg) 548 549 wg.Wait() 550 assert.Equal(t, 1, tagsUpdated) 551 552 assert.True(t, hSink.expReg["test-container/test-podid/test/metric/A/XYZ"].hash > 0) 553 554 assert.Equal(t, 10, len(serverTags)) 555 assert.Equal(t, "test-label", serverTags["projectId"]) 556 assert.Equal(t, "test-container", serverTags[core.LabelContainerName.Key]) 557 assert.Equal(t, "test-podid", serverTags[core.LabelPodId.Key]) 558 assert.Equal(t, "test-container/test/metric/A", serverTags["group_id"]) 559 assert.Equal(t, "test/metric/A", serverTags["descriptor_name"]) 560 assert.Equal(t, "XYZ", serverTags[core.LabelResourceID.Key]) 561 assert.Equal(t, "bytes", serverTags["units"]) 562 563 assert.Equal(t, "testLabelA:testValueA,testLabelB:testValueB", serverTags[core.LabelLabels.Key]) 564 assert.Equal(t, "testValueA", serverTags["labels.testLabelA"]) 565 assert.Equal(t, "testValueB", serverTags["labels.testLabelB"]) 566 567 // Make modifications to the metrics and check that they're updated correctly 568 569 // First, no changes - no update should happen 570 hSink.registerLabeledIfNecessaryInline(&metricSet, labeledMetric, wg) 571 wg.Wait() 572 assert.Equal(t, 1, tagsUpdated) 573 574 // Now modify the labels and expect an update 575 metricSet.Labels[core.LabelLabels.Key] = "testLabelA:testValueA,testLabelB:testValueB,testLabelC:testValueC" 576 hSink.registerLabeledIfNecessaryInline(&metricSet, labeledMetric, wg) 577 wg.Wait() 578 assert.Equal(t, 2, tagsUpdated) 579 580 assert.Equal(t, "testLabelA:testValueA,testLabelB:testValueB,testLabelC:testValueC", serverTags[core.LabelLabels.Key]) 581 assert.Equal(t, "testValueA", serverTags["labels.testLabelA"]) 582 assert.Equal(t, "testValueB", serverTags["labels.testLabelB"]) 583 assert.Equal(t, "testValueC", serverTags["labels.testLabelC"]) 584 } 585 586 func TestExpiringCache(t *testing.T) { 587 total := 10 588 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 589 w.WriteHeader(http.StatusOK) 590 })) 591 defer s.Close() 592 593 hSink, err := integSink(s.URL + "?tenant=test-heapster&labelToTenant=projectId&batchSize=20&concurrencyLimit=5") 594 assert.NoError(t, err) 595 596 l := make(map[string]string) 597 l["projectId"] = "test-label" 598 l[core.LabelContainerName.Key] = "test-container" 599 l[core.LabelPodId.Key] = "test-podid" 600 601 metrics := make(map[string]core.MetricValue, total) 602 descriptors := make([]core.MetricDescriptor, total) 603 for i := 0; i < total; i++ { 604 id := fmt.Sprintf("test/metric/%d", i) 605 metrics[id] = core.MetricValue{ 606 ValueType: core.ValueInt64, 607 MetricType: core.MetricCumulative, 608 IntValue: 123 * int64(i), 609 } 610 descriptors = append(descriptors, core.MetricDescriptor{ 611 Name: id, 612 Units: core.UnitsBytes, 613 ValueType: core.ValueInt64, 614 Type: core.MetricGauge, 615 }) 616 } 617 618 err = hSink.Register(descriptors) 619 assert.NoError(t, err) 620 621 metricSet := core.MetricSet{ 622 Labels: l, 623 MetricValues: metrics, 624 } 625 626 data := core.DataBatch{ 627 Timestamp: time.Now(), 628 MetricSets: map[string]*core.MetricSet{ 629 "pod1": &metricSet, 630 }, 631 } 632 633 hSink.ExportData(&data) 634 hSink.regLock.RLock() 635 assert.Equal(t, total, len(hSink.expReg)) 636 assert.Equal(t, uint64(1), hSink.expReg["test-container/test-podid/test/metric/9"].ttl) 637 hSink.regLock.RUnlock() 638 639 // Now delete part of the metrics and then check that they're expired 640 delete(metrics, "test/metric/1") 641 delete(metrics, "test/metric/6") 642 643 data.Timestamp = time.Now() 644 hSink.ExportData(&data) 645 hSink.regLock.RLock() 646 assert.Equal(t, total, len(hSink.expReg)) 647 assert.Equal(t, uint64(2), hSink.expReg["test-container/test-podid/test/metric/9"].ttl) 648 hSink.regLock.RUnlock() 649 650 data.Timestamp = time.Now() 651 hSink.ExportData(&data) 652 hSink.regLock.RLock() 653 assert.Equal(t, total-2, len(hSink.expReg)) 654 hSink.regLock.RUnlock() 655 } 656 657 func TestUserPass(t *testing.T) { 658 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 659 w.Header().Set("X-Authorization", r.Header.Get("Authorization")) 660 auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2) 661 if len(auth) != 2 || auth[0] != "Basic" { 662 assert.FailNow(t, "Could not find Basic authentication") 663 } 664 assert.True(t, len(auth[1]) > 0) 665 w.WriteHeader(http.StatusNoContent) 666 })) 667 defer s.Close() 668 669 hSink, err := integSink(s.URL + "?user=tester&pass=hidden") 670 assert.NoError(t, err) 671 assert.Equal(t, 1, len(hSink.modifiers)) 672 673 // md := make([]core.MetricDescriptor, 0, 1) 674 ld := core.LabelDescriptor{ 675 Key: "k1", 676 Description: "d1", 677 } 678 smd := core.MetricDescriptor{ 679 Name: "test/metric/1", 680 Units: core.UnitsBytes, 681 ValueType: core.ValueInt64, 682 Type: core.MetricGauge, 683 Labels: []core.LabelDescriptor{ld}, 684 } 685 err = hSink.Register([]core.MetricDescriptor{smd}) 686 assert.NoError(t, err) 687 } 688 689 func TestFiltering(t *testing.T) { 690 m := &sync.Mutex{} 691 mH := []metrics.MetricHeader{} 692 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 693 m.Lock() 694 defer m.Unlock() 695 if strings.Contains(r.RequestURI, "raw") { 696 defer r.Body.Close() 697 b, err := ioutil.ReadAll(r.Body) 698 assert.NoError(t, err) 699 700 err = json.Unmarshal(b, &mH) 701 assert.NoError(t, err) 702 } 703 })) 704 defer s.Close() 705 706 hSink, err := integSink(s.URL + "?filter=label(namespace_id:^$)&filter=label(container_name:^[/system.slice/|/user.slice].*)&filter=name(remove*)") 707 assert.NoError(t, err) 708 709 l := make(map[string]string) 710 l["namespace_id"] = "123" 711 l["container_name"] = "/system.slice/-.mount" 712 l[core.LabelPodId.Key] = "aaaa-bbbb-cccc-dddd" 713 714 l2 := make(map[string]string) 715 l2["namespace_id"] = "123" 716 l2["container_name"] = "/system.slice/dbus.service" 717 l2[core.LabelPodId.Key] = "aaaa-bbbb-cccc-dddd" 718 719 l3 := make(map[string]string) 720 l3["namespace_id"] = "123" 721 l3[core.LabelPodId.Key] = "aaaa-bbbb-cccc-dddd" 722 723 l4 := make(map[string]string) 724 l4["namespace_id"] = "" 725 l4[core.LabelPodId.Key] = "aaaa-bbbb-cccc-dddd" 726 727 l5 := make(map[string]string) 728 l5["namespace_id"] = "123" 729 l5[core.LabelPodId.Key] = "aaaa-bbbb-cccc-dddd" 730 731 metricSet1 := core.MetricSet{ 732 Labels: l, 733 MetricValues: map[string]core.MetricValue{ 734 "/system.slice/-.mount//cpu/limit": { 735 ValueType: core.ValueInt64, 736 MetricType: core.MetricCumulative, 737 IntValue: 123456, 738 }, 739 }, 740 } 741 742 metricSet2 := core.MetricSet{ 743 Labels: l2, 744 MetricValues: map[string]core.MetricValue{ 745 "/system.slice/dbus.service//cpu/usage": { 746 ValueType: core.ValueInt64, 747 MetricType: core.MetricCumulative, 748 IntValue: 123456, 749 }, 750 }, 751 } 752 753 metricSet3 := core.MetricSet{ 754 Labels: l3, 755 MetricValues: map[string]core.MetricValue{ 756 "test/metric/1": { 757 ValueType: core.ValueInt64, 758 MetricType: core.MetricCumulative, 759 IntValue: 123456, 760 }, 761 }, 762 } 763 764 metricSet4 := core.MetricSet{ 765 Labels: l4, 766 MetricValues: map[string]core.MetricValue{ 767 "test/metric/1": { 768 ValueType: core.ValueInt64, 769 MetricType: core.MetricCumulative, 770 IntValue: 123456, 771 }, 772 }, 773 } 774 775 metricSet5 := core.MetricSet{ 776 Labels: l5, 777 MetricValues: map[string]core.MetricValue{ 778 "removeme": { 779 ValueType: core.ValueInt64, 780 MetricType: core.MetricCumulative, 781 IntValue: 123456, 782 }, 783 }, 784 } 785 786 data := core.DataBatch{ 787 Timestamp: time.Now(), 788 MetricSets: map[string]*core.MetricSet{ 789 "pod1": &metricSet1, 790 "pod2": &metricSet2, 791 "pod3": &metricSet3, 792 "pod4": &metricSet4, 793 "pod5": &metricSet5, 794 }, 795 } 796 hSink.ExportData(&data) 797 798 assert.Equal(t, 1, len(mH)) 799 } 800 func TestBatchingTimeseries(t *testing.T) { 801 total := 1000 802 m := &sync.Mutex{} 803 ids := make([]string, 0, total) 804 calls := 0 805 806 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 807 m.Lock() 808 defer m.Unlock() 809 810 w.Header().Set("Content-Type", "application/json") 811 812 defer r.Body.Close() 813 b, err := ioutil.ReadAll(r.Body) 814 assert.NoError(t, err) 815 816 mH := []metrics.MetricHeader{} 817 err = json.Unmarshal(b, &mH) 818 assert.NoError(t, err) 819 820 for _, v := range mH { 821 ids = append(ids, v.ID) 822 } 823 824 calls++ 825 })) 826 defer s.Close() 827 828 hSink, err := integSink(s.URL + "?tenant=test-heapster&labelToTenant=projectId&batchSize=20&concurrencyLimit=5") 829 assert.NoError(t, err) 830 831 l := make(map[string]string) 832 l["projectId"] = "test-label" 833 l[core.LabelContainerName.Key] = "test-container" 834 l[core.LabelPodId.Key] = "test-podid" 835 836 metrics := make(map[string]core.MetricValue) 837 for i := 0; i < total; i++ { 838 id := fmt.Sprintf("test/metric/%d", i) 839 metrics[id] = core.MetricValue{ 840 ValueType: core.ValueInt64, 841 MetricType: core.MetricCumulative, 842 IntValue: 123 * int64(i), 843 } 844 } 845 846 metricSet := core.MetricSet{ 847 Labels: l, 848 MetricValues: metrics, 849 } 850 851 data := core.DataBatch{ 852 Timestamp: time.Now(), 853 MetricSets: map[string]*core.MetricSet{ 854 "pod1": &metricSet, 855 }, 856 } 857 858 hSink.ExportData(&data) 859 assert.Equal(t, total, len(ids)) 860 assert.Equal(t, calls, 50) 861 862 // Verify that all ids are unique 863 newIds := make(map[string]bool) 864 for _, v := range ids { 865 if newIds[v] { 866 t.Errorf("Key %s was duplicate", v) 867 } 868 newIds[v] = true 869 } 870 } 871 872 func BenchmarkTagsUpdates(b *testing.B) { 873 http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = 100 874 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 875 w.WriteHeader(http.StatusOK) 876 })) 877 defer s.Close() 878 hSink, err := integSink(s.URL + "?tenant=test-heapster&labelToTenant=projectId&batchSize=1000&concurrencyLimit=16") 879 if err != nil { 880 b.FailNow() 881 } 882 883 smd := core.MetricDescriptor{ 884 Name: "test/metric/A", 885 Units: core.UnitsBytes, 886 ValueType: core.ValueInt64, 887 Type: core.MetricGauge, 888 Labels: []core.LabelDescriptor{}, 889 } 890 891 //register the metric definitions 892 hSink.Register([]core.MetricDescriptor{smd}) 893 total := 10000 894 895 mset := make(map[string]*core.MetricSet) 896 for i := 0; i < total; i++ { 897 id := fmt.Sprintf("pod-%d", i) 898 899 l := make(map[string]string) 900 l["projectId"] = strconv.Itoa(i) 901 for i := 0; i < 32; i++ { 902 tagName := fmt.Sprintf("tag_name_%d", i) 903 tagValue := fmt.Sprintf("tag_value_%d", i) 904 l[tagName] = tagValue 905 l[core.LabelPodId.Key] = id 906 } 907 908 metrics := make(map[string]core.MetricValue) 909 metrics["test/metric/A"] = core.MetricValue{ 910 ValueType: core.ValueInt64, 911 MetricType: core.MetricCumulative, 912 IntValue: 123, 913 } 914 915 metricSet := core.MetricSet{ 916 Labels: l, 917 MetricValues: metrics, 918 } 919 mset[id] = &metricSet 920 } 921 922 data := core.DataBatch{ 923 Timestamp: time.Now(), 924 MetricSets: mset, 925 } 926 927 fmt.Printf("Generated data with %d metricSets\n", len(data.MetricSets)) 928 hSink.init() 929 hSink.Register([]core.MetricDescriptor{smd}) 930 b.ResetTimer() 931 for j := 0; j < b.N; j++ { 932 for a := 0; a < 10; a++ { 933 data.Timestamp = time.Now() 934 hSink.ExportData(&data) 935 } 936 } 937 938 fmt.Printf("Amount of unique definitions: %d\n", len(hSink.expReg)) 939 }