github.com/prebid/prebid-server@v0.275.0/metrics/prometheus/prometheus_test.go (about) 1 package prometheusmetrics 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/prebid/prebid-server/config" 9 "github.com/prebid/prebid-server/metrics" 10 "github.com/prebid/prebid-server/openrtb_ext" 11 "github.com/prometheus/client_golang/prometheus" 12 dto "github.com/prometheus/client_model/go" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 var modulesStages = map[string][]string{"foobar": {"entry", "raw"}, "another_module": {"raw", "auction"}} 17 18 func createMetricsForTesting() *Metrics { 19 syncerKeys := []string{} 20 return NewMetrics(config.PrometheusMetrics{ 21 Port: 8080, 22 Namespace: "prebid", 23 Subsystem: "server", 24 }, config.DisabledMetrics{}, syncerKeys, modulesStages) 25 } 26 27 func TestMetricCountGatekeeping(t *testing.T) { 28 m := createMetricsForTesting() 29 30 // Gather All Metrics 31 metricFamilies, err := m.Gatherer.Gather() 32 assert.NoError(t, err, "gather metics") 33 34 // Summarize By Adapter Cardinality 35 // - This requires metrics to be preloaded. We don't preload account metrics, so we can't test those. 36 generalCardinalityCount := 0 37 adapterCardinalityCount := 0 38 for _, metricFamily := range metricFamilies { 39 for _, metric := range metricFamily.GetMetric() { 40 isPerAdapter := false 41 for _, label := range metric.GetLabel() { 42 if label.GetName() == adapterLabel { 43 isPerAdapter = true 44 } 45 } 46 47 if isPerAdapter { 48 adapterCardinalityCount++ 49 } else { 50 generalCardinalityCount++ 51 } 52 } 53 } 54 55 // Calculate Per-Adapter Cardinality 56 adapterCount := len(openrtb_ext.CoreBidderNames()) 57 perAdapterCardinalityCount := adapterCardinalityCount / adapterCount 58 // Verify General Cardinality 59 // - This assertion provides a warning for newly added high-cardinality non-adapter specific metrics. The hardcoded limit 60 // is an arbitrary soft ceiling. Thought should be given as to the value of the new metrics if you find yourself 61 // needing to increase this number. 62 assert.True(t, generalCardinalityCount <= 500, "General Cardinality") 63 64 // Verify Per-Adapter Cardinality 65 // - This assertion provides a warning for newly added adapter metrics. Threre are 40+ adapters which makes the 66 // cost of new per-adapter metrics rather expensive. Thought should be given when adding new per-adapter metrics. 67 assert.True(t, perAdapterCardinalityCount <= 29, "Per-Adapter Cardinality count equals %d \n", perAdapterCardinalityCount) 68 } 69 70 func TestConnectionMetrics(t *testing.T) { 71 testCases := []struct { 72 description string 73 testCase func(m *Metrics) 74 expectedOpenedCount float64 75 expectedOpenedErrorCount float64 76 expectedClosedCount float64 77 expectedClosedErrorCount float64 78 }{ 79 { 80 description: "Open Success", 81 testCase: func(m *Metrics) { 82 m.RecordConnectionAccept(true) 83 }, 84 expectedOpenedCount: 1, 85 expectedOpenedErrorCount: 0, 86 expectedClosedCount: 0, 87 expectedClosedErrorCount: 0, 88 }, 89 { 90 description: "Open Error", 91 testCase: func(m *Metrics) { 92 m.RecordConnectionAccept(false) 93 }, 94 expectedOpenedCount: 0, 95 expectedOpenedErrorCount: 1, 96 expectedClosedCount: 0, 97 expectedClosedErrorCount: 0, 98 }, 99 { 100 description: "Closed Success", 101 testCase: func(m *Metrics) { 102 m.RecordConnectionClose(true) 103 }, 104 expectedOpenedCount: 0, 105 expectedOpenedErrorCount: 0, 106 expectedClosedCount: 1, 107 expectedClosedErrorCount: 0, 108 }, 109 { 110 description: "Closed Error", 111 testCase: func(m *Metrics) { 112 m.RecordConnectionClose(false) 113 }, 114 expectedOpenedCount: 0, 115 expectedOpenedErrorCount: 0, 116 expectedClosedCount: 0, 117 expectedClosedErrorCount: 1, 118 }, 119 } 120 121 for _, test := range testCases { 122 m := createMetricsForTesting() 123 124 test.testCase(m) 125 126 assertCounterValue(t, test.description, "connectionsClosed", m.connectionsClosed, 127 test.expectedClosedCount) 128 assertCounterValue(t, test.description, "connectionsOpened", m.connectionsOpened, 129 test.expectedOpenedCount) 130 assertCounterVecValue(t, test.description, "connectionsError[type=accept]", m.connectionsError, 131 test.expectedOpenedErrorCount, prometheus.Labels{ 132 connectionErrorLabel: connectionAcceptError, 133 }) 134 assertCounterVecValue(t, test.description, "connectionsError[type=close]", m.connectionsError, 135 test.expectedClosedErrorCount, prometheus.Labels{ 136 connectionErrorLabel: connectionCloseError, 137 }) 138 } 139 } 140 141 func TestRequestMetric(t *testing.T) { 142 m := createMetricsForTesting() 143 requestType := metrics.ReqTypeORTB2Web 144 requestStatus := metrics.RequestStatusBlacklisted 145 146 m.RecordRequest(metrics.Labels{ 147 RType: requestType, 148 RequestStatus: requestStatus, 149 }) 150 151 expectedCount := float64(1) 152 assertCounterVecValue(t, "", "requests", m.requests, 153 expectedCount, 154 prometheus.Labels{ 155 requestTypeLabel: string(requestType), 156 requestStatusLabel: string(requestStatus), 157 }) 158 } 159 160 func TestDebugRequestMetric(t *testing.T) { 161 testCases := []struct { 162 description string 163 givenDebugEnabledFlag bool 164 givenAccountDebugMetricsDisabled bool 165 expectedAccountDebugCount float64 166 expectedDebugCount float64 167 }{ 168 { 169 description: "Debug is enabled and account debug is enabled, both metrics should be updated", 170 givenDebugEnabledFlag: true, 171 givenAccountDebugMetricsDisabled: false, 172 expectedDebugCount: 1, 173 expectedAccountDebugCount: 1, 174 }, 175 { 176 description: "Debug and account debug are disabled, niether metrics should be updated", 177 givenDebugEnabledFlag: false, 178 givenAccountDebugMetricsDisabled: true, 179 expectedDebugCount: 0, 180 expectedAccountDebugCount: 0, 181 }, 182 { 183 description: "Debug is enabled but account debug is disabled, only non-account debug count should increment", 184 givenDebugEnabledFlag: true, 185 givenAccountDebugMetricsDisabled: true, 186 expectedDebugCount: 1, 187 expectedAccountDebugCount: 0, 188 }, 189 { 190 description: "Debug is disabled and account debug is enabled, niether metrics should increment", 191 givenDebugEnabledFlag: false, 192 givenAccountDebugMetricsDisabled: false, 193 expectedDebugCount: 0, 194 expectedAccountDebugCount: 0, 195 }, 196 } 197 198 for _, test := range testCases { 199 m := createMetricsForTesting() 200 m.metricsDisabled.AccountDebug = test.givenAccountDebugMetricsDisabled 201 m.RecordDebugRequest(test.givenDebugEnabledFlag, "acct-id") 202 203 assertCounterVecValue(t, "", "account debug requests", m.accountDebugRequests, test.expectedAccountDebugCount, prometheus.Labels{accountLabel: "acct-id"}) 204 assertCounterValue(t, "", "debug requests", m.debugRequests, test.expectedDebugCount) 205 } 206 } 207 208 func TestBidValidationCreativeSizeMetric(t *testing.T) { 209 testCases := []struct { 210 description string 211 givenDebugEnabledFlag bool 212 givenAccountAdapterMetricsDisabled bool 213 expectedAdapterCount float64 214 expectedAccountCount float64 215 }{ 216 { 217 description: "Account Metric isn't disabled, so both metrics should be incremented", 218 givenAccountAdapterMetricsDisabled: false, 219 expectedAdapterCount: 1, 220 expectedAccountCount: 1, 221 }, 222 { 223 description: "Account Metric is disabled, so only adapter metric should be incremented", 224 givenAccountAdapterMetricsDisabled: true, 225 expectedAdapterCount: 1, 226 expectedAccountCount: 0, 227 }, 228 } 229 230 for _, test := range testCases { 231 m := createMetricsForTesting() 232 m.metricsDisabled.AccountAdapterDetails = test.givenAccountAdapterMetricsDisabled 233 m.RecordBidValidationCreativeSizeError(adapterLabel, "acct-id") 234 m.RecordBidValidationCreativeSizeWarn(adapterLabel, "acct-id") 235 236 assertCounterVecValue(t, "", "account bid validation", m.accountBidResponseValidationSizeError, test.expectedAccountCount, prometheus.Labels{accountLabel: "acct-id", successLabel: successLabel}) 237 assertCounterVecValue(t, "", "adapter bid validation", m.adapterBidResponseValidationSizeError, test.expectedAdapterCount, prometheus.Labels{adapterLabel: adapterLabel, successLabel: successLabel}) 238 239 assertCounterVecValue(t, "", "account bid validation", m.accountBidResponseValidationSizeWarn, test.expectedAccountCount, prometheus.Labels{accountLabel: "acct-id", successLabel: successLabel}) 240 assertCounterVecValue(t, "", "adapter bid validation", m.adapterBidResponseValidationSizeWarn, test.expectedAdapterCount, prometheus.Labels{adapterLabel: adapterLabel, successLabel: successLabel}) 241 } 242 } 243 244 func TestBidValidationSecureMarkupMetric(t *testing.T) { 245 testCases := []struct { 246 description string 247 givenDebugEnabledFlag bool 248 givenAccountAdapterMetricsDisabled bool 249 expectedAdapterCount float64 250 expectedAccountCount float64 251 }{ 252 { 253 description: "Account Metric isn't disabled, so both metrics should be incremented", 254 givenAccountAdapterMetricsDisabled: false, 255 expectedAdapterCount: 1, 256 expectedAccountCount: 1, 257 }, 258 { 259 description: "Account Metric is disabled, so only adapter metric should be incremented", 260 givenAccountAdapterMetricsDisabled: true, 261 expectedAdapterCount: 1, 262 expectedAccountCount: 0, 263 }, 264 } 265 266 for _, test := range testCases { 267 m := createMetricsForTesting() 268 m.metricsDisabled.AccountAdapterDetails = test.givenAccountAdapterMetricsDisabled 269 m.RecordBidValidationSecureMarkupError(adapterLabel, "acct-id") 270 m.RecordBidValidationSecureMarkupWarn(adapterLabel, "acct-id") 271 272 assertCounterVecValue(t, "", "Account Secure Markup Error", m.accountBidResponseSecureMarkupError, test.expectedAccountCount, prometheus.Labels{accountLabel: "acct-id", successLabel: successLabel}) 273 assertCounterVecValue(t, "", "Adapter Secure Markup Error", m.adapterBidResponseSecureMarkupError, test.expectedAdapterCount, prometheus.Labels{adapterLabel: adapterLabel, successLabel: successLabel}) 274 275 assertCounterVecValue(t, "", "Account Secure Markup Warn", m.accountBidResponseSecureMarkupWarn, test.expectedAccountCount, prometheus.Labels{accountLabel: "acct-id", successLabel: successLabel}) 276 assertCounterVecValue(t, "", "Adapter Secure Markup Warn", m.adapterBidResponseSecureMarkupWarn, test.expectedAdapterCount, prometheus.Labels{adapterLabel: adapterLabel, successLabel: successLabel}) 277 } 278 } 279 280 func TestRequestMetricWithoutCookie(t *testing.T) { 281 requestType := metrics.ReqTypeORTB2Web 282 performTest := func(m *Metrics, cookieFlag metrics.CookieFlag) { 283 m.RecordRequest(metrics.Labels{ 284 RType: requestType, 285 RequestStatus: metrics.RequestStatusBlacklisted, 286 CookieFlag: cookieFlag, 287 }) 288 } 289 290 testCases := []struct { 291 description string 292 testCase func(m *Metrics) 293 cookieFlag metrics.CookieFlag 294 expectedCount float64 295 }{ 296 { 297 description: "Yes", 298 testCase: func(m *Metrics) { 299 performTest(m, metrics.CookieFlagYes) 300 }, 301 expectedCount: 0, 302 }, 303 { 304 description: "No", 305 testCase: func(m *Metrics) { 306 performTest(m, metrics.CookieFlagNo) 307 }, 308 expectedCount: 1, 309 }, 310 { 311 description: "Unknown", 312 testCase: func(m *Metrics) { 313 performTest(m, metrics.CookieFlagUnknown) 314 }, 315 expectedCount: 0, 316 }, 317 } 318 319 for _, test := range testCases { 320 m := createMetricsForTesting() 321 322 test.testCase(m) 323 324 assertCounterVecValue(t, test.description, "requestsWithoutCookie", m.requestsWithoutCookie, 325 test.expectedCount, 326 prometheus.Labels{ 327 requestTypeLabel: string(requestType), 328 }) 329 } 330 } 331 332 func TestAccountMetric(t *testing.T) { 333 knownPubID := "knownPublisher" 334 performTest := func(m *Metrics, pubID string) { 335 m.RecordRequest(metrics.Labels{ 336 RType: metrics.ReqTypeORTB2Web, 337 RequestStatus: metrics.RequestStatusBlacklisted, 338 PubID: pubID, 339 }) 340 } 341 342 testCases := []struct { 343 description string 344 testCase func(m *Metrics) 345 expectedCount float64 346 }{ 347 { 348 description: "Known", 349 testCase: func(m *Metrics) { 350 performTest(m, knownPubID) 351 }, 352 expectedCount: 1, 353 }, 354 { 355 description: "Unknown", 356 testCase: func(m *Metrics) { 357 performTest(m, metrics.PublisherUnknown) 358 }, 359 expectedCount: 0, 360 }, 361 } 362 363 for _, test := range testCases { 364 m := createMetricsForTesting() 365 366 test.testCase(m) 367 368 assertCounterVecValue(t, test.description, "accountRequests", m.accountRequests, 369 test.expectedCount, 370 prometheus.Labels{ 371 accountLabel: knownPubID, 372 }) 373 } 374 } 375 376 func TestImpressionsMetric(t *testing.T) { 377 performTest := func(m *Metrics, isBanner, isVideo, isAudio, isNative bool) { 378 m.RecordImps(metrics.ImpLabels{ 379 BannerImps: isBanner, 380 VideoImps: isVideo, 381 AudioImps: isAudio, 382 NativeImps: isNative, 383 }) 384 } 385 386 testCases := []struct { 387 description string 388 testCase func(m *Metrics) 389 expectedBannerCount float64 390 expectedVideoCount float64 391 expectedAudioCount float64 392 expectedNativeCount float64 393 }{ 394 { 395 description: "Banner Only", 396 testCase: func(m *Metrics) { 397 performTest(m, true, false, false, false) 398 }, 399 expectedBannerCount: 1, 400 expectedVideoCount: 0, 401 expectedAudioCount: 0, 402 expectedNativeCount: 0, 403 }, 404 { 405 description: "Video Only", 406 testCase: func(m *Metrics) { 407 performTest(m, false, true, false, false) 408 }, 409 expectedBannerCount: 0, 410 expectedVideoCount: 1, 411 expectedAudioCount: 0, 412 expectedNativeCount: 0, 413 }, 414 { 415 description: "Audio Only", 416 testCase: func(m *Metrics) { 417 performTest(m, false, false, true, false) 418 }, 419 expectedBannerCount: 0, 420 expectedVideoCount: 0, 421 expectedAudioCount: 1, 422 expectedNativeCount: 0, 423 }, 424 { 425 description: "Native Only", 426 testCase: func(m *Metrics) { 427 performTest(m, false, false, false, true) 428 }, 429 expectedBannerCount: 0, 430 expectedVideoCount: 0, 431 expectedAudioCount: 0, 432 expectedNativeCount: 1, 433 }, 434 { 435 description: "Multiple Types", 436 testCase: func(m *Metrics) { 437 performTest(m, true, false, false, true) 438 }, 439 expectedBannerCount: 1, 440 expectedVideoCount: 0, 441 expectedAudioCount: 0, 442 expectedNativeCount: 1, 443 }, 444 } 445 446 for _, test := range testCases { 447 m := createMetricsForTesting() 448 449 test.testCase(m) 450 451 var bannerCount float64 452 var videoCount float64 453 var audioCount float64 454 var nativeCount float64 455 processMetrics(m.impressions, func(m dto.Metric) { 456 value := m.GetCounter().GetValue() 457 for _, label := range m.GetLabel() { 458 if label.GetValue() == "true" { 459 switch label.GetName() { 460 case isBannerLabel: 461 bannerCount += value 462 case isVideoLabel: 463 videoCount += value 464 case isAudioLabel: 465 audioCount += value 466 case isNativeLabel: 467 nativeCount += value 468 } 469 } 470 } 471 }) 472 assert.Equal(t, test.expectedBannerCount, bannerCount, test.description+":banner") 473 assert.Equal(t, test.expectedVideoCount, videoCount, test.description+":video") 474 assert.Equal(t, test.expectedAudioCount, audioCount, test.description+":audio") 475 assert.Equal(t, test.expectedNativeCount, nativeCount, test.description+":native") 476 } 477 } 478 479 func TestRequestTimeMetric(t *testing.T) { 480 requestType := metrics.ReqTypeORTB2Web 481 performTest := func(m *Metrics, requestStatus metrics.RequestStatus, timeInMs float64) { 482 m.RecordRequestTime(metrics.Labels{ 483 RType: requestType, 484 RequestStatus: requestStatus, 485 }, time.Duration(timeInMs)*time.Millisecond) 486 } 487 488 testCases := []struct { 489 description string 490 testCase func(m *Metrics) 491 expectedCount uint64 492 expectedSum float64 493 }{ 494 { 495 description: "Success", 496 testCase: func(m *Metrics) { 497 performTest(m, metrics.RequestStatusOK, 500) 498 }, 499 expectedCount: 1, 500 expectedSum: 0.5, 501 }, 502 { 503 description: "Error", 504 testCase: func(m *Metrics) { 505 performTest(m, metrics.RequestStatusErr, 500) 506 }, 507 expectedCount: 0, 508 expectedSum: 0, 509 }, 510 } 511 512 for _, test := range testCases { 513 m := createMetricsForTesting() 514 515 test.testCase(m) 516 517 result := getHistogramFromHistogramVec(m.requestsTimer, requestTypeLabel, string(requestType)) 518 assertHistogram(t, test.description, result, test.expectedCount, test.expectedSum) 519 } 520 } 521 522 func TestRecordOverheadTimeMetric(t *testing.T) { 523 testCases := []struct { 524 description string 525 overheadType metrics.OverheadType 526 timeInMs float64 527 expectedCount uint64 528 expectedSum float64 529 }{ 530 { 531 description: "record-pre-bidder-overhead-time-1", 532 overheadType: metrics.PreBidder, 533 timeInMs: 500, 534 expectedCount: 1, 535 expectedSum: 0.5, 536 }, 537 { 538 description: "record-pre-bidder-overhead-time-2", 539 overheadType: metrics.PreBidder, 540 timeInMs: 400, 541 expectedCount: 2, 542 expectedSum: 0.9, 543 }, 544 { 545 description: "record-auction-response-overhead-time", 546 overheadType: metrics.MakeAuctionResponse, 547 timeInMs: 500, 548 expectedCount: 1, 549 expectedSum: 0.5, 550 }, 551 { 552 description: "record-make-bidder-requests-overhead-time", 553 overheadType: metrics.MakeBidderRequests, 554 timeInMs: 500, 555 expectedCount: 1, 556 expectedSum: 0.5, 557 }, 558 } 559 560 metric := createMetricsForTesting() 561 for _, test := range testCases { 562 metric.RecordOverheadTime(test.overheadType, time.Duration(test.timeInMs)*time.Millisecond) 563 resultingHistogram := getHistogramFromHistogramVec(metric.overheadTimer, overheadTypeLabel, test.overheadType.String()) 564 assertHistogram(t, test.description, resultingHistogram, test.expectedCount, test.expectedSum) 565 } 566 } 567 568 func TestRecordStoredDataFetchTime(t *testing.T) { 569 tests := []struct { 570 description string 571 dataType metrics.StoredDataType 572 fetchType metrics.StoredDataFetchType 573 }{ 574 { 575 description: "Update stored account histogram with all label", 576 dataType: metrics.AccountDataType, 577 fetchType: metrics.FetchAll, 578 }, 579 { 580 description: "Update stored AMP histogram with all label", 581 dataType: metrics.AMPDataType, 582 fetchType: metrics.FetchAll, 583 }, 584 { 585 description: "Update stored category histogram with all label", 586 dataType: metrics.CategoryDataType, 587 fetchType: metrics.FetchAll, 588 }, 589 { 590 description: "Update stored request histogram with all label", 591 dataType: metrics.RequestDataType, 592 fetchType: metrics.FetchAll, 593 }, 594 { 595 description: "Update stored video histogram with all label", 596 dataType: metrics.VideoDataType, 597 fetchType: metrics.FetchAll, 598 }, 599 { 600 description: "Update stored account histogram with delta label", 601 dataType: metrics.AccountDataType, 602 fetchType: metrics.FetchDelta, 603 }, 604 { 605 description: "Update stored AMP histogram with delta label", 606 dataType: metrics.AMPDataType, 607 fetchType: metrics.FetchDelta, 608 }, 609 { 610 description: "Update stored category histogram with delta label", 611 dataType: metrics.CategoryDataType, 612 fetchType: metrics.FetchDelta, 613 }, 614 { 615 description: "Update stored request histogram with delta label", 616 dataType: metrics.RequestDataType, 617 fetchType: metrics.FetchDelta, 618 }, 619 { 620 description: "Update stored video histogram with delta label", 621 dataType: metrics.VideoDataType, 622 fetchType: metrics.FetchDelta, 623 }, 624 { 625 description: "Update stored responses histogram with delta label", 626 dataType: metrics.ResponseDataType, 627 fetchType: metrics.FetchDelta, 628 }, 629 } 630 631 for _, tt := range tests { 632 m := createMetricsForTesting() 633 634 fetchTime := time.Duration(0.5 * float64(time.Second)) 635 m.RecordStoredDataFetchTime(metrics.StoredDataLabels{ 636 DataType: tt.dataType, 637 DataFetchType: tt.fetchType, 638 }, fetchTime) 639 640 var metricsTimer *prometheus.HistogramVec 641 switch tt.dataType { 642 case metrics.AccountDataType: 643 metricsTimer = m.storedAccountFetchTimer 644 case metrics.AMPDataType: 645 metricsTimer = m.storedAMPFetchTimer 646 case metrics.CategoryDataType: 647 metricsTimer = m.storedCategoryFetchTimer 648 case metrics.RequestDataType: 649 metricsTimer = m.storedRequestFetchTimer 650 case metrics.VideoDataType: 651 metricsTimer = m.storedVideoFetchTimer 652 case metrics.ResponseDataType: 653 metricsTimer = m.storedResponsesFetchTimer 654 } 655 656 result := getHistogramFromHistogramVec( 657 metricsTimer, 658 storedDataFetchTypeLabel, 659 string(tt.fetchType)) 660 assertHistogram(t, tt.description, result, 1, 0.5) 661 } 662 } 663 664 func TestRecordStoredDataError(t *testing.T) { 665 tests := []struct { 666 description string 667 dataType metrics.StoredDataType 668 errorType metrics.StoredDataError 669 metricName string 670 }{ 671 { 672 description: "Update stored_account_errors counter with network label", 673 dataType: metrics.AccountDataType, 674 errorType: metrics.StoredDataErrorNetwork, 675 metricName: "stored_account_errors", 676 }, 677 { 678 description: "Update stored_amp_errors counter with network label", 679 dataType: metrics.AMPDataType, 680 errorType: metrics.StoredDataErrorNetwork, 681 metricName: "stored_amp_errors", 682 }, 683 { 684 description: "Update stored_category_errors counter with network label", 685 dataType: metrics.CategoryDataType, 686 errorType: metrics.StoredDataErrorNetwork, 687 metricName: "stored_category_errors", 688 }, 689 { 690 description: "Update stored_request_errors counter with network label", 691 dataType: metrics.RequestDataType, 692 errorType: metrics.StoredDataErrorNetwork, 693 metricName: "stored_request_errors", 694 }, 695 { 696 description: "Update stored_video_errors counter with network label", 697 dataType: metrics.VideoDataType, 698 errorType: metrics.StoredDataErrorNetwork, 699 metricName: "stored_video_errors", 700 }, 701 { 702 description: "Update stored_account_errors counter with undefined label", 703 dataType: metrics.AccountDataType, 704 errorType: metrics.StoredDataErrorUndefined, 705 metricName: "stored_account_errors", 706 }, 707 { 708 description: "Update stored_amp_errors counter with undefined label", 709 dataType: metrics.AMPDataType, 710 errorType: metrics.StoredDataErrorUndefined, 711 metricName: "stored_amp_errors", 712 }, 713 { 714 description: "Update stored_category_errors counter with undefined label", 715 dataType: metrics.CategoryDataType, 716 errorType: metrics.StoredDataErrorUndefined, 717 metricName: "stored_category_errors", 718 }, 719 { 720 description: "Update stored_request_errors counter with undefined label", 721 dataType: metrics.RequestDataType, 722 errorType: metrics.StoredDataErrorUndefined, 723 metricName: "stored_request_errors", 724 }, 725 { 726 description: "Update stored_video_errors counter with undefined label", 727 dataType: metrics.VideoDataType, 728 errorType: metrics.StoredDataErrorUndefined, 729 metricName: "stored_video_errors", 730 }, 731 { 732 description: "Update stored_response_errors counter with network label", 733 dataType: metrics.ResponseDataType, 734 errorType: metrics.StoredDataErrorNetwork, 735 metricName: "stored_response_errors", 736 }, 737 } 738 739 for _, tt := range tests { 740 m := createMetricsForTesting() 741 m.RecordStoredDataError(metrics.StoredDataLabels{ 742 DataType: tt.dataType, 743 Error: tt.errorType, 744 }) 745 746 var metricsCounter *prometheus.CounterVec 747 switch tt.dataType { 748 case metrics.AccountDataType: 749 metricsCounter = m.storedAccountErrors 750 case metrics.AMPDataType: 751 metricsCounter = m.storedAMPErrors 752 case metrics.CategoryDataType: 753 metricsCounter = m.storedCategoryErrors 754 case metrics.RequestDataType: 755 metricsCounter = m.storedRequestErrors 756 case metrics.VideoDataType: 757 metricsCounter = m.storedVideoErrors 758 case metrics.ResponseDataType: 759 metricsCounter = m.storedResponsesErrors 760 } 761 762 assertCounterVecValue(t, tt.description, tt.metricName, metricsCounter, 763 1, 764 prometheus.Labels{ 765 storedDataErrorLabel: string(tt.errorType), 766 }) 767 } 768 } 769 770 func TestAdapterBidReceivedMetric(t *testing.T) { 771 adapterName := "anyName" 772 performTest := func(m *Metrics, hasAdm bool) { 773 labels := metrics.AdapterLabels{ 774 Adapter: openrtb_ext.BidderName(adapterName), 775 } 776 bidType := openrtb_ext.BidTypeBanner 777 m.RecordAdapterBidReceived(labels, bidType, hasAdm) 778 } 779 780 testCases := []struct { 781 description string 782 testCase func(m *Metrics) 783 expectedAdmCount float64 784 expectedNurlCount float64 785 }{ 786 { 787 description: "AdM", 788 testCase: func(m *Metrics) { 789 performTest(m, true) 790 }, 791 expectedAdmCount: 1, 792 expectedNurlCount: 0, 793 }, 794 { 795 description: "Nurl", 796 testCase: func(m *Metrics) { 797 performTest(m, false) 798 }, 799 expectedAdmCount: 0, 800 expectedNurlCount: 1, 801 }, 802 } 803 804 for _, test := range testCases { 805 m := createMetricsForTesting() 806 807 test.testCase(m) 808 809 assertCounterVecValue(t, test.description, "adapterBids[adm]", m.adapterBids, 810 test.expectedAdmCount, 811 prometheus.Labels{ 812 adapterLabel: adapterName, 813 markupDeliveryLabel: markupDeliveryAdm, 814 }) 815 assertCounterVecValue(t, test.description, "adapterBids[nurl]", m.adapterBids, 816 test.expectedNurlCount, 817 prometheus.Labels{ 818 adapterLabel: adapterName, 819 markupDeliveryLabel: markupDeliveryNurl, 820 }) 821 } 822 } 823 824 func TestRecordAdapterPriceMetric(t *testing.T) { 825 m := createMetricsForTesting() 826 adapterName := "anyName" 827 cpm := float64(42) 828 829 m.RecordAdapterPrice(metrics.AdapterLabels{ 830 Adapter: openrtb_ext.BidderName(adapterName), 831 }, cpm) 832 833 expectedCount := uint64(1) 834 expectedSum := cpm 835 result := getHistogramFromHistogramVec(m.adapterPrices, adapterLabel, adapterName) 836 assertHistogram(t, "adapterPrices", result, expectedCount, expectedSum) 837 } 838 839 func TestAdapterRequestMetrics(t *testing.T) { 840 adapterName := "anyName" 841 performTest := func(m *Metrics, cookieFlag metrics.CookieFlag, adapterBids metrics.AdapterBid) { 842 labels := metrics.AdapterLabels{ 843 Adapter: openrtb_ext.BidderName(adapterName), 844 CookieFlag: cookieFlag, 845 AdapterBids: adapterBids, 846 } 847 m.RecordAdapterRequest(labels) 848 } 849 850 testCases := []struct { 851 description string 852 testCase func(m *Metrics) 853 expectedCount float64 854 expectedCookieNoCount float64 855 expectedCookieYesCount float64 856 expectedCookieUnknownCount float64 857 expectedHasBidsCount float64 858 }{ 859 { 860 description: "No Cookie & No Bids", 861 testCase: func(m *Metrics) { 862 performTest(m, metrics.CookieFlagNo, metrics.AdapterBidNone) 863 }, 864 expectedCount: 1, 865 expectedCookieNoCount: 1, 866 expectedCookieYesCount: 0, 867 expectedCookieUnknownCount: 0, 868 expectedHasBidsCount: 0, 869 }, 870 { 871 description: "Unknown Cookie & No Bids", 872 testCase: func(m *Metrics) { 873 performTest(m, metrics.CookieFlagUnknown, metrics.AdapterBidNone) 874 }, 875 expectedCount: 1, 876 expectedCookieNoCount: 0, 877 expectedCookieYesCount: 0, 878 expectedCookieUnknownCount: 1, 879 expectedHasBidsCount: 0, 880 }, 881 { 882 description: "Has Cookie & No Bids", 883 testCase: func(m *Metrics) { 884 performTest(m, metrics.CookieFlagYes, metrics.AdapterBidNone) 885 }, 886 expectedCount: 1, 887 expectedCookieNoCount: 0, 888 expectedCookieYesCount: 1, 889 expectedCookieUnknownCount: 0, 890 expectedHasBidsCount: 0, 891 }, 892 { 893 description: "No Cookie & Bids Present", 894 testCase: func(m *Metrics) { 895 performTest(m, metrics.CookieFlagNo, metrics.AdapterBidPresent) 896 }, 897 expectedCount: 1, 898 expectedCookieNoCount: 1, 899 expectedCookieYesCount: 0, 900 expectedCookieUnknownCount: 0, 901 expectedHasBidsCount: 1, 902 }, 903 { 904 description: "Unknown Cookie & Bids Present", 905 testCase: func(m *Metrics) { 906 performTest(m, metrics.CookieFlagUnknown, metrics.AdapterBidPresent) 907 }, 908 expectedCount: 1, 909 expectedCookieNoCount: 0, 910 expectedCookieYesCount: 0, 911 expectedCookieUnknownCount: 1, 912 expectedHasBidsCount: 1, 913 }, 914 { 915 description: "Has Cookie & Bids Present", 916 testCase: func(m *Metrics) { 917 performTest(m, metrics.CookieFlagYes, metrics.AdapterBidPresent) 918 }, 919 expectedCount: 1, 920 expectedCookieNoCount: 0, 921 expectedCookieYesCount: 1, 922 expectedCookieUnknownCount: 0, 923 expectedHasBidsCount: 1, 924 }, 925 } 926 927 for _, test := range testCases { 928 m := createMetricsForTesting() 929 930 test.testCase(m) 931 932 var totalCount float64 933 var totalCookieNoCount float64 934 var totalCookieYesCount float64 935 var totalCookieUnknownCount float64 936 var totalHasBidsCount float64 937 processMetrics(m.adapterRequests, func(m dto.Metric) { 938 isMetricForAdapter := false 939 for _, label := range m.GetLabel() { 940 if label.GetName() == adapterLabel && label.GetValue() == adapterName { 941 isMetricForAdapter = true 942 } 943 } 944 945 if isMetricForAdapter { 946 value := m.GetCounter().GetValue() 947 totalCount += value 948 for _, label := range m.GetLabel() { 949 950 if label.GetName() == hasBidsLabel && label.GetValue() == "true" { 951 totalHasBidsCount += value 952 } 953 954 if label.GetName() == cookieLabel { 955 switch label.GetValue() { 956 case string(metrics.CookieFlagNo): 957 totalCookieNoCount += value 958 case string(metrics.CookieFlagYes): 959 totalCookieYesCount += value 960 case string(metrics.CookieFlagUnknown): 961 totalCookieUnknownCount += value 962 } 963 } 964 } 965 } 966 }) 967 assert.Equal(t, test.expectedCount, totalCount, test.description+":total") 968 assert.Equal(t, test.expectedCookieNoCount, totalCookieNoCount, test.description+":cookie=no") 969 assert.Equal(t, test.expectedCookieYesCount, totalCookieYesCount, test.description+":cookie=yes") 970 assert.Equal(t, test.expectedCookieUnknownCount, totalCookieUnknownCount, test.description+":cookie=unknown") 971 assert.Equal(t, test.expectedHasBidsCount, totalHasBidsCount, test.description+":hasBids") 972 } 973 } 974 975 func TestAdapterRequestErrorMetrics(t *testing.T) { 976 adapterName := "anyName" 977 performTest := func(m *Metrics, adapterErrors map[metrics.AdapterError]struct{}) { 978 labels := metrics.AdapterLabels{ 979 Adapter: openrtb_ext.BidderName(adapterName), 980 AdapterErrors: adapterErrors, 981 CookieFlag: metrics.CookieFlagUnknown, 982 AdapterBids: metrics.AdapterBidPresent, 983 } 984 m.RecordAdapterRequest(labels) 985 } 986 987 testCases := []struct { 988 description string 989 testCase func(m *Metrics) 990 expectedErrorsCount float64 991 expectedBadInputErrorsCount float64 992 }{ 993 { 994 description: "No Errors", 995 testCase: func(m *Metrics) { 996 performTest(m, nil) 997 }, 998 expectedErrorsCount: 0, 999 expectedBadInputErrorsCount: 0, 1000 }, 1001 { 1002 description: "Bad Input Error", 1003 testCase: func(m *Metrics) { 1004 performTest(m, map[metrics.AdapterError]struct{}{ 1005 metrics.AdapterErrorBadInput: {}, 1006 }) 1007 }, 1008 expectedErrorsCount: 1, 1009 expectedBadInputErrorsCount: 1, 1010 }, 1011 { 1012 description: "Other Error", 1013 testCase: func(m *Metrics) { 1014 performTest(m, map[metrics.AdapterError]struct{}{ 1015 metrics.AdapterErrorBadServerResponse: {}, 1016 }) 1017 }, 1018 expectedErrorsCount: 1, 1019 expectedBadInputErrorsCount: 0, 1020 }, 1021 } 1022 1023 for _, test := range testCases { 1024 m := createMetricsForTesting() 1025 1026 test.testCase(m) 1027 1028 var errorsCount float64 1029 var badInputErrorsCount float64 1030 processMetrics(m.adapterErrors, func(m dto.Metric) { 1031 isMetricForAdapter := false 1032 for _, label := range m.GetLabel() { 1033 if label.GetName() == adapterLabel && label.GetValue() == adapterName { 1034 isMetricForAdapter = true 1035 } 1036 } 1037 1038 if isMetricForAdapter { 1039 value := m.GetCounter().GetValue() 1040 errorsCount += value 1041 for _, label := range m.GetLabel() { 1042 if label.GetName() == adapterErrorLabel && label.GetValue() == string(metrics.AdapterErrorBadInput) { 1043 badInputErrorsCount += value 1044 } 1045 } 1046 } 1047 }) 1048 assert.Equal(t, test.expectedErrorsCount, errorsCount, test.description+":errors") 1049 assert.Equal(t, test.expectedBadInputErrorsCount, badInputErrorsCount, test.description+":badInputErrors") 1050 } 1051 } 1052 1053 func TestAdapterTimeMetric(t *testing.T) { 1054 adapterName := "anyName" 1055 performTest := func(m *Metrics, timeInMs float64, adapterErrors map[metrics.AdapterError]struct{}) { 1056 m.RecordAdapterTime(metrics.AdapterLabels{ 1057 Adapter: openrtb_ext.BidderName(adapterName), 1058 AdapterErrors: adapterErrors, 1059 }, time.Duration(timeInMs)*time.Millisecond) 1060 } 1061 1062 testCases := []struct { 1063 description string 1064 testCase func(m *Metrics) 1065 expectedCount uint64 1066 expectedSum float64 1067 }{ 1068 { 1069 description: "Success", 1070 testCase: func(m *Metrics) { 1071 performTest(m, 500, map[metrics.AdapterError]struct{}{}) 1072 }, 1073 expectedCount: 1, 1074 expectedSum: 0.5, 1075 }, 1076 { 1077 description: "Error", 1078 testCase: func(m *Metrics) { 1079 performTest(m, 500, map[metrics.AdapterError]struct{}{ 1080 metrics.AdapterErrorTimeout: {}, 1081 }) 1082 }, 1083 expectedCount: 0, 1084 expectedSum: 0, 1085 }, 1086 } 1087 1088 for _, test := range testCases { 1089 m := createMetricsForTesting() 1090 1091 test.testCase(m) 1092 1093 result := getHistogramFromHistogramVec(m.adapterRequestsTimer, adapterLabel, adapterName) 1094 assertHistogram(t, test.description, result, test.expectedCount, test.expectedSum) 1095 } 1096 } 1097 1098 func TestAdapterPanicMetric(t *testing.T) { 1099 m := createMetricsForTesting() 1100 adapterName := "anyName" 1101 1102 m.RecordAdapterPanic(metrics.AdapterLabels{ 1103 Adapter: openrtb_ext.BidderName(adapterName), 1104 }) 1105 1106 expectedCount := float64(1) 1107 assertCounterVecValue(t, "", "adapterPanics", m.adapterPanics, 1108 expectedCount, 1109 prometheus.Labels{ 1110 adapterLabel: adapterName, 1111 }) 1112 } 1113 1114 func TestStoredReqCacheResultMetric(t *testing.T) { 1115 m := createMetricsForTesting() 1116 1117 hitCount := 42 1118 missCount := 108 1119 m.RecordStoredReqCacheResult(metrics.CacheHit, hitCount) 1120 m.RecordStoredReqCacheResult(metrics.CacheMiss, missCount) 1121 1122 assertCounterVecValue(t, "", "storedRequestCacheResult:hit", m.storedRequestCacheResult, 1123 float64(hitCount), 1124 prometheus.Labels{ 1125 cacheResultLabel: string(metrics.CacheHit), 1126 }) 1127 assertCounterVecValue(t, "", "storedRequestCacheResult:miss", m.storedRequestCacheResult, 1128 float64(missCount), 1129 prometheus.Labels{ 1130 cacheResultLabel: string(metrics.CacheMiss), 1131 }) 1132 } 1133 1134 func TestStoredImpCacheResultMetric(t *testing.T) { 1135 m := createMetricsForTesting() 1136 1137 hitCount := 41 1138 missCount := 107 1139 m.RecordStoredImpCacheResult(metrics.CacheHit, hitCount) 1140 m.RecordStoredImpCacheResult(metrics.CacheMiss, missCount) 1141 1142 assertCounterVecValue(t, "", "storedImpressionsCacheResult:hit", m.storedImpressionsCacheResult, 1143 float64(hitCount), 1144 prometheus.Labels{ 1145 cacheResultLabel: string(metrics.CacheHit), 1146 }) 1147 assertCounterVecValue(t, "", "storedImpressionsCacheResult:miss", m.storedImpressionsCacheResult, 1148 float64(missCount), 1149 prometheus.Labels{ 1150 cacheResultLabel: string(metrics.CacheMiss), 1151 }) 1152 } 1153 1154 func TestAccountCacheResultMetric(t *testing.T) { 1155 m := createMetricsForTesting() 1156 1157 hitCount := 37 1158 missCount := 92 1159 m.RecordAccountCacheResult(metrics.CacheHit, hitCount) 1160 m.RecordAccountCacheResult(metrics.CacheMiss, missCount) 1161 1162 assertCounterVecValue(t, "", "accountCacheResult:hit", m.accountCacheResult, 1163 float64(hitCount), 1164 prometheus.Labels{ 1165 cacheResultLabel: string(metrics.CacheHit), 1166 }) 1167 assertCounterVecValue(t, "", "accountCacheResult:miss", m.accountCacheResult, 1168 float64(missCount), 1169 prometheus.Labels{ 1170 cacheResultLabel: string(metrics.CacheMiss), 1171 }) 1172 } 1173 1174 func TestCookieSyncMetric(t *testing.T) { 1175 tests := []struct { 1176 status metrics.CookieSyncStatus 1177 label string 1178 }{ 1179 { 1180 status: metrics.CookieSyncOK, 1181 label: "ok", 1182 }, 1183 { 1184 status: metrics.CookieSyncBadRequest, 1185 label: "bad_request", 1186 }, 1187 { 1188 status: metrics.CookieSyncOptOut, 1189 label: "opt_out", 1190 }, 1191 { 1192 status: metrics.CookieSyncGDPRHostCookieBlocked, 1193 label: "gdpr_blocked_host_cookie", 1194 }, 1195 } 1196 1197 for _, test := range tests { 1198 m := createMetricsForTesting() 1199 1200 m.RecordCookieSync(test.status) 1201 1202 assertCounterVecValue(t, "", "cookie_sync_requests:"+test.label, m.cookieSync, 1203 float64(1), 1204 prometheus.Labels{ 1205 statusLabel: string(test.status), 1206 }) 1207 } 1208 } 1209 1210 func TestRecordSyncerRequestMetric(t *testing.T) { 1211 key := "anyKey" 1212 1213 tests := []struct { 1214 status metrics.SyncerCookieSyncStatus 1215 label string 1216 }{ 1217 { 1218 status: metrics.SyncerCookieSyncOK, 1219 label: "ok", 1220 }, 1221 { 1222 status: metrics.SyncerCookieSyncPrivacyBlocked, 1223 label: "privacy_blocked", 1224 }, 1225 { 1226 status: metrics.SyncerCookieSyncAlreadySynced, 1227 label: "already_synced", 1228 }, 1229 { 1230 status: metrics.SyncerCookieSyncTypeNotSupported, 1231 label: "type_not_supported", 1232 }, 1233 } 1234 1235 for _, test := range tests { 1236 m := createMetricsForTesting() 1237 1238 m.RecordSyncerRequest(key, test.status) 1239 1240 assertCounterVecValue(t, "", "syncer_requests:"+test.label, m.syncerRequests, 1241 float64(1), 1242 prometheus.Labels{ 1243 syncerLabel: key, 1244 statusLabel: string(test.status), 1245 }) 1246 } 1247 } 1248 1249 func TestSetUidMetric(t *testing.T) { 1250 tests := []struct { 1251 status metrics.SetUidStatus 1252 label string 1253 }{ 1254 { 1255 status: metrics.SetUidOK, 1256 label: "ok", 1257 }, 1258 { 1259 status: metrics.SetUidBadRequest, 1260 label: "bad_request", 1261 }, 1262 { 1263 status: metrics.SetUidOptOut, 1264 label: "opt_out", 1265 }, 1266 { 1267 status: metrics.SetUidGDPRHostCookieBlocked, 1268 label: "gdpr_blocked_host_cookie", 1269 }, 1270 { 1271 status: metrics.SetUidSyncerUnknown, 1272 label: "syncer_unknown", 1273 }, 1274 } 1275 1276 for _, test := range tests { 1277 m := createMetricsForTesting() 1278 1279 m.RecordSetUid(test.status) 1280 1281 assertCounterVecValue(t, "", "setuid_requests:"+test.label, m.setUid, 1282 float64(1), 1283 prometheus.Labels{ 1284 statusLabel: string(test.status), 1285 }) 1286 } 1287 } 1288 1289 func TestRecordSyncerSetMetric(t *testing.T) { 1290 key := "anyKey" 1291 1292 tests := []struct { 1293 status metrics.SyncerSetUidStatus 1294 label string 1295 }{ 1296 { 1297 status: metrics.SyncerSetUidOK, 1298 label: "ok", 1299 }, 1300 { 1301 status: metrics.SyncerSetUidCleared, 1302 label: "cleared", 1303 }, 1304 } 1305 1306 for _, test := range tests { 1307 m := createMetricsForTesting() 1308 1309 m.RecordSyncerSet(key, test.status) 1310 1311 assertCounterVecValue(t, "", "syncer_sets:"+test.label, m.syncerSets, 1312 float64(1), 1313 prometheus.Labels{ 1314 syncerLabel: key, 1315 statusLabel: string(test.status), 1316 }) 1317 } 1318 } 1319 1320 func TestPrebidCacheRequestTimeMetric(t *testing.T) { 1321 m := createMetricsForTesting() 1322 1323 m.RecordPrebidCacheRequestTime(true, time.Duration(100)*time.Millisecond) 1324 m.RecordPrebidCacheRequestTime(false, time.Duration(200)*time.Millisecond) 1325 1326 successExpectedCount := uint64(1) 1327 successExpectedSum := float64(0.1) 1328 successResult := getHistogramFromHistogramVec(m.prebidCacheWriteTimer, successLabel, "true") 1329 assertHistogram(t, "Success", successResult, successExpectedCount, successExpectedSum) 1330 1331 errorExpectedCount := uint64(1) 1332 errorExpectedSum := float64(0.2) 1333 errorResult := getHistogramFromHistogramVec(m.prebidCacheWriteTimer, successLabel, "false") 1334 assertHistogram(t, "Error", errorResult, errorExpectedCount, errorExpectedSum) 1335 } 1336 1337 func TestRecordRequestQueueTimeMetric(t *testing.T) { 1338 performTest := func(m *Metrics, requestStatus bool, requestType metrics.RequestType, timeInSec float64) { 1339 m.RecordRequestQueueTime(requestStatus, requestType, time.Duration(timeInSec*float64(time.Second))) 1340 } 1341 1342 testCases := []struct { 1343 description string 1344 status string 1345 testCase func(m *Metrics) 1346 expectedCount uint64 1347 expectedSum float64 1348 }{ 1349 { 1350 description: "Success", 1351 status: requestSuccessLabel, 1352 testCase: func(m *Metrics) { 1353 performTest(m, true, metrics.ReqTypeVideo, 2) 1354 }, 1355 expectedCount: 1, 1356 expectedSum: 2, 1357 }, 1358 { 1359 description: "TimeoutError", 1360 status: requestRejectLabel, 1361 testCase: func(m *Metrics) { 1362 performTest(m, false, metrics.ReqTypeVideo, 50) 1363 }, 1364 expectedCount: 1, 1365 expectedSum: 50, 1366 }, 1367 } 1368 1369 m := createMetricsForTesting() 1370 for _, test := range testCases { 1371 1372 test.testCase(m) 1373 1374 result := getHistogramFromHistogramVecByTwoKeys(m.requestsQueueTimer, requestTypeLabel, "video", requestStatusLabel, test.status) 1375 assertHistogram(t, test.description, result, test.expectedCount, test.expectedSum) 1376 } 1377 } 1378 1379 func TestTimeoutNotifications(t *testing.T) { 1380 m := createMetricsForTesting() 1381 1382 m.RecordTimeoutNotice(true) 1383 m.RecordTimeoutNotice(true) 1384 m.RecordTimeoutNotice(false) 1385 1386 assertCounterVecValue(t, "", "timeout_notifications:ok", m.timeoutNotifications, 1387 float64(2), 1388 prometheus.Labels{ 1389 successLabel: requestSuccessful, 1390 }) 1391 1392 assertCounterVecValue(t, "", "timeout_notifications:fail", m.timeoutNotifications, 1393 float64(1), 1394 prometheus.Labels{ 1395 successLabel: requestFailed, 1396 }) 1397 1398 } 1399 1400 func TestRecordDNSTime(t *testing.T) { 1401 type testIn struct { 1402 dnsLookupDuration time.Duration 1403 } 1404 type testOut struct { 1405 expDuration float64 1406 expCount uint64 1407 } 1408 testCases := []struct { 1409 description string 1410 in testIn 1411 out testOut 1412 }{ 1413 { 1414 description: "Five second DNS lookup time", 1415 in: testIn{ 1416 dnsLookupDuration: time.Second * 5, 1417 }, 1418 out: testOut{ 1419 expDuration: 5, 1420 expCount: 1, 1421 }, 1422 }, 1423 { 1424 description: "Zero DNS lookup time", 1425 in: testIn{}, 1426 out: testOut{ 1427 expDuration: 0, 1428 expCount: 1, 1429 }, 1430 }, 1431 } 1432 for i, test := range testCases { 1433 pm := createMetricsForTesting() 1434 pm.RecordDNSTime(test.in.dnsLookupDuration) 1435 1436 m := dto.Metric{} 1437 pm.dnsLookupTimer.Write(&m) 1438 histogram := *m.GetHistogram() 1439 1440 assert.Equal(t, test.out.expCount, histogram.GetSampleCount(), "[%d] Incorrect number of histogram entries. Desc: %s\n", i, test.description) 1441 assert.Equal(t, test.out.expDuration, histogram.GetSampleSum(), "[%d] Incorrect number of histogram cumulative values. Desc: %s\n", i, test.description) 1442 } 1443 } 1444 1445 func TestRecordTLSHandshakeTime(t *testing.T) { 1446 testCases := []struct { 1447 description string 1448 tLSHandshakeDuration time.Duration 1449 expectedDuration float64 1450 expectedCount uint64 1451 }{ 1452 { 1453 description: "Five second DNS lookup time", 1454 tLSHandshakeDuration: time.Second * 5, 1455 expectedDuration: 5, 1456 expectedCount: 1, 1457 }, 1458 { 1459 description: "Zero DNS lookup time", 1460 tLSHandshakeDuration: 0, 1461 expectedDuration: 0, 1462 expectedCount: 1, 1463 }, 1464 } 1465 for i, test := range testCases { 1466 pm := createMetricsForTesting() 1467 pm.RecordTLSHandshakeTime(test.tLSHandshakeDuration) 1468 1469 m := dto.Metric{} 1470 pm.tlsHandhakeTimer.Write(&m) 1471 histogram := *m.GetHistogram() 1472 1473 assert.Equal(t, test.expectedCount, histogram.GetSampleCount(), "[%d] Incorrect number of histogram entries. Desc: %s\n", i, test.description) 1474 assert.Equal(t, test.expectedDuration, histogram.GetSampleSum(), "[%d] Incorrect number of histogram cumulative values. Desc: %s\n", i, test.description) 1475 } 1476 } 1477 1478 func TestRecordBidderServerResponseTime(t *testing.T) { 1479 testCases := []struct { 1480 description string 1481 timeInMs float64 1482 expectedCount uint64 1483 expectedSum float64 1484 }{ 1485 { 1486 description: "record-bidder-server-response-time-1", 1487 timeInMs: 500, 1488 expectedCount: 1, 1489 expectedSum: 0.5, 1490 }, 1491 { 1492 description: "record-bidder-server-response-time-2", 1493 timeInMs: 400, 1494 expectedCount: 1, 1495 expectedSum: 0.4, 1496 }, 1497 } 1498 for _, test := range testCases { 1499 pm := createMetricsForTesting() 1500 pm.RecordBidderServerResponseTime(time.Duration(test.timeInMs) * time.Millisecond) 1501 1502 m := dto.Metric{} 1503 pm.bidderServerResponseTimer.Write(&m) 1504 histogram := *m.GetHistogram() 1505 1506 assert.Equal(t, test.expectedCount, histogram.GetSampleCount()) 1507 assert.Equal(t, test.expectedSum, histogram.GetSampleSum()) 1508 } 1509 } 1510 1511 func TestRecordAdapterConnections(t *testing.T) { 1512 1513 type testIn struct { 1514 adapterName openrtb_ext.BidderName 1515 connWasReused bool 1516 connWait time.Duration 1517 } 1518 1519 type testOut struct { 1520 expectedConnReusedCount int64 1521 expectedConnCreatedCount int64 1522 expectedConnWaitCount uint64 1523 expectedConnWaitTime float64 1524 } 1525 1526 testCases := []struct { 1527 description string 1528 in testIn 1529 out testOut 1530 }{ 1531 { 1532 description: "[1] Successful, new connection created, was idle, has connection wait", 1533 in: testIn{ 1534 adapterName: openrtb_ext.BidderAppnexus, 1535 connWasReused: false, 1536 connWait: time.Second * 5, 1537 }, 1538 out: testOut{ 1539 expectedConnReusedCount: 0, 1540 expectedConnCreatedCount: 1, 1541 expectedConnWaitCount: 1, 1542 expectedConnWaitTime: 5, 1543 }, 1544 }, 1545 { 1546 description: "[2] Successful, new connection created, not idle, has connection wait", 1547 in: testIn{ 1548 adapterName: openrtb_ext.BidderAppnexus, 1549 connWasReused: false, 1550 connWait: time.Second * 4, 1551 }, 1552 out: testOut{ 1553 expectedConnReusedCount: 0, 1554 expectedConnCreatedCount: 1, 1555 expectedConnWaitCount: 1, 1556 expectedConnWaitTime: 4, 1557 }, 1558 }, 1559 { 1560 description: "[3] Successful, was reused, was idle, no connection wait", 1561 in: testIn{ 1562 adapterName: openrtb_ext.BidderAppnexus, 1563 connWasReused: true, 1564 }, 1565 out: testOut{ 1566 expectedConnReusedCount: 1, 1567 expectedConnCreatedCount: 0, 1568 expectedConnWaitCount: 1, 1569 expectedConnWaitTime: 0, 1570 }, 1571 }, 1572 { 1573 description: "[4] Successful, was reused, not idle, has connection wait", 1574 in: testIn{ 1575 adapterName: openrtb_ext.BidderAppnexus, 1576 connWasReused: true, 1577 connWait: time.Second * 5, 1578 }, 1579 out: testOut{ 1580 expectedConnReusedCount: 1, 1581 expectedConnCreatedCount: 0, 1582 expectedConnWaitCount: 1, 1583 expectedConnWaitTime: 5, 1584 }, 1585 }, 1586 } 1587 1588 for i, test := range testCases { 1589 m := createMetricsForTesting() 1590 assertDesciptions := []string{ 1591 fmt.Sprintf("[%d] Metric: adapterReusedConnections; Desc: %s", i+1, test.description), 1592 fmt.Sprintf("[%d] Metric: adapterCreatedConnections; Desc: %s", i+1, test.description), 1593 fmt.Sprintf("[%d] Metric: adapterWaitConnectionCount; Desc: %s", i+1, test.description), 1594 fmt.Sprintf("[%d] Metric: adapterWaitConnectionTime; Desc: %s", i+1, test.description), 1595 } 1596 1597 m.RecordAdapterConnections(test.in.adapterName, test.in.connWasReused, test.in.connWait) 1598 1599 // Assert number of reused connections 1600 assertCounterVecValue(t, 1601 assertDesciptions[0], 1602 "adapter_connection_reused", 1603 m.adapterReusedConnections, 1604 float64(test.out.expectedConnReusedCount), 1605 prometheus.Labels{adapterLabel: string(test.in.adapterName)}) 1606 1607 // Assert number of new created connections 1608 assertCounterVecValue(t, 1609 assertDesciptions[1], 1610 "adapter_connection_created", 1611 m.adapterCreatedConnections, 1612 float64(test.out.expectedConnCreatedCount), 1613 prometheus.Labels{adapterLabel: string(test.in.adapterName)}) 1614 1615 // Assert connection wait time 1616 histogram := getHistogramFromHistogramVec(m.adapterConnectionWaitTime, adapterLabel, string(test.in.adapterName)) 1617 assert.Equal(t, test.out.expectedConnWaitCount, histogram.GetSampleCount(), assertDesciptions[2]) 1618 assert.Equal(t, test.out.expectedConnWaitTime, histogram.GetSampleSum(), assertDesciptions[3]) 1619 } 1620 } 1621 1622 func TestDisabledMetrics(t *testing.T) { 1623 prometheusMetrics := NewMetrics(config.PrometheusMetrics{ 1624 Port: 8080, 1625 Namespace: "prebid", 1626 Subsystem: "server", 1627 }, config.DisabledMetrics{ 1628 AdapterConnectionMetrics: true, 1629 AdapterGDPRRequestBlocked: true, 1630 }, 1631 nil, nil) 1632 1633 // Assert counter vector was not initialized 1634 assert.Nil(t, prometheusMetrics.adapterReusedConnections, "Counter Vector adapterReusedConnections should be nil") 1635 assert.Nil(t, prometheusMetrics.adapterCreatedConnections, "Counter Vector adapterCreatedConnections should be nil") 1636 assert.Nil(t, prometheusMetrics.adapterConnectionWaitTime, "Counter Vector adapterConnectionWaitTime should be nil") 1637 assert.Nil(t, prometheusMetrics.adapterGDPRBlockedRequests, "Counter Vector adapterGDPRBlockedRequests should be nil") 1638 } 1639 1640 func TestRecordRequestPrivacy(t *testing.T) { 1641 m := createMetricsForTesting() 1642 1643 // CCPA 1644 m.RecordRequestPrivacy(metrics.PrivacyLabels{ 1645 CCPAEnforced: true, 1646 CCPAProvided: true, 1647 }) 1648 m.RecordRequestPrivacy(metrics.PrivacyLabels{ 1649 CCPAEnforced: true, 1650 CCPAProvided: false, 1651 }) 1652 m.RecordRequestPrivacy(metrics.PrivacyLabels{ 1653 CCPAEnforced: false, 1654 CCPAProvided: true, 1655 }) 1656 1657 // COPPA 1658 m.RecordRequestPrivacy(metrics.PrivacyLabels{ 1659 COPPAEnforced: true, 1660 }) 1661 1662 // LMT 1663 m.RecordRequestPrivacy(metrics.PrivacyLabels{ 1664 LMTEnforced: true, 1665 }) 1666 1667 // GDPR 1668 m.RecordRequestPrivacy(metrics.PrivacyLabels{ 1669 GDPREnforced: true, 1670 GDPRTCFVersion: metrics.TCFVersionErr, 1671 }) 1672 m.RecordRequestPrivacy(metrics.PrivacyLabels{ 1673 GDPREnforced: true, 1674 GDPRTCFVersion: metrics.TCFVersionV2, 1675 }) 1676 1677 assertCounterVecValue(t, "", "privacy_ccpa", m.privacyCCPA, 1678 float64(1), 1679 prometheus.Labels{ 1680 sourceLabel: sourceRequest, 1681 optOutLabel: "true", 1682 }) 1683 1684 assertCounterVecValue(t, "", "privacy_ccpa", m.privacyCCPA, 1685 float64(1), 1686 prometheus.Labels{ 1687 sourceLabel: sourceRequest, 1688 optOutLabel: "false", 1689 }) 1690 1691 assertCounterVecValue(t, "", "privacy_coppa", m.privacyCOPPA, 1692 float64(1), 1693 prometheus.Labels{ 1694 sourceLabel: sourceRequest, 1695 }) 1696 1697 assertCounterVecValue(t, "", "privacy_lmt", m.privacyLMT, 1698 float64(1), 1699 prometheus.Labels{ 1700 sourceLabel: sourceRequest, 1701 }) 1702 1703 assertCounterVecValue(t, "", "privacy_tcf:err", m.privacyTCF, 1704 float64(1), 1705 prometheus.Labels{ 1706 sourceLabel: sourceRequest, 1707 versionLabel: "err", 1708 }) 1709 1710 assertCounterVecValue(t, "", "privacy_tcf:v2", m.privacyTCF, 1711 float64(1), 1712 prometheus.Labels{ 1713 sourceLabel: sourceRequest, 1714 versionLabel: "v2", 1715 }) 1716 } 1717 1718 func assertCounterValue(t *testing.T, description, name string, counter prometheus.Counter, expected float64) { 1719 m := dto.Metric{} 1720 counter.Write(&m) 1721 actual := *m.GetCounter().Value 1722 1723 assert.Equal(t, expected, actual, description) 1724 } 1725 1726 func assertCounterVecValue(t *testing.T, description, name string, counterVec *prometheus.CounterVec, expected float64, labels prometheus.Labels) { 1727 counter := counterVec.With(labels) 1728 assertCounterValue(t, description, name, counter, expected) 1729 } 1730 1731 func getHistogramFromHistogramVec(histogram *prometheus.HistogramVec, labelKey, labelValue string) dto.Histogram { 1732 var result dto.Histogram 1733 processMetrics(histogram, func(m dto.Metric) { 1734 for _, label := range m.GetLabel() { 1735 if label.GetName() == labelKey && label.GetValue() == labelValue { 1736 result = *m.GetHistogram() 1737 } 1738 } 1739 }) 1740 return result 1741 } 1742 1743 func getHistogramFromHistogramVecByTwoKeys(histogram *prometheus.HistogramVec, label1Key, label1Value, label2Key, label2Value string) dto.Histogram { 1744 var result dto.Histogram 1745 processMetrics(histogram, func(m dto.Metric) { 1746 for ind, label := range m.GetLabel() { 1747 if label.GetName() == label1Key && label.GetValue() == label1Value { 1748 valInd := ind 1749 if ind == 1 { 1750 valInd = 0 1751 } else { 1752 valInd = 1 1753 } 1754 if m.Label[valInd].GetName() == label2Key && m.Label[valInd].GetValue() == label2Value { 1755 result = *m.GetHistogram() 1756 } 1757 } 1758 } 1759 }) 1760 return result 1761 } 1762 1763 func processMetrics(collector prometheus.Collector, handler func(m dto.Metric)) { 1764 collectorChan := make(chan prometheus.Metric) 1765 go func() { 1766 collector.Collect(collectorChan) 1767 close(collectorChan) 1768 }() 1769 1770 for metric := range collectorChan { 1771 dtoMetric := dto.Metric{} 1772 metric.Write(&dtoMetric) 1773 handler(dtoMetric) 1774 } 1775 } 1776 1777 func assertHistogram(t *testing.T, name string, histogram dto.Histogram, expectedCount uint64, expectedSum float64) { 1778 assert.Equal(t, expectedCount, histogram.GetSampleCount(), name+":count") 1779 assert.Equal(t, expectedSum, histogram.GetSampleSum(), name+":sum") 1780 } 1781 1782 func TestRecordAdapterGDPRRequestBlocked(t *testing.T) { 1783 m := createMetricsForTesting() 1784 1785 m.RecordAdapterGDPRRequestBlocked(openrtb_ext.BidderAppnexus) 1786 1787 assertCounterVecValue(t, 1788 "Increment adapter GDPR request blocked counter", 1789 "adapter_gdpr_requests_blocked", 1790 m.adapterGDPRBlockedRequests, 1791 1, 1792 prometheus.Labels{ 1793 adapterLabel: string(openrtb_ext.BidderAppnexus), 1794 }) 1795 } 1796 1797 func TestStoredResponsesMetric(t *testing.T) { 1798 testCases := []struct { 1799 description string 1800 publisherId string 1801 accountStoredResponsesMetricsDisabled bool 1802 expectedAccountStoredResponsesCount float64 1803 expectedStoredResponsesCount float64 1804 }{ 1805 1806 { 1807 description: "Publisher id is given, account stored responses enabled, expected both account stored responses and stored responses counter to have a record", 1808 publisherId: "acct-id", 1809 accountStoredResponsesMetricsDisabled: false, 1810 expectedAccountStoredResponsesCount: 1, 1811 expectedStoredResponsesCount: 1, 1812 }, 1813 { 1814 description: "Publisher id is given, account stored responses disabled, expected stored responses counter only to have a record", 1815 publisherId: "acct-id", 1816 accountStoredResponsesMetricsDisabled: true, 1817 expectedAccountStoredResponsesCount: 0, 1818 expectedStoredResponsesCount: 1, 1819 }, 1820 { 1821 description: "Publisher id is unknown, account stored responses enabled, expected stored responses counter only to have a record", 1822 publisherId: metrics.PublisherUnknown, 1823 accountStoredResponsesMetricsDisabled: true, 1824 expectedAccountStoredResponsesCount: 0, 1825 expectedStoredResponsesCount: 1, 1826 }, 1827 { 1828 description: "Publisher id is unknown, account stored responses disabled, expected stored responses counter only to have a record", 1829 publisherId: metrics.PublisherUnknown, 1830 accountStoredResponsesMetricsDisabled: false, 1831 expectedAccountStoredResponsesCount: 0, 1832 expectedStoredResponsesCount: 1, 1833 }, 1834 } 1835 1836 for _, test := range testCases { 1837 m := createMetricsForTesting() 1838 m.metricsDisabled.AccountStoredResponses = test.accountStoredResponsesMetricsDisabled 1839 m.RecordStoredResponse(test.publisherId) 1840 1841 assertCounterVecValue(t, "", "account stored responses", m.accountStoredResponses, test.expectedAccountStoredResponsesCount, prometheus.Labels{accountLabel: "acct-id"}) 1842 assertCounterValue(t, "", "stored responses", m.storedResponses, test.expectedStoredResponsesCount) 1843 } 1844 } 1845 1846 func TestRecordAdsCertReqMetric(t *testing.T) { 1847 testCases := []struct { 1848 description string 1849 requestSuccess bool 1850 expectedSuccessRequestsCount float64 1851 expectedFailedRequestsCount float64 1852 }{ 1853 { 1854 description: "Record failed request, expected success request count is 0 and failed request count is 1", 1855 requestSuccess: false, 1856 expectedSuccessRequestsCount: 0, 1857 expectedFailedRequestsCount: 1, 1858 }, 1859 { 1860 description: "Record successful request, expected success request count is 1 and failed request count is 0", 1861 requestSuccess: true, 1862 expectedSuccessRequestsCount: 1, 1863 expectedFailedRequestsCount: 0, 1864 }, 1865 } 1866 1867 for _, test := range testCases { 1868 m := createMetricsForTesting() 1869 m.RecordAdsCertReq(test.requestSuccess) 1870 assertCounterVecValue(t, test.description, "successfully signed requests", m.adsCertRequests, test.expectedSuccessRequestsCount, prometheus.Labels{successLabel: requestSuccessful}) 1871 assertCounterVecValue(t, test.description, "unsuccessfully signed requests", m.adsCertRequests, test.expectedFailedRequestsCount, prometheus.Labels{successLabel: requestFailed}) 1872 } 1873 } 1874 1875 func TestRecordAdsCertSignTime(t *testing.T) { 1876 type testIn struct { 1877 adsCertSignDuration time.Duration 1878 } 1879 type testOut struct { 1880 expDuration float64 1881 expCount uint64 1882 } 1883 testCases := []struct { 1884 description string 1885 in testIn 1886 out testOut 1887 }{ 1888 { 1889 description: "Five second AdsCert sign time", 1890 in: testIn{ 1891 adsCertSignDuration: time.Second * 5, 1892 }, 1893 out: testOut{ 1894 expDuration: 5, 1895 expCount: 1, 1896 }, 1897 }, 1898 { 1899 description: "Five millisecond AdsCert sign time", 1900 in: testIn{ 1901 adsCertSignDuration: time.Millisecond * 5, 1902 }, 1903 out: testOut{ 1904 expDuration: 0.005, 1905 expCount: 1, 1906 }, 1907 }, 1908 { 1909 description: "Zero AdsCert sign time", 1910 in: testIn{}, 1911 out: testOut{ 1912 expDuration: 0, 1913 expCount: 1, 1914 }, 1915 }, 1916 } 1917 for i, test := range testCases { 1918 pm := createMetricsForTesting() 1919 pm.RecordAdsCertSignTime(test.in.adsCertSignDuration) 1920 1921 m := dto.Metric{} 1922 pm.adsCertSignTimer.Write(&m) 1923 histogram := *m.GetHistogram() 1924 1925 assert.Equal(t, test.out.expCount, histogram.GetSampleCount(), "[%d] Incorrect number of histogram entries. Desc: %s\n", i, test.description) 1926 assert.Equal(t, test.out.expDuration, histogram.GetSampleSum(), "[%d] Incorrect number of histogram cumulative values. Desc: %s\n", i, test.description) 1927 } 1928 } 1929 1930 func TestRecordModuleMetrics(t *testing.T) { 1931 m := createMetricsForTesting() 1932 1933 // check that each module has its own metric recorded with correct stage labels 1934 for module, stages := range modulesStages { 1935 for _, stage := range stages { 1936 // first record the metrics 1937 m.RecordModuleCalled(metrics.ModuleLabels{ 1938 Module: module, 1939 Stage: stage, 1940 }, time.Millisecond*1) 1941 m.RecordModuleFailed(metrics.ModuleLabels{ 1942 Module: module, 1943 Stage: stage, 1944 }) 1945 m.RecordModuleSuccessNooped(metrics.ModuleLabels{ 1946 Module: module, 1947 Stage: stage, 1948 }) 1949 m.RecordModuleSuccessUpdated(metrics.ModuleLabels{ 1950 Module: module, 1951 Stage: stage, 1952 }) 1953 m.RecordModuleSuccessRejected(metrics.ModuleLabels{ 1954 Module: module, 1955 Stage: stage, 1956 }) 1957 m.RecordModuleExecutionError(metrics.ModuleLabels{ 1958 Module: module, 1959 Stage: stage, 1960 }) 1961 m.RecordModuleTimeout(metrics.ModuleLabels{ 1962 Module: module, 1963 Stage: stage, 1964 }) 1965 1966 // now check that the values are correct 1967 result := getHistogramFromHistogramVec(m.moduleDuration[module], stageLabel, stage) 1968 assertHistogram(t, fmt.Sprintf("module_%s_duration", module), result, 1, 0.001) 1969 assertCounterVecValue(t, "Module calls performed", fmt.Sprintf("%s metric recorded during %s stage", module, stage), m.moduleCalls[module], 1, prometheus.Labels{stageLabel: stage}) 1970 assertCounterVecValue(t, "Module calls failed", fmt.Sprintf("%s metric recorded during %s stage", module, stage), m.moduleFailures[module], 1, prometheus.Labels{stageLabel: stage}) 1971 assertCounterVecValue(t, "Module success noop action", fmt.Sprintf("%s metric recorded during %s stage", module, stage), m.moduleSuccessNoops[module], 1, prometheus.Labels{stageLabel: stage}) 1972 assertCounterVecValue(t, "Module success update action", fmt.Sprintf("%s metric recorded during %s stage", module, stage), m.moduleSuccessUpdates[module], 1, prometheus.Labels{stageLabel: stage}) 1973 assertCounterVecValue(t, "Module success reject action", fmt.Sprintf("%s metric recorded during %s stage", module, stage), m.moduleSuccessRejects[module], 1, prometheus.Labels{stageLabel: stage}) 1974 assertCounterVecValue(t, "Module execution error", fmt.Sprintf("%s metric recorded during %s stage", module, stage), m.moduleExecutionErrors[module], 1, prometheus.Labels{stageLabel: stage}) 1975 assertCounterVecValue(t, "Module timeout", fmt.Sprintf("%s metric recorded during %s stage", module, stage), m.moduleTimeouts[module], 1, prometheus.Labels{stageLabel: stage}) 1976 } 1977 } 1978 } 1979 1980 func TestRecordAccountGDPRPurposeWarningMetrics(t *testing.T) { 1981 testCases := []struct { 1982 name string 1983 givenPurposeName string 1984 expectedP1MetricCount float64 1985 expectedP2MetricCount float64 1986 expectedP3MetricCount float64 1987 expectedP4MetricCount float64 1988 expectedP5MetricCount float64 1989 expectedP6MetricCount float64 1990 expectedP7MetricCount float64 1991 expectedP8MetricCount float64 1992 expectedP9MetricCount float64 1993 expectedP10MetricCount float64 1994 }{ 1995 { 1996 name: "Purpose1MetricIncremented", 1997 givenPurposeName: "purpose1", 1998 expectedP1MetricCount: 1, 1999 }, 2000 { 2001 name: "Purpose2MetricIncremented", 2002 givenPurposeName: "purpose2", 2003 expectedP2MetricCount: 1, 2004 }, 2005 { 2006 name: "Purpose3MetricIncremented", 2007 givenPurposeName: "purpose3", 2008 expectedP3MetricCount: 1, 2009 }, 2010 { 2011 name: "Purpose4MetricIncremented", 2012 givenPurposeName: "purpose4", 2013 expectedP4MetricCount: 1, 2014 }, 2015 { 2016 name: "Purpose5MetricIncremented", 2017 givenPurposeName: "purpose5", 2018 expectedP5MetricCount: 1, 2019 }, 2020 { 2021 name: "Purpose6MetricIncremented", 2022 givenPurposeName: "purpose6", 2023 expectedP6MetricCount: 1, 2024 }, 2025 { 2026 name: "Purpose7MetricIncremented", 2027 givenPurposeName: "purpose7", 2028 expectedP7MetricCount: 1, 2029 }, 2030 { 2031 name: "Purpose8MetricIncremented", 2032 givenPurposeName: "purpose8", 2033 expectedP8MetricCount: 1, 2034 }, 2035 { 2036 name: "Purpose9MetricIncremented", 2037 givenPurposeName: "purpose9", 2038 expectedP9MetricCount: 1, 2039 }, 2040 { 2041 name: "Purpose10MetricIncremented", 2042 givenPurposeName: "purpose10", 2043 expectedP10MetricCount: 1, 2044 }, 2045 } 2046 for _, test := range testCases { 2047 t.Run(test.name, func(t *testing.T) { 2048 m := createMetricsForTesting() 2049 m.RecordAccountGDPRPurposeWarning("acct-id", test.givenPurposeName) 2050 2051 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose1, test.expectedP1MetricCount) 2052 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose2, test.expectedP2MetricCount) 2053 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose3, test.expectedP3MetricCount) 2054 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose4, test.expectedP4MetricCount) 2055 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose5, test.expectedP5MetricCount) 2056 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose6, test.expectedP6MetricCount) 2057 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose7, test.expectedP7MetricCount) 2058 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose8, test.expectedP8MetricCount) 2059 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose9, test.expectedP9MetricCount) 2060 assertCounterValue(t, "", "Account Deprecation Warnings", m.accountDeprecationWarningsPurpose10, test.expectedP10MetricCount) 2061 }) 2062 } 2063 } 2064 2065 func TestRecordAccountGDPRChannelEnabledWarningMetrics(t *testing.T) { 2066 testCases := []struct { 2067 name string 2068 givenPubID string 2069 expectedMetricCount float64 2070 }{ 2071 { 2072 name: "GdprChannelMetricIncremented", 2073 givenPubID: "acct-id", 2074 expectedMetricCount: 1, 2075 }, 2076 } 2077 for _, test := range testCases { 2078 t.Run(test.name, func(t *testing.T) { 2079 m := createMetricsForTesting() 2080 m.RecordAccountGDPRChannelEnabledWarning(test.givenPubID) 2081 2082 assertCounterValue(t, "", "GDPR Channel Enabled Deprecation Warnings", m.channelEnabledGDPR, test.expectedMetricCount) 2083 }) 2084 } 2085 } 2086 2087 func TestRecordAccountCCPAChannelEnabledWarningMetrics(t *testing.T) { 2088 testCases := []struct { 2089 name string 2090 givenPubID string 2091 expectedMetricCount float64 2092 }{ 2093 { 2094 name: "CcpaChannelMetricIncremented", 2095 givenPubID: "acct-id", 2096 expectedMetricCount: 1, 2097 }, 2098 } 2099 for _, test := range testCases { 2100 t.Run(test.name, func(t *testing.T) { 2101 m := createMetricsForTesting() 2102 m.RecordAccountCCPAChannelEnabledWarning(test.givenPubID) 2103 2104 assertCounterValue(t, "", "CCPA Channel Enabled Deprecation Warnings", m.channelEnabledCCPA, test.expectedMetricCount) 2105 }) 2106 } 2107 } 2108 2109 func TestRecordAccountUpgradeStatusMetrics(t *testing.T) { 2110 testCases := []struct { 2111 name string 2112 givenPubID string 2113 expectedMetricCount float64 2114 }{ 2115 { 2116 name: "AccountDeprecationMeterIncremented", 2117 givenPubID: "acct-id", 2118 expectedMetricCount: 1, 2119 }, 2120 } 2121 for _, test := range testCases { 2122 t.Run(test.name, func(t *testing.T) { 2123 m := createMetricsForTesting() 2124 m.RecordAccountUpgradeStatus(test.givenPubID) 2125 2126 assertCounterValue(t, "", "Account Depreciation Summary Meter should be incremented", m.accountDeprecationSummary, test.expectedMetricCount) 2127 }) 2128 2129 } 2130 }