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  }