github.com/prebid/prebid-server@v0.275.0/metrics/go_metrics.go (about) 1 package metrics 2 3 import ( 4 "fmt" 5 "sync" 6 "time" 7 8 "github.com/golang/glog" 9 "github.com/prebid/prebid-server/config" 10 "github.com/prebid/prebid-server/openrtb_ext" 11 metrics "github.com/rcrowley/go-metrics" 12 ) 13 14 type Metrics struct { 15 MetricsRegistry metrics.Registry 16 ConnectionCounter metrics.Counter 17 TMaxTimeoutCounter metrics.Counter 18 ConnectionAcceptErrorMeter metrics.Meter 19 ConnectionCloseErrorMeter metrics.Meter 20 ImpMeter metrics.Meter 21 AppRequestMeter metrics.Meter 22 NoCookieMeter metrics.Meter 23 DebugRequestMeter metrics.Meter 24 RequestTimer metrics.Timer 25 RequestsQueueTimer map[RequestType]map[bool]metrics.Timer 26 PrebidCacheRequestTimerSuccess metrics.Timer 27 PrebidCacheRequestTimerError metrics.Timer 28 StoredDataFetchTimer map[StoredDataType]map[StoredDataFetchType]metrics.Timer 29 StoredDataErrorMeter map[StoredDataType]map[StoredDataError]metrics.Meter 30 StoredReqCacheMeter map[CacheResult]metrics.Meter 31 StoredImpCacheMeter map[CacheResult]metrics.Meter 32 AccountCacheMeter map[CacheResult]metrics.Meter 33 DNSLookupTimer metrics.Timer 34 TLSHandshakeTimer metrics.Timer 35 BidderServerResponseTimer metrics.Timer 36 StoredResponsesMeter metrics.Meter 37 38 // Metrics for OpenRTB requests specifically 39 RequestStatuses map[RequestType]map[RequestStatus]metrics.Meter 40 AmpNoCookieMeter metrics.Meter 41 CookieSyncMeter metrics.Meter 42 CookieSyncStatusMeter map[CookieSyncStatus]metrics.Meter 43 SyncerRequestsMeter map[string]map[SyncerCookieSyncStatus]metrics.Meter 44 SetUidMeter metrics.Meter 45 SetUidStatusMeter map[SetUidStatus]metrics.Meter 46 SyncerSetsMeter map[string]map[SyncerSetUidStatus]metrics.Meter 47 48 // Media types found in the "imp" JSON object 49 ImpsTypeBanner metrics.Meter 50 ImpsTypeVideo metrics.Meter 51 ImpsTypeAudio metrics.Meter 52 ImpsTypeNative metrics.Meter 53 54 // Notification timeout metrics 55 TimeoutNotificationSuccess metrics.Meter 56 TimeoutNotificationFailure metrics.Meter 57 58 // TCF adaption metrics 59 PrivacyCCPARequest metrics.Meter 60 PrivacyCCPARequestOptOut metrics.Meter 61 PrivacyCOPPARequest metrics.Meter 62 PrivacyLMTRequest metrics.Meter 63 PrivacyTCFRequestVersion map[TCFVersionValue]metrics.Meter 64 65 AdapterMetrics map[openrtb_ext.BidderName]*AdapterMetrics 66 // Don't export accountMetrics because we need helper functions here to insure its properly populated dynamically 67 accountMetrics map[string]*accountMetrics 68 accountMetricsRWMutex sync.RWMutex 69 70 exchanges []openrtb_ext.BidderName 71 modules []string 72 // Will hold boolean values to help us disable metric collection if needed 73 MetricsDisabled config.DisabledMetrics 74 75 // AdsCert metrics 76 AdsCertRequestsSuccess metrics.Meter 77 AdsCertRequestsFailure metrics.Meter 78 adsCertSignTimer metrics.Timer 79 80 // Module metrics 81 ModuleMetrics map[string]map[string]*ModuleMetrics 82 83 OverheadTimer map[OverheadType]metrics.Timer 84 } 85 86 // AdapterMetrics houses the metrics for a particular adapter 87 type AdapterMetrics struct { 88 NoCookieMeter metrics.Meter 89 ErrorMeters map[AdapterError]metrics.Meter 90 NoBidMeter metrics.Meter 91 GotBidsMeter metrics.Meter 92 RequestTimer metrics.Timer 93 PriceHistogram metrics.Histogram 94 BidsReceivedMeter metrics.Meter 95 PanicMeter metrics.Meter 96 MarkupMetrics map[openrtb_ext.BidType]*MarkupDeliveryMetrics 97 ConnCreated metrics.Counter 98 ConnReused metrics.Counter 99 ConnWaitTime metrics.Timer 100 GDPRRequestBlocked metrics.Meter 101 102 BidValidationCreativeSizeErrorMeter metrics.Meter 103 BidValidationCreativeSizeWarnMeter metrics.Meter 104 105 BidValidationSecureMarkupErrorMeter metrics.Meter 106 BidValidationSecureMarkupWarnMeter metrics.Meter 107 } 108 109 type MarkupDeliveryMetrics struct { 110 AdmMeter metrics.Meter 111 NurlMeter metrics.Meter 112 } 113 114 type accountMetrics struct { 115 requestMeter metrics.Meter 116 debugRequestMeter metrics.Meter 117 bidsReceivedMeter metrics.Meter 118 priceHistogram metrics.Histogram 119 // store account by adapter metrics. Type is map[PBSBidder.BidderCode] 120 adapterMetrics map[openrtb_ext.BidderName]*AdapterMetrics 121 moduleMetrics map[string]*ModuleMetrics 122 storedResponsesMeter metrics.Meter 123 124 bidValidationCreativeSizeMeter metrics.Meter 125 bidValidationCreativeSizeWarnMeter metrics.Meter 126 bidValidationSecureMarkupMeter metrics.Meter 127 bidValidationSecureMarkupWarnMeter metrics.Meter 128 129 // Account Deprciation Metrics 130 accountDeprecationWarningsPurpose1Meter metrics.Meter 131 accountDeprecationWarningsPurpose2Meter metrics.Meter 132 accountDeprecationWarningsPurpose3Meter metrics.Meter 133 accountDeprecationWarningsPurpose4Meter metrics.Meter 134 accountDeprecationWarningsPurpose5Meter metrics.Meter 135 accountDeprecationWarningsPurpose6Meter metrics.Meter 136 accountDeprecationWarningsPurpose7Meter metrics.Meter 137 accountDeprecationWarningsPurpose8Meter metrics.Meter 138 accountDeprecationWarningsPurpose9Meter metrics.Meter 139 accountDeprecationWarningsPurpose10Meter metrics.Meter 140 channelEnabledGDPRMeter metrics.Meter 141 channelEnabledCCPAMeter metrics.Meter 142 accountDeprecationSummaryMeter metrics.Meter 143 } 144 145 type ModuleMetrics struct { 146 DurationTimer metrics.Timer 147 CallCounter metrics.Counter 148 FailureCounter metrics.Counter 149 SuccessNoopCounter metrics.Counter 150 SuccessUpdateCounter metrics.Counter 151 SuccessRejectCounter metrics.Counter 152 ExecutionErrorCounter metrics.Counter 153 TimeoutCounter metrics.Counter 154 } 155 156 // NewBlankMetrics creates a new Metrics object with all blank metrics object. This may also be useful for 157 // testing routines to ensure that no metrics are written anywhere. 158 // 159 // This will be useful when removing endpoints, we can just run will the blank metrics function 160 // rather than loading metrics that never get filled. 161 // This will also eventually let us configure metrics, such as setting a limited set of metrics 162 // for a production instance, and then expanding again when we need more debugging. 163 func NewBlankMetrics(registry metrics.Registry, exchanges []openrtb_ext.BidderName, disabledMetrics config.DisabledMetrics, moduleStageNames map[string][]string) *Metrics { 164 blankMeter := &metrics.NilMeter{} 165 blankTimer := &metrics.NilTimer{} 166 167 newMetrics := &Metrics{ 168 MetricsRegistry: registry, 169 RequestStatuses: make(map[RequestType]map[RequestStatus]metrics.Meter), 170 ConnectionCounter: metrics.NilCounter{}, 171 ConnectionAcceptErrorMeter: blankMeter, 172 ConnectionCloseErrorMeter: blankMeter, 173 ImpMeter: blankMeter, 174 AppRequestMeter: blankMeter, 175 DebugRequestMeter: blankMeter, 176 NoCookieMeter: blankMeter, 177 RequestTimer: blankTimer, 178 DNSLookupTimer: blankTimer, 179 TLSHandshakeTimer: blankTimer, 180 RequestsQueueTimer: make(map[RequestType]map[bool]metrics.Timer), 181 PrebidCacheRequestTimerSuccess: blankTimer, 182 PrebidCacheRequestTimerError: blankTimer, 183 StoredDataFetchTimer: make(map[StoredDataType]map[StoredDataFetchType]metrics.Timer), 184 StoredDataErrorMeter: make(map[StoredDataType]map[StoredDataError]metrics.Meter), 185 StoredReqCacheMeter: make(map[CacheResult]metrics.Meter), 186 StoredImpCacheMeter: make(map[CacheResult]metrics.Meter), 187 AccountCacheMeter: make(map[CacheResult]metrics.Meter), 188 AmpNoCookieMeter: blankMeter, 189 CookieSyncMeter: blankMeter, 190 CookieSyncStatusMeter: make(map[CookieSyncStatus]metrics.Meter), 191 SyncerRequestsMeter: make(map[string]map[SyncerCookieSyncStatus]metrics.Meter), 192 SetUidMeter: blankMeter, 193 SetUidStatusMeter: make(map[SetUidStatus]metrics.Meter), 194 SyncerSetsMeter: make(map[string]map[SyncerSetUidStatus]metrics.Meter), 195 StoredResponsesMeter: blankMeter, 196 197 ImpsTypeBanner: blankMeter, 198 ImpsTypeVideo: blankMeter, 199 ImpsTypeAudio: blankMeter, 200 ImpsTypeNative: blankMeter, 201 202 TimeoutNotificationSuccess: blankMeter, 203 TimeoutNotificationFailure: blankMeter, 204 205 PrivacyCCPARequest: blankMeter, 206 PrivacyCCPARequestOptOut: blankMeter, 207 PrivacyCOPPARequest: blankMeter, 208 PrivacyLMTRequest: blankMeter, 209 PrivacyTCFRequestVersion: make(map[TCFVersionValue]metrics.Meter, len(TCFVersions())), 210 211 AdapterMetrics: make(map[openrtb_ext.BidderName]*AdapterMetrics, len(exchanges)), 212 accountMetrics: make(map[string]*accountMetrics), 213 MetricsDisabled: disabledMetrics, 214 215 AdsCertRequestsSuccess: blankMeter, 216 AdsCertRequestsFailure: blankMeter, 217 adsCertSignTimer: blankTimer, 218 219 ModuleMetrics: make(map[string]map[string]*ModuleMetrics), 220 221 exchanges: exchanges, 222 modules: getModuleNames(moduleStageNames), 223 224 OverheadTimer: makeBlankOverheadTimerMetrics(), 225 BidderServerResponseTimer: blankTimer, 226 } 227 228 for _, a := range exchanges { 229 newMetrics.AdapterMetrics[a] = makeBlankAdapterMetrics(newMetrics.MetricsDisabled) 230 } 231 232 for module, stages := range moduleStageNames { 233 newMetrics.ModuleMetrics[module] = makeBlankModuleStageMetrics(stages) 234 } 235 236 for _, t := range RequestTypes() { 237 newMetrics.RequestStatuses[t] = make(map[RequestStatus]metrics.Meter) 238 for _, s := range RequestStatuses() { 239 newMetrics.RequestStatuses[t][s] = blankMeter 240 } 241 } 242 243 for _, c := range CacheResults() { 244 newMetrics.StoredReqCacheMeter[c] = blankMeter 245 newMetrics.StoredImpCacheMeter[c] = blankMeter 246 newMetrics.AccountCacheMeter[c] = blankMeter 247 } 248 249 for _, v := range TCFVersions() { 250 newMetrics.PrivacyTCFRequestVersion[v] = blankMeter 251 } 252 253 for _, dt := range StoredDataTypes() { 254 newMetrics.StoredDataFetchTimer[dt] = make(map[StoredDataFetchType]metrics.Timer) 255 newMetrics.StoredDataErrorMeter[dt] = make(map[StoredDataError]metrics.Meter) 256 for _, ft := range StoredDataFetchTypes() { 257 newMetrics.StoredDataFetchTimer[dt][ft] = blankTimer 258 } 259 for _, e := range StoredDataErrors() { 260 newMetrics.StoredDataErrorMeter[dt][e] = blankMeter 261 } 262 } 263 264 //to minimize memory usage, queuedTimeout metric is now supported for video endpoint only 265 //boolean value represents 2 general request statuses: accepted and rejected 266 newMetrics.RequestsQueueTimer["video"] = make(map[bool]metrics.Timer) 267 newMetrics.RequestsQueueTimer["video"][true] = blankTimer 268 newMetrics.RequestsQueueTimer["video"][false] = blankTimer 269 return newMetrics 270 } 271 272 func getModuleNames(moduleStageNames map[string][]string) []string { 273 names := make([]string, len(moduleStageNames)) 274 275 i := 0 276 for moduleName := range moduleStageNames { 277 names[i] = moduleName 278 i++ 279 } 280 281 return names 282 } 283 284 // NewMetrics creates a new Metrics object with needed metrics defined. In time we may develop to the point 285 // where Metrics contains all the metrics we might want to record, and then we build the actual 286 // metrics object to contain only the metrics we are interested in. This would allow for debug 287 // mode metrics. The code would allways try to record the metrics, but effectively noop if we are 288 // using a blank meter/timer. 289 func NewMetrics(registry metrics.Registry, exchanges []openrtb_ext.BidderName, disableAccountMetrics config.DisabledMetrics, syncerKeys []string, moduleStageNames map[string][]string) *Metrics { 290 newMetrics := NewBlankMetrics(registry, exchanges, disableAccountMetrics, moduleStageNames) 291 newMetrics.ConnectionCounter = metrics.GetOrRegisterCounter("active_connections", registry) 292 newMetrics.TMaxTimeoutCounter = metrics.GetOrRegisterCounter("tmax_timeout", registry) 293 newMetrics.ConnectionAcceptErrorMeter = metrics.GetOrRegisterMeter("connection_accept_errors", registry) 294 newMetrics.ConnectionCloseErrorMeter = metrics.GetOrRegisterMeter("connection_close_errors", registry) 295 newMetrics.ImpMeter = metrics.GetOrRegisterMeter("imps_requested", registry) 296 297 newMetrics.ImpsTypeBanner = metrics.GetOrRegisterMeter("imp_banner", registry) 298 newMetrics.ImpsTypeVideo = metrics.GetOrRegisterMeter("imp_video", registry) 299 newMetrics.ImpsTypeAudio = metrics.GetOrRegisterMeter("imp_audio", registry) 300 newMetrics.ImpsTypeNative = metrics.GetOrRegisterMeter("imp_native", registry) 301 302 newMetrics.NoCookieMeter = metrics.GetOrRegisterMeter("no_cookie_requests", registry) 303 newMetrics.AppRequestMeter = metrics.GetOrRegisterMeter("app_requests", registry) 304 newMetrics.DebugRequestMeter = metrics.GetOrRegisterMeter("debug_requests", registry) 305 newMetrics.RequestTimer = metrics.GetOrRegisterTimer("request_time", registry) 306 newMetrics.DNSLookupTimer = metrics.GetOrRegisterTimer("dns_lookup_time", registry) 307 newMetrics.TLSHandshakeTimer = metrics.GetOrRegisterTimer("tls_handshake_time", registry) 308 newMetrics.PrebidCacheRequestTimerSuccess = metrics.GetOrRegisterTimer("prebid_cache_request_time.ok", registry) 309 newMetrics.PrebidCacheRequestTimerError = metrics.GetOrRegisterTimer("prebid_cache_request_time.err", registry) 310 newMetrics.StoredResponsesMeter = metrics.GetOrRegisterMeter("stored_responses", registry) 311 newMetrics.OverheadTimer = makeOverheadTimerMetrics(registry) 312 newMetrics.BidderServerResponseTimer = metrics.GetOrRegisterTimer("bidder_server_response_time_seconds", registry) 313 314 for _, dt := range StoredDataTypes() { 315 for _, ft := range StoredDataFetchTypes() { 316 timerName := fmt.Sprintf("stored_%s_fetch_time.%s", string(dt), string(ft)) 317 newMetrics.StoredDataFetchTimer[dt][ft] = metrics.GetOrRegisterTimer(timerName, registry) 318 } 319 for _, e := range StoredDataErrors() { 320 meterName := fmt.Sprintf("stored_%s_error.%s", string(dt), string(e)) 321 newMetrics.StoredDataErrorMeter[dt][e] = metrics.GetOrRegisterMeter(meterName, registry) 322 } 323 } 324 325 newMetrics.AmpNoCookieMeter = metrics.GetOrRegisterMeter("amp_no_cookie_requests", registry) 326 327 newMetrics.CookieSyncMeter = metrics.GetOrRegisterMeter("cookie_sync_requests", registry) 328 for _, s := range CookieSyncStatuses() { 329 newMetrics.CookieSyncStatusMeter[s] = metrics.GetOrRegisterMeter(fmt.Sprintf("cookie_sync_requests.%s", s), registry) 330 } 331 332 newMetrics.SetUidMeter = metrics.GetOrRegisterMeter("setuid_requests", registry) 333 for _, s := range SetUidStatuses() { 334 newMetrics.SetUidStatusMeter[s] = metrics.GetOrRegisterMeter(fmt.Sprintf("setuid_requests.%s", s), registry) 335 } 336 337 for _, syncerKey := range syncerKeys { 338 newMetrics.SyncerRequestsMeter[syncerKey] = make(map[SyncerCookieSyncStatus]metrics.Meter) 339 for _, status := range SyncerRequestStatuses() { 340 newMetrics.SyncerRequestsMeter[syncerKey][status] = metrics.GetOrRegisterMeter(fmt.Sprintf("syncer.%s.request.%s", syncerKey, status), registry) 341 } 342 343 newMetrics.SyncerSetsMeter[syncerKey] = make(map[SyncerSetUidStatus]metrics.Meter) 344 for _, status := range SyncerSetUidStatuses() { 345 newMetrics.SyncerSetsMeter[syncerKey][status] = metrics.GetOrRegisterMeter(fmt.Sprintf("syncer.%s.set.%s", syncerKey, status), registry) 346 } 347 } 348 349 for _, a := range exchanges { 350 registerAdapterMetrics(registry, "adapter", string(a), newMetrics.AdapterMetrics[a]) 351 } 352 353 for typ, statusMap := range newMetrics.RequestStatuses { 354 for stat := range statusMap { 355 statusMap[stat] = metrics.GetOrRegisterMeter("requests."+string(stat)+"."+string(typ), registry) 356 } 357 } 358 359 for _, cacheRes := range CacheResults() { 360 newMetrics.StoredReqCacheMeter[cacheRes] = metrics.GetOrRegisterMeter(fmt.Sprintf("stored_request_cache_%s", string(cacheRes)), registry) 361 newMetrics.StoredImpCacheMeter[cacheRes] = metrics.GetOrRegisterMeter(fmt.Sprintf("stored_imp_cache_%s", string(cacheRes)), registry) 362 newMetrics.AccountCacheMeter[cacheRes] = metrics.GetOrRegisterMeter(fmt.Sprintf("account_cache_%s", string(cacheRes)), registry) 363 } 364 365 newMetrics.RequestsQueueTimer["video"][true] = metrics.GetOrRegisterTimer("queued_requests.video.accepted", registry) 366 newMetrics.RequestsQueueTimer["video"][false] = metrics.GetOrRegisterTimer("queued_requests.video.rejected", registry) 367 368 newMetrics.TimeoutNotificationSuccess = metrics.GetOrRegisterMeter("timeout_notification.ok", registry) 369 newMetrics.TimeoutNotificationFailure = metrics.GetOrRegisterMeter("timeout_notification.failed", registry) 370 371 newMetrics.PrivacyCCPARequest = metrics.GetOrRegisterMeter("privacy.request.ccpa.specified", registry) 372 newMetrics.PrivacyCCPARequestOptOut = metrics.GetOrRegisterMeter("privacy.request.ccpa.opt-out", registry) 373 newMetrics.PrivacyCOPPARequest = metrics.GetOrRegisterMeter("privacy.request.coppa", registry) 374 newMetrics.PrivacyLMTRequest = metrics.GetOrRegisterMeter("privacy.request.lmt", registry) 375 for _, version := range TCFVersions() { 376 newMetrics.PrivacyTCFRequestVersion[version] = metrics.GetOrRegisterMeter(fmt.Sprintf("privacy.request.tcf.%s", string(version)), registry) 377 } 378 379 newMetrics.AdsCertRequestsSuccess = metrics.GetOrRegisterMeter("ads_cert_requests.ok", registry) 380 newMetrics.AdsCertRequestsFailure = metrics.GetOrRegisterMeter("ads_cert_requests.failed", registry) 381 newMetrics.adsCertSignTimer = metrics.GetOrRegisterTimer("ads_cert_sign_time", registry) 382 383 for module, stages := range moduleStageNames { 384 registerModuleMetrics(registry, module, stages, newMetrics.ModuleMetrics[module]) 385 } 386 387 return newMetrics 388 } 389 390 func makeBlankOverheadTimerMetrics() map[OverheadType]metrics.Timer { 391 m := make(map[OverheadType]metrics.Timer) 392 overheads := OverheadTypes() 393 for idx := range overheads { 394 m[overheads[idx]] = &metrics.NilTimer{} 395 } 396 return m 397 } 398 399 // Part of setting up blank metrics, the adapter metrics. 400 func makeBlankAdapterMetrics(disabledMetrics config.DisabledMetrics) *AdapterMetrics { 401 blankMeter := &metrics.NilMeter{} 402 newAdapter := &AdapterMetrics{ 403 NoCookieMeter: blankMeter, 404 ErrorMeters: make(map[AdapterError]metrics.Meter), 405 NoBidMeter: blankMeter, 406 GotBidsMeter: blankMeter, 407 RequestTimer: &metrics.NilTimer{}, 408 PriceHistogram: &metrics.NilHistogram{}, 409 BidsReceivedMeter: blankMeter, 410 PanicMeter: blankMeter, 411 MarkupMetrics: makeBlankBidMarkupMetrics(), 412 } 413 if !disabledMetrics.AdapterConnectionMetrics { 414 newAdapter.ConnCreated = metrics.NilCounter{} 415 newAdapter.ConnReused = metrics.NilCounter{} 416 newAdapter.ConnWaitTime = &metrics.NilTimer{} 417 } 418 if !disabledMetrics.AdapterGDPRRequestBlocked { 419 newAdapter.GDPRRequestBlocked = blankMeter 420 } 421 for _, err := range AdapterErrors() { 422 newAdapter.ErrorMeters[err] = blankMeter 423 } 424 return newAdapter 425 } 426 427 func makeBlankModuleStageMetrics(stages []string) map[string]*ModuleMetrics { 428 blankMetrics := map[string]*ModuleMetrics{} 429 for _, stage := range stages { 430 blankMetrics[stage] = makeBlankModuleMetrics() 431 } 432 433 return blankMetrics 434 } 435 436 func makeBlankModuleMetrics() *ModuleMetrics { 437 return &ModuleMetrics{ 438 DurationTimer: &metrics.NilTimer{}, 439 CallCounter: metrics.NilCounter{}, 440 FailureCounter: metrics.NilCounter{}, 441 SuccessNoopCounter: metrics.NilCounter{}, 442 SuccessUpdateCounter: metrics.NilCounter{}, 443 SuccessRejectCounter: metrics.NilCounter{}, 444 ExecutionErrorCounter: metrics.NilCounter{}, 445 TimeoutCounter: metrics.NilCounter{}, 446 } 447 } 448 449 func makeBlankBidMarkupMetrics() map[openrtb_ext.BidType]*MarkupDeliveryMetrics { 450 return map[openrtb_ext.BidType]*MarkupDeliveryMetrics{ 451 openrtb_ext.BidTypeAudio: makeBlankMarkupDeliveryMetrics(), 452 openrtb_ext.BidTypeBanner: makeBlankMarkupDeliveryMetrics(), 453 openrtb_ext.BidTypeNative: makeBlankMarkupDeliveryMetrics(), 454 openrtb_ext.BidTypeVideo: makeBlankMarkupDeliveryMetrics(), 455 } 456 } 457 458 func makeBlankMarkupDeliveryMetrics() *MarkupDeliveryMetrics { 459 return &MarkupDeliveryMetrics{ 460 AdmMeter: &metrics.NilMeter{}, 461 NurlMeter: &metrics.NilMeter{}, 462 } 463 } 464 465 func makeOverheadTimerMetrics(registry metrics.Registry) map[OverheadType]metrics.Timer { 466 m := make(map[OverheadType]metrics.Timer) 467 overheads := OverheadTypes() 468 for idx := range overheads { 469 m[overheads[idx]] = metrics.GetOrRegisterTimer("request_over_head_time."+overheads[idx].String(), registry) 470 } 471 return m 472 } 473 474 func registerAdapterMetrics(registry metrics.Registry, adapterOrAccount string, exchange string, am *AdapterMetrics) { 475 am.NoCookieMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.no_cookie_requests", adapterOrAccount, exchange), registry) 476 am.NoBidMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.requests.nobid", adapterOrAccount, exchange), registry) 477 am.GotBidsMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.requests.gotbids", adapterOrAccount, exchange), registry) 478 am.RequestTimer = metrics.GetOrRegisterTimer(fmt.Sprintf("%[1]s.%[2]s.request_time", adapterOrAccount, exchange), registry) 479 am.PriceHistogram = metrics.GetOrRegisterHistogram(fmt.Sprintf("%[1]s.%[2]s.prices", adapterOrAccount, exchange), registry, metrics.NewExpDecaySample(1028, 0.015)) 480 am.MarkupMetrics = map[openrtb_ext.BidType]*MarkupDeliveryMetrics{ 481 openrtb_ext.BidTypeBanner: makeDeliveryMetrics(registry, adapterOrAccount+"."+exchange, openrtb_ext.BidTypeBanner), 482 openrtb_ext.BidTypeVideo: makeDeliveryMetrics(registry, adapterOrAccount+"."+exchange, openrtb_ext.BidTypeVideo), 483 openrtb_ext.BidTypeAudio: makeDeliveryMetrics(registry, adapterOrAccount+"."+exchange, openrtb_ext.BidTypeAudio), 484 openrtb_ext.BidTypeNative: makeDeliveryMetrics(registry, adapterOrAccount+"."+exchange, openrtb_ext.BidTypeNative), 485 } 486 am.ConnCreated = metrics.GetOrRegisterCounter(fmt.Sprintf("%[1]s.%[2]s.connections_created", adapterOrAccount, exchange), registry) 487 am.ConnReused = metrics.GetOrRegisterCounter(fmt.Sprintf("%[1]s.%[2]s.connections_reused", adapterOrAccount, exchange), registry) 488 am.ConnWaitTime = metrics.GetOrRegisterTimer(fmt.Sprintf("%[1]s.%[2]s.connection_wait_time", adapterOrAccount, exchange), registry) 489 for err := range am.ErrorMeters { 490 am.ErrorMeters[err] = metrics.GetOrRegisterMeter(fmt.Sprintf("%s.%s.requests.%s", adapterOrAccount, exchange, err), registry) 491 } 492 if adapterOrAccount != "adapter" { 493 am.BidsReceivedMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.bids_received", adapterOrAccount, exchange), registry) 494 } 495 am.PanicMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.requests.panic", adapterOrAccount, exchange), registry) 496 am.GDPRRequestBlocked = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.gdpr_request_blocked", adapterOrAccount, exchange), registry) 497 498 am.BidValidationCreativeSizeErrorMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.response.validation.size.err", adapterOrAccount, exchange), registry) 499 am.BidValidationCreativeSizeWarnMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.response.validation.size.warn", adapterOrAccount, exchange), registry) 500 501 am.BidValidationSecureMarkupErrorMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.response.validation.secure.err", adapterOrAccount, exchange), registry) 502 am.BidValidationSecureMarkupWarnMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("%[1]s.%[2]s.response.validation.secure.warn", adapterOrAccount, exchange), registry) 503 } 504 505 func registerModuleMetrics(registry metrics.Registry, module string, stages []string, mm map[string]*ModuleMetrics) { 506 for _, stage := range stages { 507 mm[stage].DurationTimer = metrics.GetOrRegisterTimer(fmt.Sprintf("modules.module.%s.stage.%s.duration", module, stage), registry) 508 mm[stage].CallCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("modules.module.%s.stage.%s.call", module, stage), registry) 509 mm[stage].FailureCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("modules.module.%s.stage.%s.failure", module, stage), registry) 510 mm[stage].SuccessNoopCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("modules.module.%s.stage.%s.success.noop", module, stage), registry) 511 mm[stage].SuccessUpdateCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("modules.module.%s.stage.%s.success.update", module, stage), registry) 512 mm[stage].SuccessRejectCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("modules.module.%s.stage.%s.success.reject", module, stage), registry) 513 mm[stage].ExecutionErrorCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("modules.module.%s.stage.%s.execution_error", module, stage), registry) 514 mm[stage].TimeoutCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("modules.module.%s.stage.%s.timeout", module, stage), registry) 515 } 516 } 517 518 func registerAccountModuleMetrics(registry metrics.Registry, id string, module string, mm *ModuleMetrics) { 519 mm.DurationTimer = metrics.GetOrRegisterTimer(fmt.Sprintf("account.%s.modules.module.%s.duration", id, module), registry) 520 mm.CallCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("account.%s.modules.module.%s.call", id, module), registry) 521 mm.FailureCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("account.%s.modules.module.%s.failure", id, module), registry) 522 mm.SuccessNoopCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("account.%s.modules.module.%s.success.noop", id, module), registry) 523 mm.SuccessUpdateCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("account.%s.modules.module.%s.success.update", id, module), registry) 524 mm.SuccessRejectCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("account.%s.modules.module.%s.success.reject", id, module), registry) 525 mm.ExecutionErrorCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("account.%s.modules.module.%s.execution_error", id, module), registry) 526 mm.TimeoutCounter = metrics.GetOrRegisterCounter(fmt.Sprintf("account.%s.modules.module.%s.timeout", id, module), registry) 527 } 528 529 func makeDeliveryMetrics(registry metrics.Registry, prefix string, bidType openrtb_ext.BidType) *MarkupDeliveryMetrics { 530 return &MarkupDeliveryMetrics{ 531 AdmMeter: metrics.GetOrRegisterMeter(prefix+"."+string(bidType)+".adm_bids_received", registry), 532 NurlMeter: metrics.GetOrRegisterMeter(prefix+"."+string(bidType)+".nurl_bids_received", registry), 533 } 534 } 535 536 // getAccountMetrics gets or registers the account metrics for account "id". 537 // There is no getBlankAccountMetrics() as all metrics are generated dynamically. 538 func (me *Metrics) getAccountMetrics(id string) *accountMetrics { 539 var am *accountMetrics 540 var ok bool 541 542 me.accountMetricsRWMutex.RLock() 543 am, ok = me.accountMetrics[id] 544 me.accountMetricsRWMutex.RUnlock() 545 546 if ok { 547 return am 548 } 549 550 me.accountMetricsRWMutex.Lock() 551 // Made sure to use defer as we have two exit points: we want to unlock the mutex as quickly as possible. 552 defer me.accountMetricsRWMutex.Unlock() 553 554 am, ok = me.accountMetrics[id] 555 if ok { 556 // Unlock and return as quickly as possible 557 return am 558 } 559 am = &accountMetrics{} 560 am.requestMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.requests", id), me.MetricsRegistry) 561 am.debugRequestMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.debug_requests", id), me.MetricsRegistry) 562 am.bidsReceivedMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.bids_received", id), me.MetricsRegistry) 563 am.priceHistogram = metrics.GetOrRegisterHistogram(fmt.Sprintf("account.%s.prices", id), me.MetricsRegistry, metrics.NewExpDecaySample(1028, 0.015)) 564 am.adapterMetrics = make(map[openrtb_ext.BidderName]*AdapterMetrics, len(me.exchanges)) 565 am.moduleMetrics = make(map[string]*ModuleMetrics) 566 am.storedResponsesMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.stored_responses", id), me.MetricsRegistry) 567 if !me.MetricsDisabled.AccountAdapterDetails { 568 for _, a := range me.exchanges { 569 am.adapterMetrics[a] = makeBlankAdapterMetrics(me.MetricsDisabled) 570 registerAdapterMetrics(me.MetricsRegistry, fmt.Sprintf("account.%s", id), string(a), am.adapterMetrics[a]) 571 } 572 } 573 am.bidValidationCreativeSizeMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.response.validation.size.err", id), me.MetricsRegistry) 574 am.bidValidationCreativeSizeWarnMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.response.validation.size.warn", id), me.MetricsRegistry) 575 576 am.bidValidationSecureMarkupMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.response.validation.secure.err", id), me.MetricsRegistry) 577 am.bidValidationSecureMarkupWarnMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.response.validation.secure.warn", id), me.MetricsRegistry) 578 579 am.accountDeprecationWarningsPurpose1Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose1.warn", id), me.MetricsRegistry) 580 am.accountDeprecationWarningsPurpose2Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose2.warn", id), me.MetricsRegistry) 581 am.accountDeprecationWarningsPurpose3Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose3.warn", id), me.MetricsRegistry) 582 am.accountDeprecationWarningsPurpose4Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose4.warn", id), me.MetricsRegistry) 583 am.accountDeprecationWarningsPurpose5Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose5.warn", id), me.MetricsRegistry) 584 am.accountDeprecationWarningsPurpose6Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose6.warn", id), me.MetricsRegistry) 585 am.accountDeprecationWarningsPurpose7Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose7.warn", id), me.MetricsRegistry) 586 am.accountDeprecationWarningsPurpose8Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose8.warn", id), me.MetricsRegistry) 587 am.accountDeprecationWarningsPurpose9Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose9.warn", id), me.MetricsRegistry) 588 am.accountDeprecationWarningsPurpose10Meter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.purpose10.warn", id), me.MetricsRegistry) 589 am.channelEnabledCCPAMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.ccpa.channel_enabled.warn", id), me.MetricsRegistry) 590 am.channelEnabledGDPRMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.gdpr.channel_enabled.warn", id), me.MetricsRegistry) 591 am.accountDeprecationSummaryMeter = metrics.GetOrRegisterMeter(fmt.Sprintf("account.%s.config.summary", id), me.MetricsRegistry) 592 593 if !me.MetricsDisabled.AccountModulesMetrics { 594 for _, mod := range me.modules { 595 am.moduleMetrics[mod] = makeBlankModuleMetrics() 596 registerAccountModuleMetrics(me.MetricsRegistry, id, mod, am.moduleMetrics[mod]) 597 } 598 } 599 600 me.accountMetrics[id] = am 601 602 return am 603 } 604 605 // Implement the MetricsEngine interface 606 607 // RecordRequest implements a part of the MetricsEngine interface 608 func (me *Metrics) RecordRequest(labels Labels) { 609 me.RequestStatuses[labels.RType][labels.RequestStatus].Mark(1) 610 if labels.Source == DemandApp { 611 me.AppRequestMeter.Mark(1) 612 } else { 613 if labels.CookieFlag == CookieFlagNo { 614 // NOTE: Old behavior was log me.AMPNoCookieMeter here for AMP requests. 615 // AMP is still new and OpenRTB does not do this, so changing to match 616 // OpenRTB endpoint 617 me.NoCookieMeter.Mark(1) 618 } 619 } 620 621 // Handle the account metrics now. 622 am := me.getAccountMetrics(labels.PubID) 623 am.requestMeter.Mark(1) 624 } 625 626 func (me *Metrics) RecordDebugRequest(debugEnabled bool, pubID string) { 627 if debugEnabled { 628 me.DebugRequestMeter.Mark(1) 629 if pubID != PublisherUnknown { 630 am := me.getAccountMetrics(pubID) 631 if !me.MetricsDisabled.AccountDebug { 632 am.debugRequestMeter.Mark(1) 633 } 634 } 635 } 636 } 637 638 func (me *Metrics) RecordAccountGDPRPurposeWarning(account string, purposeName string) { 639 if account != PublisherUnknown { 640 am := me.getAccountMetrics(account) 641 switch purposeName { 642 case "purpose1": 643 am.accountDeprecationWarningsPurpose1Meter.Mark(1) 644 case "purpose2": 645 am.accountDeprecationWarningsPurpose2Meter.Mark(1) 646 case "purpose3": 647 am.accountDeprecationWarningsPurpose3Meter.Mark(1) 648 case "purpose4": 649 am.accountDeprecationWarningsPurpose4Meter.Mark(1) 650 case "purpose5": 651 am.accountDeprecationWarningsPurpose5Meter.Mark(1) 652 case "purpose6": 653 am.accountDeprecationWarningsPurpose6Meter.Mark(1) 654 case "purpose7": 655 am.accountDeprecationWarningsPurpose7Meter.Mark(1) 656 case "purpose8": 657 am.accountDeprecationWarningsPurpose8Meter.Mark(1) 658 case "purpose9": 659 am.accountDeprecationWarningsPurpose9Meter.Mark(1) 660 case "purpose10": 661 am.accountDeprecationWarningsPurpose10Meter.Mark(1) 662 } 663 } 664 } 665 666 func (me *Metrics) RecordAccountGDPRChannelEnabledWarning(account string) { 667 if account != PublisherUnknown { 668 am := me.getAccountMetrics(account) 669 am.channelEnabledGDPRMeter.Mark(1) 670 } 671 } 672 673 func (me *Metrics) RecordAccountCCPAChannelEnabledWarning(account string) { 674 if account != PublisherUnknown { 675 am := me.getAccountMetrics(account) 676 am.channelEnabledCCPAMeter.Mark(1) 677 } 678 } 679 680 func (me *Metrics) RecordAccountUpgradeStatus(account string) { 681 if account != PublisherUnknown { 682 am := me.getAccountMetrics(account) 683 am.accountDeprecationSummaryMeter.Mark(1) 684 } 685 } 686 687 func (me *Metrics) RecordStoredResponse(pubId string) { 688 me.StoredResponsesMeter.Mark(1) 689 if pubId != PublisherUnknown && !me.MetricsDisabled.AccountStoredResponses { 690 me.getAccountMetrics(pubId).storedResponsesMeter.Mark(1) 691 } 692 } 693 694 func (me *Metrics) RecordImps(labels ImpLabels) { 695 me.ImpMeter.Mark(int64(1)) 696 if labels.BannerImps { 697 me.ImpsTypeBanner.Mark(int64(1)) 698 } 699 if labels.VideoImps { 700 me.ImpsTypeVideo.Mark(int64(1)) 701 } 702 if labels.AudioImps { 703 me.ImpsTypeAudio.Mark(int64(1)) 704 } 705 if labels.NativeImps { 706 me.ImpsTypeNative.Mark(int64(1)) 707 } 708 } 709 710 func (me *Metrics) RecordConnectionAccept(success bool) { 711 if success { 712 me.ConnectionCounter.Inc(1) 713 } else { 714 me.ConnectionAcceptErrorMeter.Mark(1) 715 } 716 } 717 718 func (m *Metrics) RecordTMaxTimeout() { 719 m.TMaxTimeoutCounter.Inc(1) 720 } 721 722 func (me *Metrics) RecordConnectionClose(success bool) { 723 if success { 724 me.ConnectionCounter.Dec(1) 725 } else { 726 me.ConnectionCloseErrorMeter.Mark(1) 727 } 728 } 729 730 // RecordRequestTime implements a part of the MetricsEngine interface. The calling code is responsible 731 // for determining the call duration. 732 func (me *Metrics) RecordRequestTime(labels Labels, length time.Duration) { 733 // Only record times for successful requests, as we don't have labels to screen out bad requests. 734 if labels.RequestStatus == RequestStatusOK { 735 me.RequestTimer.Update(length) 736 } 737 } 738 739 // RecordStoredDataFetchTime implements a part of the MetricsEngine interface 740 func (me *Metrics) RecordStoredDataFetchTime(labels StoredDataLabels, length time.Duration) { 741 me.StoredDataFetchTimer[labels.DataType][labels.DataFetchType].Update(length) 742 } 743 744 // RecordStoredDataError implements a part of the MetricsEngine interface 745 func (me *Metrics) RecordStoredDataError(labels StoredDataLabels) { 746 me.StoredDataErrorMeter[labels.DataType][labels.Error].Mark(1) 747 } 748 749 // RecordAdapterPanic implements a part of the MetricsEngine interface 750 func (me *Metrics) RecordAdapterPanic(labels AdapterLabels) { 751 am, ok := me.AdapterMetrics[labels.Adapter] 752 if !ok { 753 glog.Errorf("Trying to run adapter metrics on %s: adapter metrics not found", string(labels.Adapter)) 754 return 755 } 756 am.PanicMeter.Mark(1) 757 } 758 759 // RecordAdapterRequest implements a part of the MetricsEngine interface 760 func (me *Metrics) RecordAdapterRequest(labels AdapterLabels) { 761 am, ok := me.AdapterMetrics[labels.Adapter] 762 if !ok { 763 glog.Errorf("Trying to run adapter metrics on %s: adapter metrics not found", string(labels.Adapter)) 764 return 765 } 766 767 aam, ok := me.getAccountMetrics(labels.PubID).adapterMetrics[labels.Adapter] 768 switch labels.AdapterBids { 769 case AdapterBidNone: 770 am.NoBidMeter.Mark(1) 771 if ok { 772 aam.NoBidMeter.Mark(1) 773 } 774 case AdapterBidPresent: 775 am.GotBidsMeter.Mark(1) 776 if ok { 777 aam.GotBidsMeter.Mark(1) 778 } 779 default: 780 glog.Warningf("No go-metrics logged for AdapterBids value: %s", labels.AdapterBids) 781 } 782 for errType := range labels.AdapterErrors { 783 am.ErrorMeters[errType].Mark(1) 784 } 785 786 if labels.CookieFlag == CookieFlagNo { 787 am.NoCookieMeter.Mark(1) 788 } 789 } 790 791 // Keeps track of created and reused connections to adapter bidders and the time from the 792 // connection request, to the connection creation, or reuse from the pool across all engines 793 func (me *Metrics) RecordAdapterConnections(adapterName openrtb_ext.BidderName, 794 connWasReused bool, 795 connWaitTime time.Duration) { 796 797 if me.MetricsDisabled.AdapterConnectionMetrics { 798 return 799 } 800 801 am, ok := me.AdapterMetrics[adapterName] 802 if !ok { 803 glog.Errorf("Trying to log adapter connection metrics for %s: adapter not found", string(adapterName)) 804 return 805 } 806 807 if connWasReused { 808 am.ConnReused.Inc(1) 809 } else { 810 am.ConnCreated.Inc(1) 811 } 812 am.ConnWaitTime.Update(connWaitTime) 813 } 814 815 func (me *Metrics) RecordDNSTime(dnsLookupTime time.Duration) { 816 me.DNSLookupTimer.Update(dnsLookupTime) 817 } 818 819 func (me *Metrics) RecordTLSHandshakeTime(tlsHandshakeTime time.Duration) { 820 me.TLSHandshakeTimer.Update(tlsHandshakeTime) 821 } 822 823 func (me *Metrics) RecordBidderServerResponseTime(bidderServerResponseTime time.Duration) { 824 me.BidderServerResponseTimer.Update(bidderServerResponseTime) 825 } 826 827 // RecordAdapterBidReceived implements a part of the MetricsEngine interface. 828 // This tracks how many bids from each Bidder use `adm` vs. `nurl. 829 func (me *Metrics) RecordAdapterBidReceived(labels AdapterLabels, bidType openrtb_ext.BidType, hasAdm bool) { 830 am, ok := me.AdapterMetrics[labels.Adapter] 831 if !ok { 832 glog.Errorf("Trying to run adapter bid metrics on %s: adapter metrics not found", string(labels.Adapter)) 833 return 834 } 835 836 // Adapter metrics 837 am.BidsReceivedMeter.Mark(1) 838 // Account-Adapter metrics 839 if aam, ok := me.getAccountMetrics(labels.PubID).adapterMetrics[labels.Adapter]; ok { 840 aam.BidsReceivedMeter.Mark(1) 841 } 842 843 if metricsForType, ok := am.MarkupMetrics[bidType]; ok { 844 if hasAdm { 845 metricsForType.AdmMeter.Mark(1) 846 } else { 847 metricsForType.NurlMeter.Mark(1) 848 } 849 } else { 850 glog.Errorf("bid/adm metrics map entry does not exist for type %s. This is a bug, and should be reported.", bidType) 851 } 852 } 853 854 // RecordAdapterPrice implements a part of the MetricsEngine interface. Generates a histogram of winning bid prices 855 func (me *Metrics) RecordAdapterPrice(labels AdapterLabels, cpm float64) { 856 am, ok := me.AdapterMetrics[labels.Adapter] 857 if !ok { 858 glog.Errorf("Trying to run adapter price metrics on %s: adapter metrics not found", string(labels.Adapter)) 859 return 860 } 861 // Adapter metrics 862 am.PriceHistogram.Update(int64(cpm)) 863 // Account-Adapter metrics 864 if aam, ok := me.getAccountMetrics(labels.PubID).adapterMetrics[labels.Adapter]; ok { 865 aam.PriceHistogram.Update(int64(cpm)) 866 } 867 } 868 869 // RecordAdapterTime implements a part of the MetricsEngine interface. Records the adapter response time 870 func (me *Metrics) RecordAdapterTime(labels AdapterLabels, length time.Duration) { 871 am, ok := me.AdapterMetrics[labels.Adapter] 872 if !ok { 873 glog.Errorf("Trying to run adapter latency metrics on %s: adapter metrics not found", string(labels.Adapter)) 874 return 875 } 876 // Adapter metrics 877 am.RequestTimer.Update(length) 878 // Account-Adapter metrics 879 if aam, ok := me.getAccountMetrics(labels.PubID).adapterMetrics[labels.Adapter]; ok { 880 aam.RequestTimer.Update(length) 881 } 882 } 883 884 // RecordOverheadTime implements a part of the MetricsEngine interface. Records the adapter overhead time 885 func (me *Metrics) RecordOverheadTime(overhead OverheadType, length time.Duration) { 886 me.OverheadTimer[overhead].Update(length) 887 } 888 889 // RecordCookieSync implements a part of the MetricsEngine interface. Records a cookie sync request 890 func (me *Metrics) RecordCookieSync(status CookieSyncStatus) { 891 me.CookieSyncMeter.Mark(1) 892 if meter, exists := me.CookieSyncStatusMeter[status]; exists { 893 meter.Mark(1) 894 } 895 } 896 897 // RecordSyncerRequest implements a part of the MetricsEngine interface. Records a cookie sync syncer request and status 898 func (me *Metrics) RecordSyncerRequest(key string, status SyncerCookieSyncStatus) { 899 if keyMeter, exists := me.SyncerRequestsMeter[key]; exists { 900 if statusMeter, exists := keyMeter[status]; exists { 901 statusMeter.Mark(1) 902 } 903 } 904 } 905 906 // RecordSetUid implements a part of the MetricsEngine interface. Records a set uid sync request 907 func (me *Metrics) RecordSetUid(status SetUidStatus) { 908 me.SetUidMeter.Mark(1) 909 if meter, exists := me.SetUidStatusMeter[status]; exists { 910 meter.Mark(1) 911 } 912 } 913 914 // RecordSyncerSet implements a part of the MetricsEngine interface. Records a set uid sync request and status 915 func (me *Metrics) RecordSyncerSet(key string, status SyncerSetUidStatus) { 916 if keyMeter, exists := me.SyncerSetsMeter[key]; exists { 917 if statusMeter, exists := keyMeter[status]; exists { 918 statusMeter.Mark(1) 919 } 920 } 921 } 922 923 // RecordStoredReqCacheResult implements a part of the MetricsEngine interface. Records the 924 // cache hits and misses when looking up stored requests 925 func (me *Metrics) RecordStoredReqCacheResult(cacheResult CacheResult, inc int) { 926 me.StoredReqCacheMeter[cacheResult].Mark(int64(inc)) 927 } 928 929 // RecordStoredImpCacheResult implements a part of the MetricsEngine interface. Records the 930 // cache hits and misses when looking up stored impressions. 931 func (me *Metrics) RecordStoredImpCacheResult(cacheResult CacheResult, inc int) { 932 me.StoredImpCacheMeter[cacheResult].Mark(int64(inc)) 933 } 934 935 // RecordAccountCacheResult implements a part of the MetricsEngine interface. Records the 936 // cache hits and misses when looking up accounts. 937 func (me *Metrics) RecordAccountCacheResult(cacheResult CacheResult, inc int) { 938 me.AccountCacheMeter[cacheResult].Mark(int64(inc)) 939 } 940 941 // RecordPrebidCacheRequestTime implements a part of the MetricsEngine interface. Records the 942 // amount of time taken to store the auction result in Prebid Cache. 943 func (me *Metrics) RecordPrebidCacheRequestTime(success bool, length time.Duration) { 944 if success { 945 me.PrebidCacheRequestTimerSuccess.Update(length) 946 } else { 947 me.PrebidCacheRequestTimerError.Update(length) 948 } 949 } 950 951 func (me *Metrics) RecordRequestQueueTime(success bool, requestType RequestType, length time.Duration) { 952 if requestType == ReqTypeVideo { //remove this check when other request types are supported 953 me.RequestsQueueTimer[requestType][success].Update(length) 954 } 955 956 } 957 958 func (me *Metrics) RecordTimeoutNotice(success bool) { 959 if success { 960 me.TimeoutNotificationSuccess.Mark(1) 961 } else { 962 me.TimeoutNotificationFailure.Mark(1) 963 } 964 } 965 966 func (me *Metrics) RecordRequestPrivacy(privacy PrivacyLabels) { 967 if privacy.CCPAProvided { 968 me.PrivacyCCPARequest.Mark(1) 969 if privacy.CCPAEnforced { 970 me.PrivacyCCPARequestOptOut.Mark(1) 971 } 972 } 973 974 if privacy.COPPAEnforced { 975 me.PrivacyCOPPARequest.Mark(1) 976 } 977 978 if privacy.GDPREnforced { 979 if metric, ok := me.PrivacyTCFRequestVersion[privacy.GDPRTCFVersion]; ok { 980 metric.Mark(1) 981 } else { 982 me.PrivacyTCFRequestVersion[TCFVersionErr].Mark(1) 983 } 984 } 985 986 if privacy.LMTEnforced { 987 me.PrivacyLMTRequest.Mark(1) 988 } 989 } 990 991 func (me *Metrics) RecordAdapterGDPRRequestBlocked(adapterName openrtb_ext.BidderName) { 992 if me.MetricsDisabled.AdapterGDPRRequestBlocked { 993 return 994 } 995 996 am, ok := me.AdapterMetrics[adapterName] 997 if !ok { 998 glog.Errorf("Trying to log adapter GDPR request blocked metric for %s: adapter not found", string(adapterName)) 999 return 1000 } 1001 1002 am.GDPRRequestBlocked.Mark(1) 1003 } 1004 1005 func (me *Metrics) RecordAdsCertReq(success bool) { 1006 if success { 1007 me.AdsCertRequestsSuccess.Mark(1) 1008 } else { 1009 me.AdsCertRequestsFailure.Mark(1) 1010 } 1011 } 1012 1013 func (me *Metrics) RecordAdsCertSignTime(adsCertSignTime time.Duration) { 1014 me.adsCertSignTimer.Update(adsCertSignTime) 1015 } 1016 1017 func (me *Metrics) RecordBidValidationCreativeSizeError(adapter openrtb_ext.BidderName, pubID string) { 1018 am, ok := me.AdapterMetrics[adapter] 1019 if !ok { 1020 glog.Errorf("Trying to run adapter metrics on %s: adapter metrics not found", string(adapter)) 1021 return 1022 } 1023 am.BidValidationCreativeSizeErrorMeter.Mark(1) 1024 1025 aam := me.getAccountMetrics(pubID) 1026 if !me.MetricsDisabled.AccountAdapterDetails { 1027 aam.bidValidationCreativeSizeMeter.Mark(1) 1028 } 1029 } 1030 1031 func (me *Metrics) RecordBidValidationCreativeSizeWarn(adapter openrtb_ext.BidderName, pubID string) { 1032 am, ok := me.AdapterMetrics[adapter] 1033 if !ok { 1034 glog.Errorf("Trying to run adapter metrics on %s: adapter metrics not found", string(adapter)) 1035 return 1036 } 1037 am.BidValidationCreativeSizeWarnMeter.Mark(1) 1038 1039 aam := me.getAccountMetrics(pubID) 1040 if !me.MetricsDisabled.AccountAdapterDetails { 1041 aam.bidValidationCreativeSizeWarnMeter.Mark(1) 1042 } 1043 } 1044 1045 func (me *Metrics) RecordBidValidationSecureMarkupError(adapter openrtb_ext.BidderName, pubID string) { 1046 am, ok := me.AdapterMetrics[adapter] 1047 if !ok { 1048 glog.Errorf("Trying to run adapter metrics on %s: adapter metrics not found", string(adapter)) 1049 return 1050 } 1051 am.BidValidationSecureMarkupErrorMeter.Mark(1) 1052 1053 aam := me.getAccountMetrics(pubID) 1054 if !me.MetricsDisabled.AccountAdapterDetails { 1055 aam.bidValidationSecureMarkupMeter.Mark(1) 1056 } 1057 } 1058 1059 func (me *Metrics) RecordBidValidationSecureMarkupWarn(adapter openrtb_ext.BidderName, pubID string) { 1060 am, ok := me.AdapterMetrics[adapter] 1061 if !ok { 1062 glog.Errorf("Trying to run adapter metrics on %s: adapter metrics not found", string(adapter)) 1063 return 1064 } 1065 am.BidValidationSecureMarkupWarnMeter.Mark(1) 1066 1067 aam := me.getAccountMetrics(pubID) 1068 if !me.MetricsDisabled.AccountAdapterDetails { 1069 aam.bidValidationSecureMarkupWarnMeter.Mark(1) 1070 } 1071 } 1072 1073 func (me *Metrics) RecordModuleCalled(labels ModuleLabels, duration time.Duration) { 1074 mm, err := me.getModuleMetric(labels) 1075 if err != nil { 1076 return 1077 } 1078 1079 // Module metrics 1080 mm.CallCounter.Inc(1) 1081 mm.DurationTimer.Update(duration) 1082 1083 // Account-Module metrics 1084 if labels.AccountID != "" && labels.AccountID != PublisherUnknown { 1085 if aam, ok := me.getAccountMetrics(labels.AccountID).moduleMetrics[labels.Module]; ok { 1086 aam.CallCounter.Inc(1) 1087 aam.DurationTimer.Update(duration) 1088 } 1089 } 1090 } 1091 1092 func (me *Metrics) RecordModuleFailed(labels ModuleLabels) { 1093 mm, err := me.getModuleMetric(labels) 1094 if err != nil { 1095 return 1096 } 1097 1098 // Module metrics 1099 mm.FailureCounter.Inc(1) 1100 1101 // Account-Module metrics 1102 if labels.AccountID != "" && labels.AccountID != PublisherUnknown { 1103 if aam, ok := me.getAccountMetrics(labels.AccountID).moduleMetrics[labels.Module]; ok { 1104 aam.FailureCounter.Inc(1) 1105 } 1106 } 1107 } 1108 1109 func (me *Metrics) RecordModuleSuccessNooped(labels ModuleLabels) { 1110 mm, err := me.getModuleMetric(labels) 1111 if err != nil { 1112 return 1113 } 1114 1115 // Module metrics 1116 mm.SuccessNoopCounter.Inc(1) 1117 1118 // Account-Module metrics 1119 if labels.AccountID != "" && labels.AccountID != PublisherUnknown { 1120 if aam, ok := me.getAccountMetrics(labels.AccountID).moduleMetrics[labels.Module]; ok { 1121 aam.SuccessNoopCounter.Inc(1) 1122 } 1123 } 1124 } 1125 1126 func (me *Metrics) RecordModuleSuccessUpdated(labels ModuleLabels) { 1127 mm, err := me.getModuleMetric(labels) 1128 if err != nil { 1129 return 1130 } 1131 1132 // Module metrics 1133 mm.SuccessUpdateCounter.Inc(1) 1134 1135 // Account-Module metrics 1136 if labels.AccountID != "" && labels.AccountID != PublisherUnknown { 1137 if aam, ok := me.getAccountMetrics(labels.AccountID).moduleMetrics[labels.Module]; ok { 1138 aam.SuccessUpdateCounter.Inc(1) 1139 } 1140 } 1141 } 1142 1143 func (me *Metrics) RecordModuleSuccessRejected(labels ModuleLabels) { 1144 mm, err := me.getModuleMetric(labels) 1145 if err != nil { 1146 return 1147 } 1148 1149 // Module metrics 1150 mm.SuccessRejectCounter.Inc(1) 1151 1152 // Account-Module metrics 1153 if labels.AccountID != "" && labels.AccountID != PublisherUnknown { 1154 if aam, ok := me.getAccountMetrics(labels.AccountID).moduleMetrics[labels.Module]; ok { 1155 aam.SuccessRejectCounter.Inc(1) 1156 } 1157 } 1158 } 1159 1160 func (me *Metrics) RecordModuleExecutionError(labels ModuleLabels) { 1161 mm, err := me.getModuleMetric(labels) 1162 if err != nil { 1163 return 1164 } 1165 1166 // Module metrics 1167 mm.ExecutionErrorCounter.Inc(1) 1168 1169 // Account-Module metrics 1170 if labels.AccountID != "" && labels.AccountID != PublisherUnknown { 1171 if aam, ok := me.getAccountMetrics(labels.AccountID).moduleMetrics[labels.Module]; ok { 1172 aam.ExecutionErrorCounter.Inc(1) 1173 } 1174 } 1175 } 1176 1177 func (me *Metrics) RecordModuleTimeout(labels ModuleLabels) { 1178 mm, err := me.getModuleMetric(labels) 1179 if err != nil { 1180 return 1181 } 1182 1183 // Module metrics 1184 mm.TimeoutCounter.Inc(1) 1185 1186 // Account-Module metrics 1187 if labels.AccountID != "" && labels.AccountID != PublisherUnknown { 1188 if aam, ok := me.getAccountMetrics(labels.AccountID).moduleMetrics[labels.Module]; ok { 1189 aam.TimeoutCounter.Inc(1) 1190 } 1191 } 1192 } 1193 1194 func (me *Metrics) getModuleMetric(labels ModuleLabels) (*ModuleMetrics, error) { 1195 mm, ok := me.ModuleMetrics[labels.Module][labels.Stage] 1196 if !ok { 1197 err := fmt.Errorf("Trying to run module %s metrics for stage %s: module metrics not found", labels.Module, labels.Stage) 1198 glog.Errorf(err.Error()) 1199 return nil, err 1200 } 1201 1202 return mm, nil 1203 }