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