github.com/prebid/prebid-server/v2@v2.18.0/metrics/prometheus/prometheus.go (about) 1 package prometheusmetrics 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 "time" 8 9 "github.com/prebid/prebid-server/v2/config" 10 "github.com/prebid/prebid-server/v2/metrics" 11 "github.com/prebid/prebid-server/v2/openrtb_ext" 12 "github.com/prometheus/client_golang/prometheus" 13 promCollector "github.com/prometheus/client_golang/prometheus/collectors" 14 ) 15 16 // Metrics defines the Prometheus metrics backing the MetricsEngine implementation. 17 type Metrics struct { 18 Registerer prometheus.Registerer 19 Gatherer *prometheus.Registry 20 21 // General Metrics 22 tmaxTimeout prometheus.Counter 23 connectionsClosed prometheus.Counter 24 connectionsError *prometheus.CounterVec 25 connectionsOpened prometheus.Counter 26 cookieSync *prometheus.CounterVec 27 setUid *prometheus.CounterVec 28 impressions *prometheus.CounterVec 29 prebidCacheWriteTimer *prometheus.HistogramVec 30 requests *prometheus.CounterVec 31 debugRequests prometheus.Counter 32 requestsTimer *prometheus.HistogramVec 33 requestsQueueTimer *prometheus.HistogramVec 34 requestsWithoutCookie *prometheus.CounterVec 35 storedImpressionsCacheResult *prometheus.CounterVec 36 storedRequestCacheResult *prometheus.CounterVec 37 accountCacheResult *prometheus.CounterVec 38 storedAccountFetchTimer *prometheus.HistogramVec 39 storedAccountErrors *prometheus.CounterVec 40 storedAMPFetchTimer *prometheus.HistogramVec 41 storedAMPErrors *prometheus.CounterVec 42 storedCategoryFetchTimer *prometheus.HistogramVec 43 storedCategoryErrors *prometheus.CounterVec 44 storedRequestFetchTimer *prometheus.HistogramVec 45 storedRequestErrors *prometheus.CounterVec 46 storedVideoFetchTimer *prometheus.HistogramVec 47 storedVideoErrors *prometheus.CounterVec 48 timeoutNotifications *prometheus.CounterVec 49 dnsLookupTimer prometheus.Histogram 50 tlsHandhakeTimer prometheus.Histogram 51 privacyCCPA *prometheus.CounterVec 52 privacyCOPPA *prometheus.CounterVec 53 privacyLMT *prometheus.CounterVec 54 privacyTCF *prometheus.CounterVec 55 storedResponses prometheus.Counter 56 storedResponsesFetchTimer *prometheus.HistogramVec 57 storedResponsesErrors *prometheus.CounterVec 58 adsCertRequests *prometheus.CounterVec 59 adsCertSignTimer prometheus.Histogram 60 bidderServerResponseTimer prometheus.Histogram 61 62 // Adapter Metrics 63 adapterBids *prometheus.CounterVec 64 adapterErrors *prometheus.CounterVec 65 adapterPanics *prometheus.CounterVec 66 adapterPrices *prometheus.HistogramVec 67 adapterRequests *prometheus.CounterVec 68 overheadTimer *prometheus.HistogramVec 69 adapterRequestsTimer *prometheus.HistogramVec 70 adapterReusedConnections *prometheus.CounterVec 71 adapterCreatedConnections *prometheus.CounterVec 72 adapterConnectionWaitTime *prometheus.HistogramVec 73 adapterScrubbedBuyerUIDs *prometheus.CounterVec 74 adapterGDPRBlockedRequests *prometheus.CounterVec 75 adapterBidResponseValidationSizeError *prometheus.CounterVec 76 adapterBidResponseValidationSizeWarn *prometheus.CounterVec 77 adapterBidResponseSecureMarkupError *prometheus.CounterVec 78 adapterBidResponseSecureMarkupWarn *prometheus.CounterVec 79 80 // Syncer Metrics 81 syncerRequests *prometheus.CounterVec 82 syncerSets *prometheus.CounterVec 83 84 // Account Metrics 85 accountRequests *prometheus.CounterVec 86 accountDebugRequests *prometheus.CounterVec 87 accountStoredResponses *prometheus.CounterVec 88 accountBidResponseValidationSizeError *prometheus.CounterVec 89 accountBidResponseValidationSizeWarn *prometheus.CounterVec 90 accountBidResponseSecureMarkupError *prometheus.CounterVec 91 accountBidResponseSecureMarkupWarn *prometheus.CounterVec 92 93 // Module Metrics as a map where the key is the module name 94 moduleDuration map[string]*prometheus.HistogramVec 95 moduleCalls map[string]*prometheus.CounterVec 96 moduleFailures map[string]*prometheus.CounterVec 97 moduleSuccessNoops map[string]*prometheus.CounterVec 98 moduleSuccessUpdates map[string]*prometheus.CounterVec 99 moduleSuccessRejects map[string]*prometheus.CounterVec 100 moduleExecutionErrors map[string]*prometheus.CounterVec 101 moduleTimeouts map[string]*prometheus.CounterVec 102 103 metricsDisabled config.DisabledMetrics 104 } 105 106 const ( 107 accountLabel = "account" 108 actionLabel = "action" 109 adapterErrorLabel = "adapter_error" 110 adapterLabel = "adapter" 111 bidTypeLabel = "bid_type" 112 cacheResultLabel = "cache_result" 113 connectionErrorLabel = "connection_error" 114 cookieLabel = "cookie" 115 hasBidsLabel = "has_bids" 116 isAudioLabel = "audio" 117 isBannerLabel = "banner" 118 isNativeLabel = "native" 119 isVideoLabel = "video" 120 markupDeliveryLabel = "delivery" 121 optOutLabel = "opt_out" 122 overheadTypeLabel = "overhead_type" 123 privacyBlockedLabel = "privacy_blocked" 124 requestStatusLabel = "request_status" 125 requestTypeLabel = "request_type" 126 stageLabel = "stage" 127 statusLabel = "status" 128 successLabel = "success" 129 syncerLabel = "syncer" 130 versionLabel = "version" 131 ) 132 133 const ( 134 connectionAcceptError = "accept" 135 connectionCloseError = "close" 136 ) 137 138 const ( 139 markupDeliveryAdm = "adm" 140 markupDeliveryNurl = "nurl" 141 ) 142 143 const ( 144 requestSuccessLabel = "requestAcceptedLabel" 145 requestRejectLabel = "requestRejectedLabel" 146 ) 147 148 const ( 149 requestSuccessful = "ok" 150 requestFailed = "failed" 151 ) 152 153 const ( 154 sourceLabel = "source" 155 sourceRequest = "request" 156 ) 157 158 const ( 159 storedDataFetchTypeLabel = "stored_data_fetch_type" 160 storedDataErrorLabel = "stored_data_error" 161 ) 162 163 // NewMetrics initializes a new Prometheus metrics instance with preloaded label values. 164 func NewMetrics(cfg config.PrometheusMetrics, disabledMetrics config.DisabledMetrics, syncerKeys []string, moduleStageNames map[string][]string) *Metrics { 165 standardTimeBuckets := []float64{0.05, 0.1, 0.15, 0.20, 0.25, 0.3, 0.4, 0.5, 0.75, 1} 166 cacheWriteTimeBuckets := []float64{0.001, 0.002, 0.005, 0.01, 0.025, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 1} 167 priceBuckets := []float64{250, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000} 168 queuedRequestTimeBuckets := []float64{0, 1, 5, 30, 60, 120, 180, 240, 300} 169 overheadTimeBuckets := []float64{0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1} 170 171 metrics := Metrics{} 172 reg := prometheus.NewRegistry() 173 metrics.metricsDisabled = disabledMetrics 174 175 metrics.connectionsClosed = newCounterWithoutLabels(cfg, reg, 176 "connections_closed", 177 "Count of successful connections closed to Prebid Server.") 178 179 metrics.connectionsError = newCounter(cfg, reg, 180 "connections_error", 181 "Count of errors for connection open and close attempts to Prebid Server labeled by type.", 182 []string{connectionErrorLabel}) 183 184 metrics.connectionsOpened = newCounterWithoutLabels(cfg, reg, 185 "connections_opened", 186 "Count of successful connections opened to Prebid Server.") 187 188 metrics.tmaxTimeout = newCounterWithoutLabels(cfg, reg, 189 "tmax_timeout", 190 "Count of requests rejected due to Tmax timeout exceed.") 191 192 metrics.cookieSync = newCounter(cfg, reg, 193 "cookie_sync_requests", 194 "Count of cookie sync requests to Prebid Server.", 195 []string{statusLabel}) 196 197 metrics.setUid = newCounter(cfg, reg, 198 "setuid_requests", 199 "Count of set uid requests to Prebid Server.", 200 []string{statusLabel}) 201 202 metrics.impressions = newCounter(cfg, reg, 203 "impressions_requests", 204 "Count of requested impressions to Prebid Server labeled by type.", 205 []string{isBannerLabel, isVideoLabel, isAudioLabel, isNativeLabel}) 206 207 metrics.prebidCacheWriteTimer = newHistogramVec(cfg, reg, 208 "prebidcache_write_time_seconds", 209 "Seconds to write to Prebid Cache labeled by success or failure. Failure timing is limited by Prebid Server enforced timeouts.", 210 []string{successLabel}, 211 cacheWriteTimeBuckets) 212 213 metrics.requests = newCounter(cfg, reg, 214 "requests", 215 "Count of total requests to Prebid Server labeled by type and status.", 216 []string{requestTypeLabel, requestStatusLabel}) 217 218 metrics.debugRequests = newCounterWithoutLabels(cfg, reg, 219 "debug_requests", 220 "Count of total requests to Prebid Server that have debug enabled") 221 222 metrics.requestsTimer = newHistogramVec(cfg, reg, 223 "request_time_seconds", 224 "Seconds to resolve successful Prebid Server requests labeled by type.", 225 []string{requestTypeLabel}, 226 standardTimeBuckets) 227 228 metrics.requestsWithoutCookie = newCounter(cfg, reg, 229 "requests_without_cookie", 230 "Count of total requests to Prebid Server without a cookie labeled by type.", 231 []string{requestTypeLabel}) 232 233 metrics.storedImpressionsCacheResult = newCounter(cfg, reg, 234 "stored_impressions_cache_performance", 235 "Count of stored impression cache requests attempts by hits or miss.", 236 []string{cacheResultLabel}) 237 238 metrics.storedRequestCacheResult = newCounter(cfg, reg, 239 "stored_request_cache_performance", 240 "Count of stored request cache requests attempts by hits or miss.", 241 []string{cacheResultLabel}) 242 243 metrics.accountCacheResult = newCounter(cfg, reg, 244 "account_cache_performance", 245 "Count of account cache lookups by hits or miss.", 246 []string{cacheResultLabel}) 247 248 metrics.storedAccountFetchTimer = newHistogramVec(cfg, reg, 249 "stored_account_fetch_time_seconds", 250 "Seconds to fetch stored accounts labeled by fetch type", 251 []string{storedDataFetchTypeLabel}, 252 standardTimeBuckets) 253 254 metrics.storedAccountErrors = newCounter(cfg, reg, 255 "stored_account_errors", 256 "Count of stored account errors by error type", 257 []string{storedDataErrorLabel}) 258 259 metrics.storedAMPFetchTimer = newHistogramVec(cfg, reg, 260 "stored_amp_fetch_time_seconds", 261 "Seconds to fetch stored AMP requests labeled by fetch type", 262 []string{storedDataFetchTypeLabel}, 263 standardTimeBuckets) 264 265 metrics.storedAMPErrors = newCounter(cfg, reg, 266 "stored_amp_errors", 267 "Count of stored AMP errors by error type", 268 []string{storedDataErrorLabel}) 269 270 metrics.storedCategoryFetchTimer = newHistogramVec(cfg, reg, 271 "stored_category_fetch_time_seconds", 272 "Seconds to fetch stored categories labeled by fetch type", 273 []string{storedDataFetchTypeLabel}, 274 standardTimeBuckets) 275 276 metrics.storedCategoryErrors = newCounter(cfg, reg, 277 "stored_category_errors", 278 "Count of stored category errors by error type", 279 []string{storedDataErrorLabel}) 280 281 metrics.storedRequestFetchTimer = newHistogramVec(cfg, reg, 282 "stored_request_fetch_time_seconds", 283 "Seconds to fetch stored requests labeled by fetch type", 284 []string{storedDataFetchTypeLabel}, 285 standardTimeBuckets) 286 287 metrics.storedRequestErrors = newCounter(cfg, reg, 288 "stored_request_errors", 289 "Count of stored request errors by error type", 290 []string{storedDataErrorLabel}) 291 292 metrics.storedVideoFetchTimer = newHistogramVec(cfg, reg, 293 "stored_video_fetch_time_seconds", 294 "Seconds to fetch stored video labeled by fetch type", 295 []string{storedDataFetchTypeLabel}, 296 standardTimeBuckets) 297 298 metrics.storedVideoErrors = newCounter(cfg, reg, 299 "stored_video_errors", 300 "Count of stored video errors by error type", 301 []string{storedDataErrorLabel}) 302 303 metrics.timeoutNotifications = newCounter(cfg, reg, 304 "timeout_notification", 305 "Count of timeout notifications triggered, and if they were successfully sent.", 306 []string{successLabel}) 307 308 metrics.dnsLookupTimer = newHistogram(cfg, reg, 309 "dns_lookup_time", 310 "Seconds to resolve DNS", 311 standardTimeBuckets) 312 313 metrics.tlsHandhakeTimer = newHistogram(cfg, reg, 314 "tls_handshake_time", 315 "Seconds to perform TLS Handshake", 316 standardTimeBuckets) 317 318 metrics.privacyCCPA = newCounter(cfg, reg, 319 "privacy_ccpa", 320 "Count of total requests to Prebid Server where CCPA was provided by source and opt-out .", 321 []string{sourceLabel, optOutLabel}) 322 323 metrics.privacyCOPPA = newCounter(cfg, reg, 324 "privacy_coppa", 325 "Count of total requests to Prebid Server where the COPPA flag was set by source", 326 []string{sourceLabel}) 327 328 metrics.privacyTCF = newCounter(cfg, reg, 329 "privacy_tcf", 330 "Count of TCF versions for requests where GDPR was enforced by source and version.", 331 []string{versionLabel, sourceLabel}) 332 333 metrics.privacyLMT = newCounter(cfg, reg, 334 "privacy_lmt", 335 "Count of total requests to Prebid Server where the LMT flag was set by source", 336 []string{sourceLabel}) 337 338 if !metrics.metricsDisabled.AdapterBuyerUIDScrubbed { 339 metrics.adapterScrubbedBuyerUIDs = newCounter(cfg, reg, 340 "adapter_buyeruids_scrubbed", 341 "Count of total bidder requests with a scrubbed buyeruid due to a privacy policy", 342 []string{adapterLabel}) 343 } 344 if !metrics.metricsDisabled.AdapterGDPRRequestBlocked { 345 metrics.adapterGDPRBlockedRequests = newCounter(cfg, reg, 346 "adapter_gdpr_requests_blocked", 347 "Count of total bidder requests blocked due to unsatisfied GDPR purpose 2 legal basis", 348 []string{adapterLabel}) 349 } 350 351 metrics.storedResponsesFetchTimer = newHistogramVec(cfg, reg, 352 "stored_response_fetch_time_seconds", 353 "Seconds to fetch stored responses labeled by fetch type", 354 []string{storedDataFetchTypeLabel}, 355 standardTimeBuckets) 356 357 metrics.storedResponsesErrors = newCounter(cfg, reg, 358 "stored_response_errors", 359 "Count of stored video errors by error type", 360 []string{storedDataErrorLabel}) 361 362 metrics.storedResponses = newCounterWithoutLabels(cfg, reg, 363 "stored_responses", 364 "Count of total requests to Prebid Server that have stored responses") 365 366 metrics.adapterBids = newCounter(cfg, reg, 367 "adapter_bids", 368 "Count of bids labeled by adapter and markup delivery type (adm or nurl).", 369 []string{adapterLabel, markupDeliveryLabel}) 370 371 metrics.adapterErrors = newCounter(cfg, reg, 372 "adapter_errors", 373 "Count of errors labeled by adapter and error type.", 374 []string{adapterLabel, adapterErrorLabel}) 375 376 metrics.adapterPanics = newCounter(cfg, reg, 377 "adapter_panics", 378 "Count of panics labeled by adapter.", 379 []string{adapterLabel}) 380 381 metrics.adapterPrices = newHistogramVec(cfg, reg, 382 "adapter_prices", 383 "Monetary value of the bids labeled by adapter.", 384 []string{adapterLabel}, 385 priceBuckets) 386 387 metrics.adapterRequests = newCounter(cfg, reg, 388 "adapter_requests", 389 "Count of requests labeled by adapter, if has a cookie, and if it resulted in bids.", 390 []string{adapterLabel, cookieLabel, hasBidsLabel}) 391 392 if !metrics.metricsDisabled.AdapterConnectionMetrics { 393 metrics.adapterCreatedConnections = newCounter(cfg, reg, 394 "adapter_connection_created", 395 "Count that keeps track of new connections when contacting adapter bidder endpoints.", 396 []string{adapterLabel}) 397 398 metrics.adapterReusedConnections = newCounter(cfg, reg, 399 "adapter_connection_reused", 400 "Count that keeps track of reused connections when contacting adapter bidder endpoints.", 401 []string{adapterLabel}) 402 403 metrics.adapterConnectionWaitTime = newHistogramVec(cfg, reg, 404 "adapter_connection_wait", 405 "Seconds from when the connection was requested until it is either created or reused", 406 []string{adapterLabel}, 407 standardTimeBuckets) 408 } 409 410 metrics.adapterBidResponseValidationSizeError = newCounter(cfg, reg, 411 "adapter_response_validation_size_err", 412 "Count that tracks number of bids removed from bid response that had a creative size greater than maxWidth/maxHeight", 413 []string{adapterLabel, successLabel}) 414 415 metrics.adapterBidResponseValidationSizeWarn = newCounter(cfg, reg, 416 "adapter_response_validation_size_warn", 417 "Count that tracks number of bids removed from bid response that had a creative size greater than maxWidth/maxHeight (warn)", 418 []string{adapterLabel, successLabel}) 419 420 metrics.adapterBidResponseSecureMarkupError = newCounter(cfg, reg, 421 "adapter_response_validation_secure_err", 422 "Count that tracks number of bids removed from bid response that had a invalid bidAdm", 423 []string{adapterLabel, successLabel}) 424 425 metrics.adapterBidResponseSecureMarkupWarn = newCounter(cfg, reg, 426 "adapter_response_validation_secure_warn", 427 "Count that tracks number of bids removed from bid response that had a invalid bidAdm (warn)", 428 []string{adapterLabel, successLabel}) 429 430 metrics.overheadTimer = newHistogramVec(cfg, reg, 431 "overhead_time_seconds", 432 "Seconds to prepare adapter request or resolve adapter response", 433 []string{overheadTypeLabel}, 434 overheadTimeBuckets) 435 436 metrics.adapterRequestsTimer = newHistogramVec(cfg, reg, 437 "adapter_request_time_seconds", 438 "Seconds to resolve each successful request labeled by adapter.", 439 []string{adapterLabel}, 440 standardTimeBuckets) 441 442 metrics.bidderServerResponseTimer = newHistogram(cfg, reg, 443 "bidder_server_response_time_seconds", 444 "Duration needed to send HTTP request and receive response back from bidder server.", 445 standardTimeBuckets) 446 447 metrics.syncerRequests = newCounter(cfg, reg, 448 "syncer_requests", 449 "Count of cookie sync requests where a syncer is a candidate to be synced labeled by syncer key and status.", 450 []string{syncerLabel, statusLabel}) 451 452 metrics.syncerSets = newCounter(cfg, reg, 453 "syncer_sets", 454 "Count of setuid set requests for a syncer labeled by syncer key and status.", 455 []string{syncerLabel, statusLabel}) 456 457 metrics.accountRequests = newCounter(cfg, reg, 458 "account_requests", 459 "Count of total requests to Prebid Server labeled by account.", 460 []string{accountLabel}) 461 462 metrics.accountDebugRequests = newCounter(cfg, reg, 463 "account_debug_requests", 464 "Count of total requests to Prebid Server that have debug enabled labled by account", 465 []string{accountLabel}) 466 467 metrics.accountBidResponseValidationSizeError = newCounter(cfg, reg, 468 "account_response_validation_size_err", 469 "Count that tracks number of bids removed from bid response that had a creative size greater than maxWidth/maxHeight labeled by account (enforce) ", 470 []string{accountLabel, successLabel}) 471 472 metrics.accountBidResponseValidationSizeWarn = newCounter(cfg, reg, 473 "account_response_validation_size_warn", 474 "Count that tracks number of bids removed from bid response that had a creative size greater than maxWidth/maxHeight labeled by account (warn)", 475 []string{accountLabel, successLabel}) 476 477 metrics.accountBidResponseSecureMarkupError = newCounter(cfg, reg, 478 "account_response_validation_secure_err", 479 "Count that tracks number of bids removed from bid response that had a invalid bidAdm labeled by account (enforce) ", 480 []string{accountLabel, successLabel}) 481 482 metrics.accountBidResponseSecureMarkupWarn = newCounter(cfg, reg, 483 "account_response_validation_secure_warn", 484 "Count that tracks number of bids removed from bid response that had a invalid bidAdm labeled by account (warn)", 485 []string{accountLabel, successLabel}) 486 487 metrics.requestsQueueTimer = newHistogramVec(cfg, reg, 488 "request_queue_time", 489 "Seconds request was waiting in queue", 490 []string{requestTypeLabel, requestStatusLabel}, 491 queuedRequestTimeBuckets) 492 493 metrics.accountStoredResponses = newCounter(cfg, reg, 494 "account_stored_responses", 495 "Count of total requests to Prebid Server that have stored responses labled by account", 496 []string{accountLabel}) 497 498 metrics.adsCertSignTimer = newHistogram(cfg, reg, 499 "ads_cert_sign_time", 500 "Seconds to generate an AdsCert header", 501 standardTimeBuckets) 502 503 metrics.adsCertRequests = newCounter(cfg, reg, 504 "ads_cert_requests", 505 "Count of AdsCert request, and if they were successfully sent.", 506 []string{successLabel}) 507 508 createModulesMetrics(cfg, reg, &metrics, moduleStageNames, standardTimeBuckets) 509 510 metrics.Gatherer = reg 511 512 metricsPrefix := "" 513 if len(cfg.Namespace) > 0 { 514 metricsPrefix += fmt.Sprintf("%s_", cfg.Namespace) 515 } 516 if len(cfg.Subsystem) > 0 { 517 metricsPrefix += fmt.Sprintf("%s_", cfg.Subsystem) 518 } 519 520 metrics.Registerer = prometheus.WrapRegistererWithPrefix(metricsPrefix, reg) 521 metrics.Registerer.MustRegister(promCollector.NewGoCollector()) 522 523 preloadLabelValues(&metrics, syncerKeys, moduleStageNames) 524 525 return &metrics 526 } 527 528 func createModulesMetrics(cfg config.PrometheusMetrics, registry *prometheus.Registry, m *Metrics, moduleStageNames map[string][]string, standardTimeBuckets []float64) { 529 l := len(moduleStageNames) 530 m.moduleDuration = make(map[string]*prometheus.HistogramVec, l) 531 m.moduleCalls = make(map[string]*prometheus.CounterVec, l) 532 m.moduleFailures = make(map[string]*prometheus.CounterVec, l) 533 m.moduleSuccessNoops = make(map[string]*prometheus.CounterVec, l) 534 m.moduleSuccessUpdates = make(map[string]*prometheus.CounterVec, l) 535 m.moduleSuccessRejects = make(map[string]*prometheus.CounterVec, l) 536 m.moduleExecutionErrors = make(map[string]*prometheus.CounterVec, l) 537 m.moduleTimeouts = make(map[string]*prometheus.CounterVec, l) 538 539 // create for each registered module its own metric 540 for module := range moduleStageNames { 541 m.moduleDuration[module] = newHistogramVec(cfg, registry, 542 fmt.Sprintf("modules_%s_duration", module), 543 "Amount of seconds a module processed a hook labeled by stage name.", 544 []string{stageLabel}, 545 standardTimeBuckets) 546 547 m.moduleCalls[module] = newCounter(cfg, registry, 548 fmt.Sprintf("modules_%s_called", module), 549 "Count of module calls labeled by stage name.", 550 []string{stageLabel}) 551 552 m.moduleFailures[module] = newCounter(cfg, registry, 553 fmt.Sprintf("modules_%s_failed", module), 554 "Count of module fails labeled by stage name.", 555 []string{stageLabel}) 556 557 m.moduleSuccessNoops[module] = newCounter(cfg, registry, 558 fmt.Sprintf("modules_%s_success_noops", module), 559 "Count of module successful noops labeled by stage name.", 560 []string{stageLabel}) 561 562 m.moduleSuccessUpdates[module] = newCounter(cfg, registry, 563 fmt.Sprintf("modules_%s_success_updates", module), 564 "Count of module successful updates labeled by stage name.", 565 []string{stageLabel}) 566 567 m.moduleSuccessRejects[module] = newCounter(cfg, registry, 568 fmt.Sprintf("modules_%s_success_rejects", module), 569 "Count of module successful rejects labeled by stage name.", 570 []string{stageLabel}) 571 572 m.moduleExecutionErrors[module] = newCounter(cfg, registry, 573 fmt.Sprintf("modules_%s_execution_errors", module), 574 "Count of module execution errors labeled by stage name.", 575 []string{stageLabel}) 576 577 m.moduleTimeouts[module] = newCounter(cfg, registry, 578 fmt.Sprintf("modules_%s_timeouts", module), 579 "Count of module timeouts labeled by stage name.", 580 []string{stageLabel}) 581 } 582 } 583 584 func newCounter(cfg config.PrometheusMetrics, registry *prometheus.Registry, name, help string, labels []string) *prometheus.CounterVec { 585 opts := prometheus.CounterOpts{ 586 Namespace: cfg.Namespace, 587 Subsystem: cfg.Subsystem, 588 Name: name, 589 Help: help, 590 } 591 counter := prometheus.NewCounterVec(opts, labels) 592 registry.MustRegister(counter) 593 return counter 594 } 595 596 func newCounterWithoutLabels(cfg config.PrometheusMetrics, registry *prometheus.Registry, name, help string) prometheus.Counter { 597 opts := prometheus.CounterOpts{ 598 Namespace: cfg.Namespace, 599 Subsystem: cfg.Subsystem, 600 Name: name, 601 Help: help, 602 } 603 counter := prometheus.NewCounter(opts) 604 registry.MustRegister(counter) 605 return counter 606 } 607 608 func newHistogramVec(cfg config.PrometheusMetrics, registry *prometheus.Registry, name, help string, labels []string, buckets []float64) *prometheus.HistogramVec { 609 opts := prometheus.HistogramOpts{ 610 Namespace: cfg.Namespace, 611 Subsystem: cfg.Subsystem, 612 Name: name, 613 Help: help, 614 Buckets: buckets, 615 } 616 histogram := prometheus.NewHistogramVec(opts, labels) 617 registry.MustRegister(histogram) 618 return histogram 619 } 620 621 func newHistogram(cfg config.PrometheusMetrics, registry *prometheus.Registry, name, help string, buckets []float64) prometheus.Histogram { 622 opts := prometheus.HistogramOpts{ 623 Namespace: cfg.Namespace, 624 Subsystem: cfg.Subsystem, 625 Name: name, 626 Help: help, 627 Buckets: buckets, 628 } 629 histogram := prometheus.NewHistogram(opts) 630 registry.MustRegister(histogram) 631 return histogram 632 } 633 634 func (m *Metrics) RecordConnectionAccept(success bool) { 635 if success { 636 m.connectionsOpened.Inc() 637 } else { 638 m.connectionsError.With(prometheus.Labels{ 639 connectionErrorLabel: connectionAcceptError, 640 }).Inc() 641 } 642 } 643 644 func (m *Metrics) RecordTMaxTimeout() { 645 m.tmaxTimeout.Inc() 646 } 647 648 func (m *Metrics) RecordConnectionClose(success bool) { 649 if success { 650 m.connectionsClosed.Inc() 651 } else { 652 m.connectionsError.With(prometheus.Labels{ 653 connectionErrorLabel: connectionCloseError, 654 }).Inc() 655 } 656 } 657 658 func (m *Metrics) RecordRequest(labels metrics.Labels) { 659 m.requests.With(prometheus.Labels{ 660 requestTypeLabel: string(labels.RType), 661 requestStatusLabel: string(labels.RequestStatus), 662 }).Inc() 663 664 if labels.CookieFlag == metrics.CookieFlagNo { 665 m.requestsWithoutCookie.With(prometheus.Labels{ 666 requestTypeLabel: string(labels.RType), 667 }).Inc() 668 } 669 670 if labels.PubID != metrics.PublisherUnknown { 671 m.accountRequests.With(prometheus.Labels{ 672 accountLabel: labels.PubID, 673 }).Inc() 674 } 675 } 676 677 func (m *Metrics) RecordDebugRequest(debugEnabled bool, pubID string) { 678 if debugEnabled { 679 m.debugRequests.Inc() 680 if !m.metricsDisabled.AccountDebug && pubID != metrics.PublisherUnknown { 681 m.accountDebugRequests.With(prometheus.Labels{ 682 accountLabel: pubID, 683 }).Inc() 684 } 685 } 686 } 687 688 func (m *Metrics) RecordStoredResponse(pubId string) { 689 m.storedResponses.Inc() 690 if !m.metricsDisabled.AccountStoredResponses && pubId != metrics.PublisherUnknown { 691 m.accountStoredResponses.With(prometheus.Labels{ 692 accountLabel: pubId, 693 }).Inc() 694 } 695 } 696 697 func (m *Metrics) RecordImps(labels metrics.ImpLabels) { 698 m.impressions.With(prometheus.Labels{ 699 isBannerLabel: strconv.FormatBool(labels.BannerImps), 700 isVideoLabel: strconv.FormatBool(labels.VideoImps), 701 isAudioLabel: strconv.FormatBool(labels.AudioImps), 702 isNativeLabel: strconv.FormatBool(labels.NativeImps), 703 }).Inc() 704 } 705 706 func (m *Metrics) RecordRequestTime(labels metrics.Labels, length time.Duration) { 707 if labels.RequestStatus == metrics.RequestStatusOK { 708 m.requestsTimer.With(prometheus.Labels{ 709 requestTypeLabel: string(labels.RType), 710 }).Observe(length.Seconds()) 711 } 712 } 713 714 func (m *Metrics) RecordStoredDataFetchTime(labels metrics.StoredDataLabels, length time.Duration) { 715 switch labels.DataType { 716 case metrics.AccountDataType: 717 m.storedAccountFetchTimer.With(prometheus.Labels{ 718 storedDataFetchTypeLabel: string(labels.DataFetchType), 719 }).Observe(length.Seconds()) 720 case metrics.AMPDataType: 721 m.storedAMPFetchTimer.With(prometheus.Labels{ 722 storedDataFetchTypeLabel: string(labels.DataFetchType), 723 }).Observe(length.Seconds()) 724 case metrics.CategoryDataType: 725 m.storedCategoryFetchTimer.With(prometheus.Labels{ 726 storedDataFetchTypeLabel: string(labels.DataFetchType), 727 }).Observe(length.Seconds()) 728 case metrics.RequestDataType: 729 m.storedRequestFetchTimer.With(prometheus.Labels{ 730 storedDataFetchTypeLabel: string(labels.DataFetchType), 731 }).Observe(length.Seconds()) 732 case metrics.VideoDataType: 733 m.storedVideoFetchTimer.With(prometheus.Labels{ 734 storedDataFetchTypeLabel: string(labels.DataFetchType), 735 }).Observe(length.Seconds()) 736 case metrics.ResponseDataType: 737 m.storedResponsesFetchTimer.With(prometheus.Labels{ 738 storedDataFetchTypeLabel: string(labels.DataFetchType), 739 }).Observe(length.Seconds()) 740 } 741 } 742 743 func (m *Metrics) RecordStoredDataError(labels metrics.StoredDataLabels) { 744 switch labels.DataType { 745 case metrics.AccountDataType: 746 m.storedAccountErrors.With(prometheus.Labels{ 747 storedDataErrorLabel: string(labels.Error), 748 }).Inc() 749 case metrics.AMPDataType: 750 m.storedAMPErrors.With(prometheus.Labels{ 751 storedDataErrorLabel: string(labels.Error), 752 }).Inc() 753 case metrics.CategoryDataType: 754 m.storedCategoryErrors.With(prometheus.Labels{ 755 storedDataErrorLabel: string(labels.Error), 756 }).Inc() 757 case metrics.RequestDataType: 758 m.storedRequestErrors.With(prometheus.Labels{ 759 storedDataErrorLabel: string(labels.Error), 760 }).Inc() 761 case metrics.VideoDataType: 762 m.storedVideoErrors.With(prometheus.Labels{ 763 storedDataErrorLabel: string(labels.Error), 764 }).Inc() 765 case metrics.ResponseDataType: 766 m.storedResponsesErrors.With(prometheus.Labels{ 767 storedDataErrorLabel: string(labels.Error), 768 }).Inc() 769 } 770 } 771 772 func (m *Metrics) RecordAdapterRequest(labels metrics.AdapterLabels) { 773 lowerCasedAdapter := strings.ToLower(string(labels.Adapter)) 774 m.adapterRequests.With(prometheus.Labels{ 775 adapterLabel: lowerCasedAdapter, 776 cookieLabel: string(labels.CookieFlag), 777 hasBidsLabel: strconv.FormatBool(labels.AdapterBids == metrics.AdapterBidPresent), 778 }).Inc() 779 780 for err := range labels.AdapterErrors { 781 m.adapterErrors.With(prometheus.Labels{ 782 adapterLabel: lowerCasedAdapter, 783 adapterErrorLabel: string(err), 784 }).Inc() 785 } 786 } 787 788 // Keeps track of created and reused connections to adapter bidders and the time from the 789 // connection request, to the connection creation, or reuse from the pool across all engines 790 func (m *Metrics) RecordAdapterConnections(adapterName openrtb_ext.BidderName, connWasReused bool, connWaitTime time.Duration) { 791 lowerCasedAdapterName := strings.ToLower(string(adapterName)) 792 if m.metricsDisabled.AdapterConnectionMetrics { 793 return 794 } 795 796 if connWasReused { 797 m.adapterReusedConnections.With(prometheus.Labels{ 798 adapterLabel: lowerCasedAdapterName, 799 }).Inc() 800 } else { 801 m.adapterCreatedConnections.With(prometheus.Labels{ 802 adapterLabel: lowerCasedAdapterName, 803 }).Inc() 804 } 805 806 m.adapterConnectionWaitTime.With(prometheus.Labels{ 807 adapterLabel: lowerCasedAdapterName, 808 }).Observe(connWaitTime.Seconds()) 809 } 810 811 func (m *Metrics) RecordDNSTime(dnsLookupTime time.Duration) { 812 m.dnsLookupTimer.Observe(dnsLookupTime.Seconds()) 813 } 814 815 func (m *Metrics) RecordTLSHandshakeTime(tlsHandshakeTime time.Duration) { 816 m.tlsHandhakeTimer.Observe(tlsHandshakeTime.Seconds()) 817 } 818 819 func (m *Metrics) RecordBidderServerResponseTime(bidderServerResponseTime time.Duration) { 820 m.bidderServerResponseTimer.Observe(bidderServerResponseTime.Seconds()) 821 } 822 823 func (m *Metrics) RecordAdapterPanic(labels metrics.AdapterLabels) { 824 m.adapterPanics.With(prometheus.Labels{ 825 adapterLabel: strings.ToLower(string(labels.Adapter)), 826 }).Inc() 827 } 828 829 func (m *Metrics) RecordAdapterBidReceived(labels metrics.AdapterLabels, bidType openrtb_ext.BidType, hasAdm bool) { 830 markupDelivery := markupDeliveryNurl 831 if hasAdm { 832 markupDelivery = markupDeliveryAdm 833 } 834 835 m.adapterBids.With(prometheus.Labels{ 836 adapterLabel: strings.ToLower(string(labels.Adapter)), 837 markupDeliveryLabel: markupDelivery, 838 }).Inc() 839 } 840 841 func (m *Metrics) RecordAdapterPrice(labels metrics.AdapterLabels, cpm float64) { 842 m.adapterPrices.With(prometheus.Labels{ 843 adapterLabel: strings.ToLower(string(labels.Adapter)), 844 }).Observe(cpm) 845 } 846 847 func (m *Metrics) RecordOverheadTime(overhead metrics.OverheadType, duration time.Duration) { 848 m.overheadTimer.With(prometheus.Labels{ 849 overheadTypeLabel: overhead.String(), 850 }).Observe(duration.Seconds()) 851 } 852 853 func (m *Metrics) RecordAdapterTime(labels metrics.AdapterLabels, length time.Duration) { 854 if len(labels.AdapterErrors) == 0 { 855 m.adapterRequestsTimer.With(prometheus.Labels{ 856 adapterLabel: strings.ToLower(string(labels.Adapter)), 857 }).Observe(length.Seconds()) 858 } 859 } 860 861 func (m *Metrics) RecordCookieSync(status metrics.CookieSyncStatus) { 862 m.cookieSync.With(prometheus.Labels{ 863 statusLabel: string(status), 864 }).Inc() 865 } 866 867 func (m *Metrics) RecordSyncerRequest(key string, status metrics.SyncerCookieSyncStatus) { 868 m.syncerRequests.With(prometheus.Labels{ 869 syncerLabel: key, 870 statusLabel: string(status), 871 }).Inc() 872 } 873 874 func (m *Metrics) RecordSetUid(status metrics.SetUidStatus) { 875 m.setUid.With(prometheus.Labels{ 876 statusLabel: string(status), 877 }).Inc() 878 } 879 880 func (m *Metrics) RecordSyncerSet(key string, status metrics.SyncerSetUidStatus) { 881 m.syncerSets.With(prometheus.Labels{ 882 syncerLabel: key, 883 statusLabel: string(status), 884 }).Inc() 885 } 886 887 func (m *Metrics) RecordStoredReqCacheResult(cacheResult metrics.CacheResult, inc int) { 888 m.storedRequestCacheResult.With(prometheus.Labels{ 889 cacheResultLabel: string(cacheResult), 890 }).Add(float64(inc)) 891 } 892 893 func (m *Metrics) RecordStoredImpCacheResult(cacheResult metrics.CacheResult, inc int) { 894 m.storedImpressionsCacheResult.With(prometheus.Labels{ 895 cacheResultLabel: string(cacheResult), 896 }).Add(float64(inc)) 897 } 898 899 func (m *Metrics) RecordAccountCacheResult(cacheResult metrics.CacheResult, inc int) { 900 m.accountCacheResult.With(prometheus.Labels{ 901 cacheResultLabel: string(cacheResult), 902 }).Add(float64(inc)) 903 } 904 905 func (m *Metrics) RecordPrebidCacheRequestTime(success bool, length time.Duration) { 906 m.prebidCacheWriteTimer.With(prometheus.Labels{ 907 successLabel: strconv.FormatBool(success), 908 }).Observe(length.Seconds()) 909 } 910 911 func (m *Metrics) RecordRequestQueueTime(success bool, requestType metrics.RequestType, length time.Duration) { 912 successLabelFormatted := requestRejectLabel 913 if success { 914 successLabelFormatted = requestSuccessLabel 915 } 916 m.requestsQueueTimer.With(prometheus.Labels{ 917 requestTypeLabel: string(requestType), 918 requestStatusLabel: successLabelFormatted, 919 }).Observe(length.Seconds()) 920 } 921 922 func (m *Metrics) RecordTimeoutNotice(success bool) { 923 if success { 924 m.timeoutNotifications.With(prometheus.Labels{ 925 successLabel: requestSuccessful, 926 }).Inc() 927 } else { 928 m.timeoutNotifications.With(prometheus.Labels{ 929 successLabel: requestFailed, 930 }).Inc() 931 } 932 } 933 934 func (m *Metrics) RecordRequestPrivacy(privacy metrics.PrivacyLabels) { 935 if privacy.CCPAProvided { 936 m.privacyCCPA.With(prometheus.Labels{ 937 sourceLabel: sourceRequest, 938 optOutLabel: strconv.FormatBool(privacy.CCPAEnforced), 939 }).Inc() 940 } 941 942 if privacy.COPPAEnforced { 943 m.privacyCOPPA.With(prometheus.Labels{ 944 sourceLabel: sourceRequest, 945 }).Inc() 946 } 947 948 if privacy.GDPREnforced { 949 m.privacyTCF.With(prometheus.Labels{ 950 versionLabel: string(privacy.GDPRTCFVersion), 951 sourceLabel: sourceRequest, 952 }).Inc() 953 } 954 955 if privacy.LMTEnforced { 956 m.privacyLMT.With(prometheus.Labels{ 957 sourceLabel: sourceRequest, 958 }).Inc() 959 } 960 } 961 962 func (m *Metrics) RecordAdapterBuyerUIDScrubbed(adapterName openrtb_ext.BidderName) { 963 if m.metricsDisabled.AdapterBuyerUIDScrubbed { 964 return 965 } 966 967 m.adapterScrubbedBuyerUIDs.With(prometheus.Labels{ 968 adapterLabel: strings.ToLower(string(adapterName)), 969 }).Inc() 970 } 971 972 func (m *Metrics) RecordAdapterGDPRRequestBlocked(adapterName openrtb_ext.BidderName) { 973 if m.metricsDisabled.AdapterGDPRRequestBlocked { 974 return 975 } 976 977 m.adapterGDPRBlockedRequests.With(prometheus.Labels{ 978 adapterLabel: strings.ToLower(string(adapterName)), 979 }).Inc() 980 } 981 982 func (m *Metrics) RecordAdsCertReq(success bool) { 983 if success { 984 m.adsCertRequests.With(prometheus.Labels{ 985 successLabel: requestSuccessful, 986 }).Inc() 987 } else { 988 m.adsCertRequests.With(prometheus.Labels{ 989 successLabel: requestFailed, 990 }).Inc() 991 } 992 } 993 func (m *Metrics) RecordAdsCertSignTime(adsCertSignTime time.Duration) { 994 m.adsCertSignTimer.Observe(adsCertSignTime.Seconds()) 995 } 996 997 func (m *Metrics) RecordBidValidationCreativeSizeError(adapter openrtb_ext.BidderName, account string) { 998 lowerCasedAdapter := strings.ToLower(string(adapter)) 999 m.adapterBidResponseValidationSizeError.With(prometheus.Labels{ 1000 adapterLabel: lowerCasedAdapter, successLabel: successLabel, 1001 }).Inc() 1002 1003 if !m.metricsDisabled.AccountAdapterDetails && account != metrics.PublisherUnknown { 1004 m.accountBidResponseValidationSizeError.With(prometheus.Labels{ 1005 accountLabel: account, successLabel: successLabel, 1006 }).Inc() 1007 } 1008 } 1009 1010 func (m *Metrics) RecordBidValidationCreativeSizeWarn(adapter openrtb_ext.BidderName, account string) { 1011 lowerCasedAdapter := strings.ToLower(string(adapter)) 1012 m.adapterBidResponseValidationSizeWarn.With(prometheus.Labels{ 1013 adapterLabel: lowerCasedAdapter, successLabel: successLabel, 1014 }).Inc() 1015 1016 if !m.metricsDisabled.AccountAdapterDetails && account != metrics.PublisherUnknown { 1017 m.accountBidResponseValidationSizeWarn.With(prometheus.Labels{ 1018 accountLabel: account, successLabel: successLabel, 1019 }).Inc() 1020 } 1021 } 1022 1023 func (m *Metrics) RecordBidValidationSecureMarkupError(adapter openrtb_ext.BidderName, account string) { 1024 m.adapterBidResponseSecureMarkupError.With(prometheus.Labels{ 1025 adapterLabel: strings.ToLower(string(adapter)), successLabel: successLabel, 1026 }).Inc() 1027 1028 if !m.metricsDisabled.AccountAdapterDetails && account != metrics.PublisherUnknown { 1029 m.accountBidResponseSecureMarkupError.With(prometheus.Labels{ 1030 accountLabel: account, successLabel: successLabel, 1031 }).Inc() 1032 } 1033 } 1034 1035 func (m *Metrics) RecordBidValidationSecureMarkupWarn(adapter openrtb_ext.BidderName, account string) { 1036 m.adapterBidResponseSecureMarkupWarn.With(prometheus.Labels{ 1037 adapterLabel: strings.ToLower(string(adapter)), successLabel: successLabel, 1038 }).Inc() 1039 1040 if !m.metricsDisabled.AccountAdapterDetails && account != metrics.PublisherUnknown { 1041 m.accountBidResponseSecureMarkupWarn.With(prometheus.Labels{ 1042 accountLabel: account, successLabel: successLabel, 1043 }).Inc() 1044 } 1045 } 1046 1047 func (m *Metrics) RecordModuleCalled(labels metrics.ModuleLabels, duration time.Duration) { 1048 m.moduleCalls[labels.Module].With(prometheus.Labels{ 1049 stageLabel: labels.Stage, 1050 }).Inc() 1051 1052 m.moduleDuration[labels.Module].With(prometheus.Labels{ 1053 stageLabel: labels.Stage, 1054 }).Observe(duration.Seconds()) 1055 } 1056 1057 func (m *Metrics) RecordModuleFailed(labels metrics.ModuleLabels) { 1058 m.moduleFailures[labels.Module].With(prometheus.Labels{ 1059 stageLabel: labels.Stage, 1060 }).Inc() 1061 } 1062 1063 func (m *Metrics) RecordModuleSuccessNooped(labels metrics.ModuleLabels) { 1064 m.moduleSuccessNoops[labels.Module].With(prometheus.Labels{ 1065 stageLabel: labels.Stage, 1066 }).Inc() 1067 } 1068 1069 func (m *Metrics) RecordModuleSuccessUpdated(labels metrics.ModuleLabels) { 1070 m.moduleSuccessUpdates[labels.Module].With(prometheus.Labels{ 1071 stageLabel: labels.Stage, 1072 }).Inc() 1073 } 1074 1075 func (m *Metrics) RecordModuleSuccessRejected(labels metrics.ModuleLabels) { 1076 m.moduleSuccessRejects[labels.Module].With(prometheus.Labels{ 1077 stageLabel: labels.Stage, 1078 }).Inc() 1079 } 1080 1081 func (m *Metrics) RecordModuleExecutionError(labels metrics.ModuleLabels) { 1082 m.moduleExecutionErrors[labels.Module].With(prometheus.Labels{ 1083 stageLabel: labels.Stage, 1084 }).Inc() 1085 } 1086 1087 func (m *Metrics) RecordModuleTimeout(labels metrics.ModuleLabels) { 1088 m.moduleTimeouts[labels.Module].With(prometheus.Labels{ 1089 stageLabel: labels.Stage, 1090 }).Inc() 1091 }