diff --git a/analytics/pubmatic/logger.go b/analytics/pubmatic/logger.go index 3e7c6ecb095..8aadd699e50 100644 --- a/analytics/pubmatic/logger.go +++ b/analytics/pubmatic/logger.go @@ -13,11 +13,7 @@ import ( "github.com/prebid/prebid-server/openrtb_ext" ) -func GetLogAuctionObjectAsURL(ao analytics.AuctionObject, logInfo, forRespExt bool) (string, http.Header) { - rCtx := GetRequestCtx(ao.HookExecutionOutcome) - if rCtx == nil { - return "", http.Header{} - } +func GetLogAuctionObjectAsURL(ao analytics.AuctionObject, rCtx *models.RequestCtx, logInfo, forRespExt bool) (string, http.Header) { wlog := WloggerRecord{ record: record{ diff --git a/analytics/pubmatic/pubmatic.go b/analytics/pubmatic/pubmatic.go index a59f6ed8804..0f5854ec20f 100644 --- a/analytics/pubmatic/pubmatic.go +++ b/analytics/pubmatic/pubmatic.go @@ -38,9 +38,23 @@ func (ow HTTPLogger) LogAuctionObject(ao *analytics.AuctionObject) { } }() - url, headers := GetLogAuctionObjectAsURL(*ao, false, false) + rCtx := GetRequestCtx(ao.HookExecutionOutcome) + if rCtx == nil { + // glog.Errorf("Failed to get the request context for AuctionObject - [%v]", ao) + // add this log once complete header-bidding code is migrated to modules + return + } + + var err error + url, headers := GetLogAuctionObjectAsURL(*ao, rCtx, false, false) if url != "" { - Send(url, headers) + err = Send(url, headers) + } + + // record the logger failure + if url == "" || err != nil { + glog.Errorf("Failed to send the owlogger for pub:[%d], profile:[%d], version:[%d].", + rCtx.PubID, rCtx.ProfileID, rCtx.VersionID) } } diff --git a/endpoints/openrtb2/auction_ow.go b/endpoints/openrtb2/auction_ow.go index 74009fab5db..108655f268c 100644 --- a/endpoints/openrtb2/auction_ow.go +++ b/endpoints/openrtb2/auction_ow.go @@ -61,7 +61,7 @@ func UpdateResponseExtOW(bidResponse *openrtb2.BidResponse, ao analytics.Auction } if rCtx.LogInfoFlag == 1 { - extBidResponse.OwLogInfo.Logger, _ = pubmatic.GetLogAuctionObjectAsURL(ao, true, true) + extBidResponse.OwLogInfo.Logger, _ = pubmatic.GetLogAuctionObjectAsURL(ao, rCtx, true, true) } // TODO: uncomment after seatnonbid PR is merged https://github.com/prebid/prebid-server/pull/2505 @@ -73,7 +73,7 @@ func UpdateResponseExtOW(bidResponse *openrtb2.BidResponse, ao analytics.Auction // } if rCtx.Debug { - extBidResponse.OwLogger, _ = pubmatic.GetLogAuctionObjectAsURL(ao, false, true) + extBidResponse.OwLogger, _ = pubmatic.GetLogAuctionObjectAsURL(ao, rCtx, false, true) } bidResponse.Ext, _ = json.Marshal(extBidResponse) diff --git a/go.mod b/go.mod index 7bc67c28bbb..c5b8c3d1981 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,7 @@ require ( github.com/go-sql-driver/mysql v1.7.0 github.com/satori/go.uuid v1.2.0 github.com/golang/mock v1.6.0 + github.com/satori/go.uuid v1.2.0 ) require ( diff --git a/modules/pubmatic/openwrap/adunitconfig/banner.go b/modules/pubmatic/openwrap/adunitconfig/banner.go index fef365120ff..bd3e2d64294 100644 --- a/modules/pubmatic/openwrap/adunitconfig/banner.go +++ b/modules/pubmatic/openwrap/adunitconfig/banner.go @@ -25,6 +25,7 @@ func UpdateBannerObjectWithAdunitConfig(rCtx models.RequestCtx, imp openrtb2.Imp if defaultAdUnitConfig.Banner != nil && defaultAdUnitConfig.Banner.Enabled != nil && !*defaultAdUnitConfig.Banner.Enabled { f := false adUnitCtx.AppliedSlotAdUnitConfig = &adunitconfig.AdConfig{Banner: &adunitconfig.Banner{Enabled: &f}} + rCtx.MetricsEngine.RecordImpDisabledViaConfigStats(models.ImpTypeBanner, rCtx.PubIDStr, rCtx.ProfileIDStr) return } } @@ -44,6 +45,7 @@ func UpdateBannerObjectWithAdunitConfig(rCtx models.RequestCtx, imp openrtb2.Imp if adUnitCtx.SelectedSlotAdUnitConfig.Banner.Enabled != nil && !*adUnitCtx.SelectedSlotAdUnitConfig.Banner.Enabled { f := false adUnitCtx.AppliedSlotAdUnitConfig = &adunitconfig.AdConfig{Banner: &adunitconfig.Banner{Enabled: &f}} + rCtx.MetricsEngine.RecordImpDisabledViaConfigStats(models.ImpTypeBanner, rCtx.PubIDStr, rCtx.ProfileIDStr) return } } diff --git a/modules/pubmatic/openwrap/adunitconfig/video.go b/modules/pubmatic/openwrap/adunitconfig/video.go index c9fcc49f868..21e59cf522a 100644 --- a/modules/pubmatic/openwrap/adunitconfig/video.go +++ b/modules/pubmatic/openwrap/adunitconfig/video.go @@ -28,6 +28,7 @@ func UpdateVideoObjectWithAdunitConfig(rCtx models.RequestCtx, imp openrtb2.Imp, if defaultAdUnitConfig.Video != nil && defaultAdUnitConfig.Video.Enabled != nil && !*defaultAdUnitConfig.Video.Enabled { f := false adUnitCtx.AppliedSlotAdUnitConfig = &adunitconfig.AdConfig{Video: &adunitconfig.Video{Enabled: &f}} + rCtx.MetricsEngine.RecordImpDisabledViaConfigStats(models.ImpTypeVideo, rCtx.PubIDStr, rCtx.ProfileIDStr) return } } @@ -44,6 +45,7 @@ func UpdateVideoObjectWithAdunitConfig(rCtx models.RequestCtx, imp openrtb2.Imp, if adUnitCtx.SelectedSlotAdUnitConfig.Video.Enabled != nil && !*adUnitCtx.SelectedSlotAdUnitConfig.Video.Enabled { f := false adUnitCtx.AppliedSlotAdUnitConfig = &adunitconfig.AdConfig{Video: &adunitconfig.Video{Enabled: &f}} + rCtx.MetricsEngine.RecordImpDisabledViaConfigStats(models.ImpTypeVideo, rCtx.PubIDStr, rCtx.ProfileIDStr) return } } @@ -71,6 +73,7 @@ func UpdateVideoObjectWithAdunitConfig(rCtx models.RequestCtx, imp openrtb2.Imp, // if allowedConnectionTypes != nil && !checkValuePresentInArray(allowedConnectionTypes, int(*connectionType)) { // f := false // adUnitCtx.AppliedSlotAdUnitConfig = &adunitconfig.AdConfig{Video: &adunitconfig.Video{Enabled: &f}} + // rCtx.MetricsEngine.RecordVideoImpDisabledViaConnTypeStats(rCtx.PubIDStr,rCtx.ProfIDStr) // return // } // } diff --git a/modules/pubmatic/openwrap/auctionresponsehook.go b/modules/pubmatic/openwrap/auctionresponsehook.go index 59f1f37ee7d..58dc892e396 100644 --- a/modules/pubmatic/openwrap/auctionresponsehook.go +++ b/modules/pubmatic/openwrap/auctionresponsehook.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "strconv" + "time" "github.com/prebid/openrtb/v19/openrtb2" "github.com/prebid/prebid-server/hooks/hookanalytics" @@ -34,8 +35,11 @@ func (m OpenWrap) handleAuctionResponseHook( } defer func() { moduleCtx.ModuleContext["rctx"] = rctx + m.metricEngine.RecordPublisherResponseTimeStats(rctx.PubIDStr, int(time.Since(time.Unix(rctx.StartTime, 0)).Milliseconds())) }() + RecordPublisherPartnerNoCookieStats(rctx) + // cache rctx for analytics result.AnalyticsTags = hookanalytics.Analytics{ Activities: []hookanalytics.Activity{ @@ -59,12 +63,14 @@ func (m OpenWrap) handleAuctionResponseHook( winningBids := make(map[string]models.OwBid, 0) for _, seatBid := range payload.BidResponse.SeatBid { for _, bid := range seatBid.Bid { + + m.metricEngine.RecordPlatformPublisherPartnerResponseStats(rctx.Platform, rctx.PubIDStr, seatBid.Seat) + impCtx, ok := rctx.ImpBidCtx[bid.ImpID] if !ok { result.Errors = append(result.Errors, "invalid impCtx.ID for bid"+bid.ImpID) continue } - partnerID := 0 if bidderMeta, ok := impCtx.Bidders[seatBid.Seat]; ok { partnerID = bidderMeta.PartnerID @@ -169,6 +175,9 @@ func (m OpenWrap) handleAuctionResponseHook( } rctx.WinningBids = winningBids + if len(winningBids) == 0 { + m.metricEngine.RecordNobidErrPrebidServerResponse(rctx.PubIDStr) + } droppedBids, warnings := addPWTTargetingForBid(rctx, payload.BidResponse) if len(droppedBids) != 0 { @@ -178,10 +187,6 @@ func (m OpenWrap) handleAuctionResponseHook( result.Warnings = append(result.Warnings, warnings...) } - rctx.NoSeatBids = m.addDefaultBids(rctx, payload.BidResponse) - - rctx.Trackers = tracker.CreateTrackers(rctx, payload.BidResponse) - responseExt := openrtb_ext.ExtBidResponse{} // TODO use concrete structure if len(payload.BidResponse.Ext) != 0 { @@ -190,8 +195,13 @@ func (m OpenWrap) handleAuctionResponseHook( } } - for k, v := range responseExt.ResponseTimeMillis { - rctx.BidderResponseTimeMillis[k.String()] = v + rctx.NoSeatBids = m.addDefaultBids(rctx, payload.BidResponse, &responseExt) + + rctx.Trackers = tracker.CreateTrackers(rctx, payload.BidResponse) + + for bidder, responseTimeMs := range responseExt.ResponseTimeMillis { + rctx.BidderResponseTimeMillis[bidder.String()] = responseTimeMs + m.metricEngine.RecordPartnerResponseTimeStats(rctx.PubIDStr, string(bidder), responseTimeMs) } // TODO: PBS-Core should pass the hostcookie for module to usersync.ParseCookieFromRequest() diff --git a/modules/pubmatic/openwrap/beforevalidationhook.go b/modules/pubmatic/openwrap/beforevalidationhook.go index aaaef592512..5cad5e67657 100644 --- a/modules/pubmatic/openwrap/beforevalidationhook.go +++ b/modules/pubmatic/openwrap/beforevalidationhook.go @@ -39,6 +39,10 @@ func (m OpenWrap) handleBeforeValidationHook( } defer func() { moduleCtx.ModuleContext["rctx"] = rCtx + if len(result.Errors) > 0 { + m.metricEngine.RecordBadRequests(rCtx.Endpoint, getPubmaticErrorCode(result.NbrCode)) + + } }() pubID, err := getPubID(*payload.BidRequest) @@ -48,6 +52,12 @@ func (m OpenWrap) handleBeforeValidationHook( return result, fmt.Errorf("invalid publisher id : %v", err) } rCtx.PubID = pubID + rCtx.PubIDStr = strconv.Itoa(pubID) + + if rCtx.UidCookie == nil { + m.metricEngine.RecordUidsCookieNotPresentErrorStats(rCtx.PubIDStr, rCtx.ProfileIDStr) + } + m.metricEngine.RecordPublisherProfileRequests(rCtx.PubIDStr, rCtx.ProfileIDStr) requestExt, err := models.GetRequestExt(payload.BidRequest.Ext) if err != nil { @@ -68,17 +78,30 @@ func (m OpenWrap) handleBeforeValidationHook( result.NbrCode = nbr.InvalidProfileConfiguration err = errors.New("failed to get profile data: " + err.Error()) result.Errors = append(result.Errors, err.Error()) + m.metricEngine.RecordPublisherInvalidProfileRequests(rCtx.Endpoint, rCtx.PubIDStr, rCtx.ProfileIDStr) + m.metricEngine.RecordPublisherInvalidProfileImpressions(rCtx.PubIDStr, rCtx.ProfileIDStr, len(payload.BidRequest.Imp)) return result, err } rCtx.PartnerConfigMap = partnerConfigMap // keep a copy at module level as well rCtx.Platform, _ = rCtx.GetVersionLevelKey(models.PLATFORM_KEY) + if rCtx.Platform == "" { + result.NbrCode = nbr.InvalidPlatform + err = errors.New("failed to get platform data") + result.Errors = append(result.Errors, err.Error()) + m.metricEngine.RecordPublisherInvalidProfileRequests(rCtx.Endpoint, rCtx.PubIDStr, rCtx.ProfileIDStr) + m.metricEngine.RecordPublisherInvalidProfileImpressions(rCtx.PubIDStr, rCtx.ProfileIDStr, len(payload.BidRequest.Imp)) + return result, err + } + rCtx.PageURL = getPageURL(payload.BidRequest) rCtx.DevicePlatform = GetDevicePlatform(rCtx.UA, payload.BidRequest, rCtx.Platform) rCtx.SendAllBids = isSendAllBids(rCtx) rCtx.Source, rCtx.Origin = getSourceAndOrigin(payload.BidRequest) rCtx.TMax = m.setTimeout(rCtx) + m.metricEngine.RecordPublisherRequests(rCtx.Endpoint, rCtx.PubIDStr, rCtx.Platform) + if newPartnerConfigMap, ok := ABTestProcessing(rCtx); ok { rCtx.ABTestConfigApplied = 1 rCtx.PartnerConfigMap = newPartnerConfigMap @@ -91,6 +114,7 @@ func (m OpenWrap) handleBeforeValidationHook( result.NbrCode = nbr.AllPartnerThrottled result.Errors = append(result.Errors, "All adapters throttled") rCtx.ImpBidCtx = getDefaultImpBidCtx(*payload.BidRequest) // for wrapper logger sz + m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr) return result, err } @@ -100,6 +124,7 @@ func (m OpenWrap) handleBeforeValidationHook( err = errors.New("failed to price granularity details: " + err.Error()) result.Errors = append(result.Errors, err.Error()) rCtx.ImpBidCtx = getDefaultImpBidCtx(*payload.BidRequest) // for wrapper logger sz + m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr) return result, err } @@ -126,12 +151,19 @@ func (m OpenWrap) handleBeforeValidationHook( result.NbrCode = nbr.InvalidImpressionTagID err = errors.New("tagid missing for imp: " + imp.ID) result.Errors = append(result.Errors, err.Error()) + m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr) return result, err } - if len(requestExt.Prebid.Macros) == 0 && imp.Video != nil { - // provide custom macros for video event trackers - requestExt.Prebid.Macros = getVASTEventMacros(rCtx) + if imp.Video != nil { + //add stats for video instl impressions + if imp.Instl == 1 { + m.metricEngine.RecordVideoInstlImpsStats(rCtx.PubIDStr, rCtx.ProfileIDStr) + } + if len(requestExt.Prebid.Macros) == 0 { + // provide custom macros for video event trackers + requestExt.Prebid.Macros = getVASTEventMacros(rCtx) + } } impExt := &models.ImpExtension{} @@ -141,6 +173,7 @@ func (m OpenWrap) handleBeforeValidationHook( result.NbrCode = nbr.InternalError err = errors.New("failed to parse imp.ext: " + imp.ID) result.Errors = append(result.Errors, err.Error()) + m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr) return result, err } } @@ -154,6 +187,15 @@ func (m OpenWrap) handleBeforeValidationHook( var videoAdUnitCtx, bannerAdUnitCtx models.AdUnitCtx if rCtx.AdUnitConfig != nil { + // Currently we are supporting Video config via Ad Unit config file for in-app / video / display profiles + if (rCtx.Platform == models.PLATFORM_APP || rCtx.Platform == models.PLATFORM_VIDEO || rCtx.Platform == models.PLATFORM_DISPLAY) && imp.Video != nil { + if payload.BidRequest.App != nil && payload.BidRequest.App.Content != nil { + m.metricEngine.RecordReqImpsWithAppContentCount(rCtx.PubIDStr) + } + if payload.BidRequest.Site != nil && payload.BidRequest.Site.Content != nil { + m.metricEngine.RecordReqImpsWithSiteContentCount(rCtx.PubIDStr) + } + } videoAdUnitCtx = adunitconfig.UpdateVideoObjectWithAdunitConfig(rCtx, imp, div, payload.BidRequest.Device.ConnectionType) bannerAdUnitCtx = adunitconfig.UpdateBannerObjectWithAdunitConfig(rCtx, imp, div) } @@ -215,9 +257,12 @@ func (m OpenWrap) handleBeforeValidationHook( if err != nil || len(bidderParams) == 0 { result.Errors = append(result.Errors, fmt.Sprintf("no bidder params found for imp:%s partner: %s", imp.ID, prebidBidderCode)) nonMapped[bidderCode] = struct{}{} + m.metricEngine.RecordSlotNotMappedErrorStats(rCtx.PubIDStr, bidderCode) continue } + m.metricEngine.RecordPlatformPublisherPartnerReqStats(rCtx.Platform, rCtx.PubIDStr, bidderCode) + bidderMeta[bidderCode] = models.PartnerData{ PartnerID: partnerID, PrebidBidderCode: prebidBidderCode, @@ -295,6 +340,7 @@ func (m OpenWrap) handleBeforeValidationHook( result.NbrCode = nbr.AllSlotsDisabled err = errors.New("All slots disabled: " + err.Error()) result.Errors = append(result.Errors, err.Error()) + m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr) return result, nil } @@ -302,6 +348,7 @@ func (m OpenWrap) handleBeforeValidationHook( result.NbrCode = nbr.ServerSidePartnerNotConfigured err = errors.New("server side partner not found: " + err.Error()) result.Errors = append(result.Errors, err.Error()) + m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr) return result, nil } diff --git a/modules/pubmatic/openwrap/bidderparams/pubmatic.go b/modules/pubmatic/openwrap/bidderparams/pubmatic.go index f19a1ea92fa..8ac3d0773a4 100644 --- a/modules/pubmatic/openwrap/bidderparams/pubmatic.go +++ b/modules/pubmatic/openwrap/bidderparams/pubmatic.go @@ -88,6 +88,8 @@ func PreparePubMaticParamsV25(rctx models.RequestCtx, cache cache.Cache, bidRequ extImpPubMatic.AdSlot = GenerateSlotName(0, 0, unmappedKPG, imp.TagID, div, rctx.Source) if len(slots) != 0 { // reuse this field for wt and wl in combination with isRegex matchedPattern = slots[0] + } else { + rctx.MetricsEngine.RecordMisConfigurationErrorStats(rctx.PubIDStr, string(openrtb_ext.BidderPubmatic)) } } diff --git a/modules/pubmatic/openwrap/config/config.go b/modules/pubmatic/openwrap/config/config.go index c2f0082db71..0d7cf85540a 100755 --- a/modules/pubmatic/openwrap/config/config.go +++ b/modules/pubmatic/openwrap/config/config.go @@ -1,6 +1,10 @@ package config -import "time" +import ( + "time" + + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/stats" +) // Config contains the values read from the config file at boot time type Config struct { @@ -12,10 +16,12 @@ type Config struct { PixelView PixelView Features FeatureToggle Log Log + Stats stats.Stats } type Server struct { HostName string + DCName string //Name of the data center } type Database struct { diff --git a/modules/pubmatic/openwrap/defaultbids.go b/modules/pubmatic/openwrap/defaultbids.go index 792314abd90..510e9a3225a 100644 --- a/modules/pubmatic/openwrap/defaultbids.go +++ b/modules/pubmatic/openwrap/defaultbids.go @@ -5,11 +5,13 @@ import ( "strconv" "github.com/prebid/openrtb/v19/openrtb2" + "github.com/prebid/prebid-server/errortypes" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/adunitconfig" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/prebid/prebid-server/openrtb_ext" ) -func (m *OpenWrap) addDefaultBids(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) map[string]map[string][]openrtb2.Bid { +func (m *OpenWrap) addDefaultBids(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse, bidResponseExt *openrtb_ext.ExtBidResponse) map[string]map[string][]openrtb2.Bid { // responded bidders per impression seatBids := make(map[string]map[string]struct{}, len(bidResponse.SeatBid)) for _, seatBid := range bidResponse.SeatBid { @@ -54,6 +56,9 @@ func (m *OpenWrap) addDefaultBids(rctx models.RequestCtx, bidResponse *openrtb2. ImpID: impID, Ext: newNoBidExt(rctx, impID), }) + + // record error stats for each bidder + m.recordErrorStats(rctx, bidResponseExt, bidder) } } } @@ -154,3 +159,19 @@ func (m *OpenWrap) applyDefaultBids(rctx models.RequestCtx, bidResponse *openrtb return bidResponse, nil } + +func (m *OpenWrap) recordErrorStats(rctx models.RequestCtx, bidResponseExt *openrtb_ext.ExtBidResponse, bidder string) { + bidderErr, ok := bidResponseExt.Errors[openrtb_ext.BidderName(bidder)] + if ok && len(bidderErr) > 0 { + switch bidderErr[0].Code { + case errortypes.TimeoutErrorCode: + m.metricEngine.RecordPartnerTimeoutErrorStats(rctx.PubIDStr, bidder) + case errortypes.UnknownErrorCode: + m.metricEngine.RecordUnkownPrebidErrorStats(rctx.PubIDStr, bidder) + default: + m.metricEngine.RecordNobidErrorStats(rctx.PubIDStr, bidder) + } + } else { + m.metricEngine.RecordNobidErrorStats(rctx.PubIDStr, bidder) + } +} diff --git a/modules/pubmatic/openwrap/entrypointhook.go b/modules/pubmatic/openwrap/entrypointhook.go index 4029232fd68..ccb2ea2fb11 100644 --- a/modules/pubmatic/openwrap/entrypointhook.go +++ b/modules/pubmatic/openwrap/entrypointhook.go @@ -2,6 +2,7 @@ package openwrap import ( "context" + "strconv" "time" "github.com/prebid/prebid-server/hooks/hookexecution" @@ -30,6 +31,7 @@ func (m OpenWrap) handleEntrypointHook( return result, nil } + var endpoint string var err error var requestExtWrapper models.RequestExtWrapper switch payload.Request.URL.Path { @@ -39,15 +41,27 @@ func (m OpenWrap) handleEntrypointHook( } requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body) case OpenWrapAuction: // legacy hybrid api should not execute module + m.metricEngine.RecordPBSAuctionRequestsStats() return result, nil case OpenWrapV25: requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper") + endpoint = models.EndpointV25 case OpenWrapV25Video: requestExtWrapper, err = v25.ConvertVideoToAuctionRequest(payload, &result) + endpoint = models.EndpointVideo case OpenWrapAmp: // requestExtWrapper, err = models.GetQueryParamRequestExtWrapper(payload.Body) + endpoint = models.EndpointAMP + default: + // we should return from here } + defer func() { + if len(result.Errors) > 0 { + m.metricEngine.RecordBadRequests(endpoint, getPubmaticErrorCode(result.NbrCode)) + } + }() + // init default for all modules result.Reject = true @@ -85,6 +99,9 @@ func (m OpenWrap) handleEntrypointHook( ImpBidCtx: make(map[string]models.ImpCtx), PrebidBidderCode: make(map[string]string), BidderResponseTimeMillis: make(map[string]int), + ProfileIDStr: strconv.Itoa(requestExtWrapper.ProfileId), + Endpoint: endpoint, + MetricsEngine: m.metricEngine, } // only http.ErrNoCookie is returned, we can ignore it diff --git a/modules/pubmatic/openwrap/entrypointhook_test.go b/modules/pubmatic/openwrap/entrypointhook_test.go index b8e6c34ebdf..23b2e264861 100644 --- a/modules/pubmatic/openwrap/entrypointhook_test.go +++ b/modules/pubmatic/openwrap/entrypointhook_test.go @@ -5,15 +5,21 @@ import ( "net/http" "testing" + "github.com/golang/mock/gomock" "github.com/prebid/prebid-server/hooks/hookstage" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/mock" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/nbr" "github.com/stretchr/testify/assert" ) func TestOpenWrap_handleEntrypointHook(t *testing.T) { + ctrl := gomock.NewController(t) + mockEngine := mock.NewMockMetricsEngine(ctrl) + defer ctrl.Finish() + type fields struct { cfg config.Config cache cache.Cache @@ -22,6 +28,7 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { in0 context.Context miCtx hookstage.ModuleInvocationContext payload hookstage.EntrypointPayload + setup func(*mock.MockMetricsEngine) } tests := []struct { name string @@ -48,6 +55,7 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { }(), Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`), }, + setup: func(mme *mock.MockMetricsEngine) {}, }, want: hookstage.HookResult[hookstage.EntrypointPayload]{}, }, @@ -78,6 +86,7 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { }(), Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`), }, + setup: func(mme *mock.MockMetricsEngine) {}, }, want: hookstage.HookResult[hookstage.EntrypointPayload]{ ModuleContext: hookstage.ModuleContext{ @@ -104,6 +113,9 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { ImpBidCtx: make(map[string]models.ImpCtx), PrebidBidderCode: make(map[string]string), BidderResponseTimeMillis: make(map[string]int), + ProfileIDStr: "5890", + Endpoint: models.EndpointV25, + MetricsEngine: mockEngine, }, }, }, @@ -135,6 +147,7 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { }(), Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1,"wiid":"4df09505-d0b2-4d70-94d9-dc41e8e777f7"}}}`), }, + setup: func(mme *mock.MockMetricsEngine) {}, }, want: hookstage.HookResult[hookstage.EntrypointPayload]{ ModuleContext: hookstage.ModuleContext{ @@ -153,6 +166,9 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { ImpBidCtx: make(map[string]models.ImpCtx), PrebidBidderCode: make(map[string]string), BidderResponseTimeMillis: make(map[string]int), + ProfileIDStr: "5890", + Endpoint: models.EndpointV25, + MetricsEngine: mockEngine, }, }, }, @@ -177,6 +193,9 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { }(), Body: []byte(`{"ext":{"wrapper":{"profileids":5890,"versionid":1}}}`), }, + setup: func(mme *mock.MockMetricsEngine) { + mme.EXPECT().RecordBadRequests(gomock.Any(), 700) + }, }, want: hookstage.HookResult[hookstage.EntrypointPayload]{ Reject: true, @@ -188,9 +207,12 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + + tt.args.setup(mockEngine) m := OpenWrap{ - cfg: tt.fields.cfg, - cache: tt.fields.cache, + cfg: tt.fields.cfg, + cache: tt.fields.cache, + metricEngine: mockEngine, } got, err := m.handleEntrypointHook(tt.args.in0, tt.args.miCtx, tt.args.payload) assert.Equal(t, err, tt.wantErr) diff --git a/modules/pubmatic/openwrap/metrics/config/metrics.go b/modules/pubmatic/openwrap/metrics/config/metrics.go new file mode 100644 index 00000000000..bde02748f58 --- /dev/null +++ b/modules/pubmatic/openwrap/metrics/config/metrics.go @@ -0,0 +1,385 @@ +package config + +import ( + "fmt" + + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/stats" +) + +// NewMetricsEngine initialises the stats-client and prometheus and return them as MultiMetricsEngine +func NewMetricsEngine(cfg config.Config) (MultiMetricsEngine, error) { + + // Create a list of metrics engines to use. + engineList := make(MultiMetricsEngine, 0, 1) + + if cfg.Stats.Endpoint != "" { + hostName := cfg.Stats.DefaultHostName // Dummy hostname N:P + if cfg.Stats.UseHostName { + hostName = cfg.Server.HostName // actual hostname node-name:pod-name + } + + sc, err := stats.InitStatsClient( + cfg.Stats.Endpoint, + hostName, + cfg.Server.HostName, + cfg.Server.DCName, + cfg.Stats.PublishInterval, + cfg.Stats.PublishThreshold, + cfg.Stats.Retries, + cfg.Stats.DialTimeout, + cfg.Stats.KeepAliveDuration, + cfg.Stats.MaxIdleConnections, + cfg.Stats.MaxIdleConnectionsPerHost, + cfg.Stats.ResponseHeaderTimeout, + cfg.Stats.MaxChannelLength, + cfg.Stats.PoolMaxWorkers, + cfg.Stats.PoolMaxCapacity) + + if err != nil { + return nil, err + } + + engineList = append(engineList, sc) + } + + // TODO: Set up the Prometheus metrics engine. + if len(engineList) > 0 { + return engineList, nil + } + return nil, fmt.Errorf("metric-engine is not configured") +} + +// MultiMetricsEngine logs metrics to multiple metrics databases The can be useful in transitioning +// an instance from one engine to another, you can run both in parallel to verify stats match up. +type MultiMetricsEngine []metrics.MetricsEngine + +// RecordOpenWrapServerPanicStats across all engines +func (me *MultiMetricsEngine) RecordOpenWrapServerPanicStats() { + for _, thisME := range *me { + thisME.RecordOpenWrapServerPanicStats() + } +} + +// RecordPublisherPartnerNoCookieStats across all engines +func (me *MultiMetricsEngine) RecordPublisherPartnerNoCookieStats(publisher, partner string) { + for _, thisME := range *me { + thisME.RecordPublisherPartnerNoCookieStats(publisher, partner) + } +} + +// RecordPartnerTimeoutErrorStats across all engines +func (me *MultiMetricsEngine) RecordPartnerTimeoutErrorStats(publisher, partner string) { + for _, thisME := range *me { + thisME.RecordPartnerTimeoutErrorStats(publisher, partner) + } +} + +// RecordNobidErrorStats across all engines +func (me *MultiMetricsEngine) RecordNobidErrorStats(publisher, partner string) { + for _, thisME := range *me { + thisME.RecordNobidErrorStats(publisher, partner) + } +} + +// RecordUnkownPrebidErrorStats across all engines +func (me *MultiMetricsEngine) RecordUnkownPrebidErrorStats(publisher, partner string) { + for _, thisME := range *me { + thisME.RecordUnkownPrebidErrorStats(publisher, partner) + } +} + +// RecordSlotNotMappedErrorStats across all engines +func (me *MultiMetricsEngine) RecordSlotNotMappedErrorStats(publisher, partner string) { + for _, thisME := range *me { + thisME.RecordSlotNotMappedErrorStats(publisher, partner) + } +} + +// RecordMisConfigurationErrorStats across all engines +func (me *MultiMetricsEngine) RecordMisConfigurationErrorStats(publisher, partner string) { + for _, thisME := range *me { + thisME.RecordMisConfigurationErrorStats(publisher, partner) + } +} + +// RecordPublisherProfileRequests across all engines +func (me *MultiMetricsEngine) RecordPublisherProfileRequests(publisher, profile string) { + for _, thisME := range *me { + thisME.RecordPublisherProfileRequests(publisher, profile) + } +} + +// RecordPublisherInvalidProfileImpressions across all engines +func (me *MultiMetricsEngine) RecordPublisherInvalidProfileImpressions(publisher, profileID string, impCount int) { + for _, thisME := range *me { + thisME.RecordPublisherInvalidProfileImpressions(publisher, profileID, impCount) + } +} + +// RecordNobidErrPrebidServerRequests across all engines +func (me *MultiMetricsEngine) RecordNobidErrPrebidServerRequests(publisher string) { + for _, thisME := range *me { + thisME.RecordNobidErrPrebidServerRequests(publisher) + } +} + +// RecordNobidErrPrebidServerResponse across all engines +func (me *MultiMetricsEngine) RecordNobidErrPrebidServerResponse(publisher string) { + for _, thisME := range *me { + thisME.RecordNobidErrPrebidServerResponse(publisher) + } +} + +// RecordInvalidCreativeStats across all engines +func (me *MultiMetricsEngine) RecordInvalidCreativeStats(publisher, partner string) { + for _, thisME := range *me { + thisME.RecordInvalidCreativeStats(publisher, partner) + } +} + +// RecordInvalidCreativeStats across all engines +func (me *MultiMetricsEngine) RecordPlatformPublisherPartnerReqStats(platform, publisher, partner string) { + for _, thisME := range *me { + thisME.RecordPlatformPublisherPartnerReqStats(platform, publisher, partner) + } +} + +// RecordInvalidCreativeStats across all engines +func (me *MultiMetricsEngine) RecordPlatformPublisherPartnerResponseStats(platform, publisher, partner string) { + for _, thisME := range *me { + thisME.RecordPlatformPublisherPartnerResponseStats(platform, publisher, partner) + } +} + +// RecordPublisherResponseEncodingErrorStats across all engines +func (me *MultiMetricsEngine) RecordPublisherResponseEncodingErrorStats(publisher string) { + for _, thisME := range *me { + thisME.RecordPublisherResponseEncodingErrorStats(publisher) + } +} + +// RecordPartnerResponseTimeStats across all engines +func (me *MultiMetricsEngine) RecordPartnerResponseTimeStats(publisher, profileID string, responseTime int) { + for _, thisME := range *me { + thisME.RecordPartnerResponseTimeStats(publisher, profileID, responseTime) + } +} + +// RecordPublisherResponseTimeStats across all engines +func (me *MultiMetricsEngine) RecordPublisherResponseTimeStats(publisher string, responseTime int) { + for _, thisME := range *me { + thisME.RecordPublisherResponseTimeStats(publisher, responseTime) + } +} + +// RecordPublisherWrapperLoggerFailure across all engines +func (me *MultiMetricsEngine) RecordPublisherWrapperLoggerFailure(publisher, profileID, versionID string) { + for _, thisME := range *me { + thisME.RecordPublisherWrapperLoggerFailure(publisher, profileID, versionID) + } +} + +// RecordCacheErrorRequests across all engines +func (me *MultiMetricsEngine) RecordCacheErrorRequests(endpoint, publisher, profileID string) { + for _, thisME := range *me { + thisME.RecordCacheErrorRequests(endpoint, publisher, profileID) + } +} + +// RecordPublisherInvalidProfileRequests across all engines +func (me *MultiMetricsEngine) RecordPublisherInvalidProfileRequests(endpoint, publisher, profileID string) { + for _, thisME := range *me { + thisME.RecordPublisherInvalidProfileRequests(endpoint, publisher, profileID) + } +} + +// RecordBadRequests across all engines +func (me *MultiMetricsEngine) RecordBadRequests(endpoint string, errorCode int) { + for _, thisME := range *me { + thisME.RecordBadRequests(endpoint, errorCode) + } +} + +// RecordPrebidTimeoutRequests across all engines +func (me *MultiMetricsEngine) RecordPrebidTimeoutRequests(publisher, profileID string) { + for _, thisME := range *me { + thisME.RecordPrebidTimeoutRequests(publisher, profileID) + } +} + +// RecordSSTimeoutRequests across all engines +func (me *MultiMetricsEngine) RecordSSTimeoutRequests(publisher, profileID string) { + for _, thisME := range *me { + thisME.RecordSSTimeoutRequests(publisher, profileID) + } +} + +// RecordUidsCookieNotPresentErrorStats across all engines +func (me *MultiMetricsEngine) RecordUidsCookieNotPresentErrorStats(publisher, profileID string) { + for _, thisME := range *me { + thisME.RecordUidsCookieNotPresentErrorStats(publisher, profileID) + } +} + +// RecordVideoInstlImpsStats across all engines +func (me *MultiMetricsEngine) RecordVideoInstlImpsStats(publisher, profileID string) { + for _, thisME := range *me { + thisME.RecordVideoInstlImpsStats(publisher, profileID) + } +} + +// RecordImpDisabledViaConfigStats across all engines +func (me *MultiMetricsEngine) RecordImpDisabledViaConfigStats(impType, publisher, profileID string) { + for _, thisME := range *me { + thisME.RecordImpDisabledViaConfigStats(impType, publisher, profileID) + } +} + +// RecordPreProcessingTimeStats across all engines +func (me *MultiMetricsEngine) RecordPreProcessingTimeStats(publisher string, processingTime int) { + for _, thisME := range *me { + thisME.RecordPreProcessingTimeStats(publisher, processingTime) + } +} + +// RecordStatsKeyCTVPrebidFailedImpression across all engines +func (me *MultiMetricsEngine) RecordStatsKeyCTVPrebidFailedImpression(errorcode int, publisher string, profile string) { + for _, thisME := range *me { + thisME.RecordStatsKeyCTVPrebidFailedImpression(errorcode, publisher, profile) + } +} + +// RecordCTVRequests across all engines +func (me *MultiMetricsEngine) RecordCTVRequests(endpoint, platform string) { + for _, thisME := range *me { + thisME.RecordCTVRequests(endpoint, platform) + } +} + +// RecordPublisherRequests across all engines +func (me *MultiMetricsEngine) RecordPublisherRequests(endpoint, publisher, platform string) { + for _, thisME := range *me { + thisME.RecordPublisherRequests(endpoint, publisher, platform) + } +} + +// RecordCTVHTTPMethodRequests across all engines +func (me *MultiMetricsEngine) RecordCTVHTTPMethodRequests(endpoint, publisher, method string) { + for _, thisME := range *me { + thisME.RecordCTVHTTPMethodRequests(endpoint, publisher, method) + } +} + +// RecordCTVInvalidReasonCount across all engines +func (me *MultiMetricsEngine) RecordCTVInvalidReasonCount(errorCode int, publisher string) { + for _, thisME := range *me { + thisME.RecordCTVInvalidReasonCount(errorCode, publisher) + } +} + +// RecordCTVReqImpsWithDbConfigCount across all engines +func (me *MultiMetricsEngine) RecordCTVReqImpsWithDbConfigCount(publisher string) { + for _, thisME := range *me { + thisME.RecordCTVReqImpsWithDbConfigCount(publisher) + } +} + +// RecordCTVReqImpsWithReqConfigCount across all engines +func (me *MultiMetricsEngine) RecordCTVReqImpsWithReqConfigCount(publisher string) { + for _, thisME := range *me { + thisME.RecordCTVReqImpsWithReqConfigCount(publisher) + } +} + +// RecordAdPodGeneratedImpressionsCount across all engines +func (me *MultiMetricsEngine) RecordAdPodGeneratedImpressionsCount(impCount int, publisher string) { + for _, thisME := range *me { + thisME.RecordAdPodGeneratedImpressionsCount(impCount, publisher) + } +} + +// RecordRequestAdPodGeneratedImpressionsCount across all engines +func (me *MultiMetricsEngine) RecordRequestAdPodGeneratedImpressionsCount(impCount int, publisher string) { + for _, thisME := range *me { + thisME.RecordRequestAdPodGeneratedImpressionsCount(impCount, publisher) + } +} + +// RecordAdPodImpressionYield across all engines +func (me *MultiMetricsEngine) RecordAdPodImpressionYield(maxDuration int, minDuration int, publisher string) { + for _, thisME := range *me { + thisME.RecordAdPodImpressionYield(maxDuration, minDuration, publisher) + } +} + +// RecordCTVReqCountWithAdPod across all engines +func (me *MultiMetricsEngine) RecordCTVReqCountWithAdPod(publisher, profile string) { + for _, thisME := range *me { + thisME.RecordCTVReqCountWithAdPod(publisher, profile) + } +} + +// RecordReqImpsWithAppContentCount across all engines +func (me *MultiMetricsEngine) RecordReqImpsWithAppContentCount(publisher string) { + for _, thisME := range *me { + thisME.RecordReqImpsWithAppContentCount(publisher) + } +} + +// RecordReqImpsWithSiteContentCount across all engines +func (me *MultiMetricsEngine) RecordReqImpsWithSiteContentCount(publisher string) { + for _, thisME := range *me { + thisME.RecordReqImpsWithSiteContentCount(publisher) + } +} + +// RecordPBSAuctionRequestsStats across all engines +func (me *MultiMetricsEngine) RecordPBSAuctionRequestsStats() { + for _, thisME := range *me { + thisME.RecordPBSAuctionRequestsStats() + } +} + +// RecordInjectTrackerErrorCount across all engines +func (me *MultiMetricsEngine) RecordInjectTrackerErrorCount(adformat, publisher, partner string) { + for _, thisME := range *me { + thisME.RecordInjectTrackerErrorCount(adformat, publisher, partner) + } +} + +// RecordBidResponseByDealCountInPBS across all engines +func (me *MultiMetricsEngine) RecordBidResponseByDealCountInPBS(publisher, profile, aliasBidder, dealId string) { + for _, thisME := range *me { + thisME.RecordBidResponseByDealCountInPBS(publisher, profile, aliasBidder, dealId) + } +} + +// RecordBidResponseByDealCountInHB across all engines +func (me *MultiMetricsEngine) RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId string) { + for _, thisME := range *me { + thisME.RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId) + } +} + +// RecordPartnerTimeoutInPBS across all engines +func (me *MultiMetricsEngine) RecordPartnerTimeoutInPBS(publisher, profile, aliasBidder string) { + for _, thisME := range *me { + thisME.RecordPartnerTimeoutInPBS(publisher, profile, aliasBidder) + } +} + +// RecordVideoImpDisabledViaConnTypeStats across all engines +func (me *MultiMetricsEngine) RecordVideoImpDisabledViaConnTypeStats(publisher, profile string) { + for _, thisME := range *me { + thisME.RecordVideoImpDisabledViaConnTypeStats(publisher, profile) + } +} + +// Shutdown across all engines +func (me *MultiMetricsEngine) Shutdown() { + for _, thisME := range *me { + thisME.Shutdown() + } +} diff --git a/modules/pubmatic/openwrap/metrics/config/metrics_test.go b/modules/pubmatic/openwrap/metrics/config/metrics_test.go new file mode 100644 index 00000000000..08b7bf59bc9 --- /dev/null +++ b/modules/pubmatic/openwrap/metrics/config/metrics_test.go @@ -0,0 +1,186 @@ +package config + +import ( + "fmt" + "testing" + + "github.com/golang/mock/gomock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/mock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/stats" + "github.com/stretchr/testify/assert" +) + +func TestNewMetricsEngine(t *testing.T) { + + type want struct { + expectNilEngine bool + err error + } + testCases := []struct { + name string + cfg config.Config + want want + }{ + { + name: "Valid configuration with stats endpoint", + cfg: config.Config{ + Stats: stats.Stats{ + Endpoint: "http://example.com", + UseHostName: true, + }, + }, + want: want{ + expectNilEngine: false, + err: nil, + }, + }, + { + name: "Empty stats endpoint", + cfg: config.Config{ + Stats: stats.Stats{ + Endpoint: "", + }, + }, + want: want{ + expectNilEngine: true, + err: fmt.Errorf("metric-engine is not configured"), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actualOutput, actualError := NewMetricsEngine(tc.cfg) + assert.Equal(t, tc.want.expectNilEngine, actualOutput == nil) + assert.Equal(t, tc.want.err, actualError) + }) + } +} + +func TestRecordFunctionForMultiMetricsEngine(t *testing.T) { + + ctrl := gomock.NewController(t) + mockEngine := mock.NewMockMetricsEngine(ctrl) + defer ctrl.Finish() + + // set the variables + publisher := "5890" + profile := "123" + partner := "pubmatic" + impCount := 1 + platform := "video" + responseTime := 1 + endpoint := "in-app" + versionID := "1" + errorCode := 10 + processingTime := 10 + method := "GET" + maxDuration := 20 + minDuration := 10 + aliasBidder := "pubmatic-2" + adFormat := "banner" + dealId := "pubdeal" + + // set the expectations + mockEngine.EXPECT().RecordOpenWrapServerPanicStats() + mockEngine.EXPECT().RecordPublisherPartnerNoCookieStats(publisher, partner) + mockEngine.EXPECT().RecordPartnerTimeoutErrorStats(publisher, partner) + mockEngine.EXPECT().RecordNobidErrorStats(publisher, partner) + mockEngine.EXPECT().RecordUnkownPrebidErrorStats(publisher, partner) + mockEngine.EXPECT().RecordSlotNotMappedErrorStats(publisher, partner) + mockEngine.EXPECT().RecordMisConfigurationErrorStats(publisher, partner) + mockEngine.EXPECT().RecordPublisherProfileRequests(publisher, profile) + mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions(publisher, profile, impCount) + mockEngine.EXPECT().RecordNobidErrPrebidServerRequests(publisher) + mockEngine.EXPECT().RecordNobidErrPrebidServerResponse(publisher) + mockEngine.EXPECT().RecordInvalidCreativeStats(publisher, partner) + mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats(platform, publisher, partner) + mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats(platform, publisher, partner) + mockEngine.EXPECT().RecordPublisherResponseEncodingErrorStats(publisher) + mockEngine.EXPECT().RecordPartnerResponseTimeStats(publisher, partner, responseTime) + mockEngine.EXPECT().RecordPublisherResponseTimeStats(publisher, responseTime) + mockEngine.EXPECT().RecordPublisherWrapperLoggerFailure(publisher, profile, versionID) + mockEngine.EXPECT().RecordCacheErrorRequests(endpoint, publisher, profile) + mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(endpoint, publisher, profile) + mockEngine.EXPECT().RecordBadRequests(endpoint, errorCode) + mockEngine.EXPECT().RecordPrebidTimeoutRequests(publisher, profile) + mockEngine.EXPECT().RecordSSTimeoutRequests(publisher, profile) + mockEngine.EXPECT().RecordUidsCookieNotPresentErrorStats(publisher, profile) + mockEngine.EXPECT().RecordVideoInstlImpsStats(publisher, profile) + mockEngine.EXPECT().RecordImpDisabledViaConfigStats(adFormat, publisher, profile) + mockEngine.EXPECT().RecordPreProcessingTimeStats(publisher, processingTime) + mockEngine.EXPECT().RecordStatsKeyCTVPrebidFailedImpression(errorCode, publisher, profile) + mockEngine.EXPECT().RecordCTVRequests(endpoint, platform) + mockEngine.EXPECT().RecordPublisherRequests(endpoint, publisher, platform) + mockEngine.EXPECT().RecordCTVHTTPMethodRequests(endpoint, publisher, method) + mockEngine.EXPECT().RecordCTVInvalidReasonCount(errorCode, publisher) + mockEngine.EXPECT().RecordCTVReqImpsWithDbConfigCount(publisher) + mockEngine.EXPECT().RecordCTVReqImpsWithReqConfigCount(publisher) + mockEngine.EXPECT().RecordAdPodGeneratedImpressionsCount(impCount, publisher) + mockEngine.EXPECT().RecordRequestAdPodGeneratedImpressionsCount(impCount, publisher) + mockEngine.EXPECT().RecordReqImpsWithAppContentCount(publisher) + mockEngine.EXPECT().RecordReqImpsWithSiteContentCount(publisher) + mockEngine.EXPECT().RecordAdPodImpressionYield(maxDuration, minDuration, publisher) + mockEngine.EXPECT().RecordCTVReqCountWithAdPod(publisher, profile) + mockEngine.EXPECT().RecordPBSAuctionRequestsStats() + mockEngine.EXPECT().RecordInjectTrackerErrorCount(adFormat, publisher, partner) + mockEngine.EXPECT().RecordBidResponseByDealCountInPBS(publisher, profile, aliasBidder, dealId) + mockEngine.EXPECT().RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId) + mockEngine.EXPECT().RecordPartnerTimeoutInPBS(publisher, profile, aliasBidder) + mockEngine.EXPECT().RecordVideoImpDisabledViaConnTypeStats(publisher, profile) + mockEngine.EXPECT().Shutdown() + + // create the multi-metric engine + multiMetricEngine := MultiMetricsEngine{} + multiMetricEngine = append(multiMetricEngine, mockEngine) + + // call the functions + multiMetricEngine.RecordOpenWrapServerPanicStats() + multiMetricEngine.RecordPublisherPartnerNoCookieStats(publisher, partner) + multiMetricEngine.RecordPartnerTimeoutErrorStats(publisher, partner) + multiMetricEngine.RecordNobidErrorStats(publisher, partner) + multiMetricEngine.RecordUnkownPrebidErrorStats(publisher, partner) + multiMetricEngine.RecordSlotNotMappedErrorStats(publisher, partner) + multiMetricEngine.RecordMisConfigurationErrorStats(publisher, partner) + multiMetricEngine.RecordPublisherProfileRequests(publisher, profile) + multiMetricEngine.RecordPublisherInvalidProfileImpressions(publisher, profile, impCount) + multiMetricEngine.RecordNobidErrPrebidServerRequests(publisher) + multiMetricEngine.RecordNobidErrPrebidServerResponse(publisher) + multiMetricEngine.RecordInvalidCreativeStats(publisher, partner) + multiMetricEngine.RecordPlatformPublisherPartnerReqStats(platform, publisher, partner) + multiMetricEngine.RecordPlatformPublisherPartnerResponseStats(platform, publisher, partner) + multiMetricEngine.RecordPublisherResponseEncodingErrorStats(publisher) + multiMetricEngine.RecordPartnerResponseTimeStats(publisher, partner, responseTime) + multiMetricEngine.RecordPublisherResponseTimeStats(publisher, responseTime) + multiMetricEngine.RecordPublisherWrapperLoggerFailure(publisher, profile, versionID) + multiMetricEngine.RecordCacheErrorRequests(endpoint, publisher, profile) + multiMetricEngine.RecordPublisherInvalidProfileRequests(endpoint, publisher, profile) + multiMetricEngine.RecordBadRequests(endpoint, errorCode) + multiMetricEngine.RecordPrebidTimeoutRequests(publisher, profile) + multiMetricEngine.RecordSSTimeoutRequests(publisher, profile) + multiMetricEngine.RecordUidsCookieNotPresentErrorStats(publisher, profile) + multiMetricEngine.RecordVideoInstlImpsStats(publisher, profile) + multiMetricEngine.RecordImpDisabledViaConfigStats(adFormat, publisher, profile) + multiMetricEngine.RecordPreProcessingTimeStats(publisher, processingTime) + multiMetricEngine.RecordStatsKeyCTVPrebidFailedImpression(errorCode, publisher, profile) + multiMetricEngine.RecordCTVRequests(endpoint, platform) + multiMetricEngine.RecordPublisherRequests(endpoint, publisher, platform) + multiMetricEngine.RecordCTVHTTPMethodRequests(endpoint, publisher, method) + multiMetricEngine.RecordCTVInvalidReasonCount(errorCode, publisher) + multiMetricEngine.RecordCTVReqImpsWithDbConfigCount(publisher) + multiMetricEngine.RecordCTVReqImpsWithReqConfigCount(publisher) + multiMetricEngine.RecordAdPodGeneratedImpressionsCount(impCount, publisher) + multiMetricEngine.RecordRequestAdPodGeneratedImpressionsCount(impCount, publisher) + multiMetricEngine.RecordReqImpsWithAppContentCount(publisher) + multiMetricEngine.RecordReqImpsWithSiteContentCount(publisher) + multiMetricEngine.RecordAdPodImpressionYield(maxDuration, minDuration, publisher) + multiMetricEngine.RecordCTVReqCountWithAdPod(publisher, profile) + multiMetricEngine.RecordPBSAuctionRequestsStats() + multiMetricEngine.RecordInjectTrackerErrorCount(adFormat, publisher, partner) + multiMetricEngine.RecordBidResponseByDealCountInPBS(publisher, profile, aliasBidder, dealId) + multiMetricEngine.RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId) + multiMetricEngine.RecordPartnerTimeoutInPBS(publisher, profile, aliasBidder) + multiMetricEngine.RecordVideoImpDisabledViaConnTypeStats(publisher, profile) + multiMetricEngine.Shutdown() +} diff --git a/modules/pubmatic/openwrap/metrics/metrics.go b/modules/pubmatic/openwrap/metrics/metrics.go index af163a0277b..edfb5da2fa5 100644 --- a/modules/pubmatic/openwrap/metrics/metrics.go +++ b/modules/pubmatic/openwrap/metrics/metrics.go @@ -3,20 +3,14 @@ package metrics // MetricsEngine is a generic interface to record PBS metrics into the desired backend type MetricsEngine interface { RecordOpenWrapServerPanicStats() - RecordPublisherPartnerStats(publisher, partner string) - RecordPublisherPartnerImpStats(publisher, partner string, impCount int) RecordPublisherPartnerNoCookieStats(publisher, partner string) RecordPartnerTimeoutErrorStats(publisher, partner string) - RecordNobiderStatusErrorStats(publisher, partner string) RecordNobidErrorStats(publisher, partner string) RecordUnkownPrebidErrorStats(publisher, partner string) RecordSlotNotMappedErrorStats(publisher, partner string) RecordMisConfigurationErrorStats(publisher, partner string) RecordPublisherProfileRequests(publisher, profileID string) RecordPublisherInvalidProfileImpressions(publisher, profileID string, impCount int) - RecordPublisherNoConsentRequests(publisher string) - RecordPublisherNoConsentImpressions(publisher string, impCount int) - RecordPublisherRequestStats(publisher string) RecordNobidErrPrebidServerRequests(publisher string) RecordNobidErrPrebidServerResponse(publisher string) RecordInvalidCreativeStats(publisher, partner string) @@ -40,21 +34,19 @@ type MetricsEngine interface { RecordPublisherRequests(endpoint string, publisher string, platform string) RecordCTVHTTPMethodRequests(endpoint string, publisher string, method string) RecordCTVInvalidReasonCount(errorCode int, publisher string) - RecordCTVIncompleteAdPodsCount(impCount int, reason string, publisher string) RecordCTVReqImpsWithDbConfigCount(publisher string) RecordCTVReqImpsWithReqConfigCount(publisher string) RecordAdPodGeneratedImpressionsCount(impCount int, publisher string) RecordRequestAdPodGeneratedImpressionsCount(impCount int, publisher string) - RecordAdPodSecondsMissedCount(seconds int, publisher string) RecordReqImpsWithAppContentCount(publisher string) RecordReqImpsWithSiteContentCount(publisher string) RecordAdPodImpressionYield(maxDuration int, minDuration int, publisher string) RecordCTVReqCountWithAdPod(publisherID, profileID string) - RecordCTVKeyBidDuration(duration int, publisherID, profileID string) RecordPBSAuctionRequestsStats() RecordInjectTrackerErrorCount(adformat, publisher, partner string) RecordBidResponseByDealCountInPBS(publisher, profile, aliasBidder, dealId string) RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId string) RecordPartnerTimeoutInPBS(publisher, profile, aliasBidder string) RecordVideoImpDisabledViaConnTypeStats(publisher, profileID string) + Shutdown() } diff --git a/modules/pubmatic/openwrap/metrics/mock/mock.go b/modules/pubmatic/openwrap/metrics/mock/mock.go new file mode 100644 index 00000000000..41d949fd71d --- /dev/null +++ b/modules/pubmatic/openwrap/metrics/mock/mock.go @@ -0,0 +1,705 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/PubMatic-OpenWrap/prebid-server/modules/pubmatic/openwrap/metrics (interfaces: MetricsEngine) + +// Package mock_metrics is a generated GoMock package. +package mock + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockMetricsEngine is a mock of MetricsEngine interface +type MockMetricsEngine struct { + ctrl *gomock.Controller + recorder *MockMetricsEngineMockRecorder +} + +// MockMetricsEngineMockRecorder is the mock recorder for MockMetricsEngine +type MockMetricsEngineMockRecorder struct { + mock *MockMetricsEngine +} + +// NewMockMetricsEngine creates a new mock instance +func NewMockMetricsEngine(ctrl *gomock.Controller) *MockMetricsEngine { + mock := &MockMetricsEngine{ctrl: ctrl} + mock.recorder = &MockMetricsEngineMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockMetricsEngine) EXPECT() *MockMetricsEngineMockRecorder { + return m.recorder +} + +// RecordAdPodGeneratedImpressionsCount mocks base method +func (m *MockMetricsEngine) RecordAdPodGeneratedImpressionsCount(arg0 int, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordAdPodGeneratedImpressionsCount", arg0, arg1) +} + +// RecordAdPodGeneratedImpressionsCount indicates an expected call of RecordAdPodGeneratedImpressionsCount +func (mr *MockMetricsEngineMockRecorder) RecordAdPodGeneratedImpressionsCount(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordAdPodGeneratedImpressionsCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordAdPodGeneratedImpressionsCount), arg0, arg1) +} + +// RecordAdPodImpressionYield mocks base method +func (m *MockMetricsEngine) RecordAdPodImpressionYield(arg0, arg1 int, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordAdPodImpressionYield", arg0, arg1, arg2) +} + +// RecordAdPodImpressionYield indicates an expected call of RecordAdPodImpressionYield +func (mr *MockMetricsEngineMockRecorder) RecordAdPodImpressionYield(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordAdPodImpressionYield", reflect.TypeOf((*MockMetricsEngine)(nil).RecordAdPodImpressionYield), arg0, arg1, arg2) +} + +// RecordAdPodSecondsMissedCount mocks base method +func (m *MockMetricsEngine) RecordAdPodSecondsMissedCount(arg0 int, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordAdPodSecondsMissedCount", arg0, arg1) +} + +// RecordAdPodSecondsMissedCount indicates an expected call of RecordAdPodSecondsMissedCount +func (mr *MockMetricsEngineMockRecorder) RecordAdPodSecondsMissedCount(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordAdPodSecondsMissedCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordAdPodSecondsMissedCount), arg0, arg1) +} + +// RecordBadRequests mocks base method +func (m *MockMetricsEngine) RecordBadRequests(arg0 string, arg1 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordBadRequests", arg0, arg1) +} + +// RecordBadRequests indicates an expected call of RecordBadRequests +func (mr *MockMetricsEngineMockRecorder) RecordBadRequests(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBadRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBadRequests), arg0, arg1) +} + +// RecordBidResponseByDealCountInHB mocks base method +func (m *MockMetricsEngine) RecordBidResponseByDealCountInHB(arg0, arg1, arg2, arg3 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordBidResponseByDealCountInHB", arg0, arg1, arg2, arg3) +} + +// RecordBidResponseByDealCountInHB indicates an expected call of RecordBidResponseByDealCountInHB +func (mr *MockMetricsEngineMockRecorder) RecordBidResponseByDealCountInHB(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBidResponseByDealCountInHB", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBidResponseByDealCountInHB), arg0, arg1, arg2, arg3) +} + +// RecordBidResponseByDealCountInPBS mocks base method +func (m *MockMetricsEngine) RecordBidResponseByDealCountInPBS(arg0, arg1, arg2, arg3 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordBidResponseByDealCountInPBS", arg0, arg1, arg2, arg3) +} + +// RecordBidResponseByDealCountInPBS indicates an expected call of RecordBidResponseByDealCountInPBS +func (mr *MockMetricsEngineMockRecorder) RecordBidResponseByDealCountInPBS(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBidResponseByDealCountInPBS", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBidResponseByDealCountInPBS), arg0, arg1, arg2, arg3) +} + +// RecordCTVHTTPMethodRequests mocks base method +func (m *MockMetricsEngine) RecordCTVHTTPMethodRequests(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVHTTPMethodRequests", arg0, arg1, arg2) +} + +// RecordCTVHTTPMethodRequests indicates an expected call of RecordCTVHTTPMethodRequests +func (mr *MockMetricsEngineMockRecorder) RecordCTVHTTPMethodRequests(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVHTTPMethodRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVHTTPMethodRequests), arg0, arg1, arg2) +} + +// RecordCTVIncompleteAdPodsCount mocks base method +func (m *MockMetricsEngine) RecordCTVIncompleteAdPodsCount(arg0 int, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVIncompleteAdPodsCount", arg0, arg1, arg2) +} + +// RecordCTVIncompleteAdPodsCount indicates an expected call of RecordCTVIncompleteAdPodsCount +func (mr *MockMetricsEngineMockRecorder) RecordCTVIncompleteAdPodsCount(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVIncompleteAdPodsCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVIncompleteAdPodsCount), arg0, arg1, arg2) +} + +// RecordCTVInvalidReasonCount mocks base method +func (m *MockMetricsEngine) RecordCTVInvalidReasonCount(arg0 int, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVInvalidReasonCount", arg0, arg1) +} + +// RecordCTVInvalidReasonCount indicates an expected call of RecordCTVInvalidReasonCount +func (mr *MockMetricsEngineMockRecorder) RecordCTVInvalidReasonCount(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVInvalidReasonCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVInvalidReasonCount), arg0, arg1) +} + +// RecordCTVKeyBidDuration mocks base method +func (m *MockMetricsEngine) RecordCTVKeyBidDuration(arg0 int, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVKeyBidDuration", arg0, arg1, arg2) +} + +// RecordCTVKeyBidDuration indicates an expected call of RecordCTVKeyBidDuration +func (mr *MockMetricsEngineMockRecorder) RecordCTVKeyBidDuration(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVKeyBidDuration", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVKeyBidDuration), arg0, arg1, arg2) +} + +// RecordCTVReqCountWithAdPod mocks base method +func (m *MockMetricsEngine) RecordCTVReqCountWithAdPod(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVReqCountWithAdPod", arg0, arg1) +} + +// RecordCTVReqCountWithAdPod indicates an expected call of RecordCTVReqCountWithAdPod +func (mr *MockMetricsEngineMockRecorder) RecordCTVReqCountWithAdPod(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVReqCountWithAdPod", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVReqCountWithAdPod), arg0, arg1) +} + +// RecordCTVReqImpsWithDbConfigCount mocks base method +func (m *MockMetricsEngine) RecordCTVReqImpsWithDbConfigCount(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVReqImpsWithDbConfigCount", arg0) +} + +// RecordCTVReqImpsWithDbConfigCount indicates an expected call of RecordCTVReqImpsWithDbConfigCount +func (mr *MockMetricsEngineMockRecorder) RecordCTVReqImpsWithDbConfigCount(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVReqImpsWithDbConfigCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVReqImpsWithDbConfigCount), arg0) +} + +// RecordCTVReqImpsWithReqConfigCount mocks base method +func (m *MockMetricsEngine) RecordCTVReqImpsWithReqConfigCount(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVReqImpsWithReqConfigCount", arg0) +} + +// RecordCTVReqImpsWithReqConfigCount indicates an expected call of RecordCTVReqImpsWithReqConfigCount +func (mr *MockMetricsEngineMockRecorder) RecordCTVReqImpsWithReqConfigCount(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVReqImpsWithReqConfigCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVReqImpsWithReqConfigCount), arg0) +} + +// RecordCTVRequests mocks base method +func (m *MockMetricsEngine) RecordCTVRequests(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCTVRequests", arg0, arg1) +} + +// RecordCTVRequests indicates an expected call of RecordCTVRequests +func (mr *MockMetricsEngineMockRecorder) RecordCTVRequests(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVRequests), arg0, arg1) +} + +// RecordCacheErrorRequests mocks base method +func (m *MockMetricsEngine) RecordCacheErrorRequests(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordCacheErrorRequests", arg0, arg1, arg2) +} + +// RecordCacheErrorRequests indicates an expected call of RecordCacheErrorRequests +func (mr *MockMetricsEngineMockRecorder) RecordCacheErrorRequests(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCacheErrorRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCacheErrorRequests), arg0, arg1, arg2) +} + +// RecordImpDisabledViaConfigStats mocks base method +func (m *MockMetricsEngine) RecordImpDisabledViaConfigStats(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordImpDisabledViaConfigStats", arg0, arg1, arg2) +} + +// RecordImpDisabledViaConfigStats indicates an expected call of RecordImpDisabledViaConfigStats +func (mr *MockMetricsEngineMockRecorder) RecordImpDisabledViaConfigStats(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordImpDisabledViaConfigStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordImpDisabledViaConfigStats), arg0, arg1, arg2) +} + +// RecordInjectTrackerErrorCount mocks base method +func (m *MockMetricsEngine) RecordInjectTrackerErrorCount(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordInjectTrackerErrorCount", arg0, arg1, arg2) +} + +// RecordInjectTrackerErrorCount indicates an expected call of RecordInjectTrackerErrorCount +func (mr *MockMetricsEngineMockRecorder) RecordInjectTrackerErrorCount(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordInjectTrackerErrorCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordInjectTrackerErrorCount), arg0, arg1, arg2) +} + +// RecordInvalidCreativeStats mocks base method +func (m *MockMetricsEngine) RecordInvalidCreativeStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordInvalidCreativeStats", arg0, arg1) +} + +// RecordInvalidCreativeStats indicates an expected call of RecordInvalidCreativeStats +func (mr *MockMetricsEngineMockRecorder) RecordInvalidCreativeStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordInvalidCreativeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordInvalidCreativeStats), arg0, arg1) +} + +// RecordMisConfigurationErrorStats mocks base method +func (m *MockMetricsEngine) RecordMisConfigurationErrorStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordMisConfigurationErrorStats", arg0, arg1) +} + +// RecordMisConfigurationErrorStats indicates an expected call of RecordMisConfigurationErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordMisConfigurationErrorStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordMisConfigurationErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordMisConfigurationErrorStats), arg0, arg1) +} + +// RecordNobidErrPrebidServerRequests mocks base method +func (m *MockMetricsEngine) RecordNobidErrPrebidServerRequests(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordNobidErrPrebidServerRequests", arg0) +} + +// RecordNobidErrPrebidServerRequests indicates an expected call of RecordNobidErrPrebidServerRequests +func (mr *MockMetricsEngineMockRecorder) RecordNobidErrPrebidServerRequests(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordNobidErrPrebidServerRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordNobidErrPrebidServerRequests), arg0) +} + +// RecordNobidErrPrebidServerResponse mocks base method +func (m *MockMetricsEngine) RecordNobidErrPrebidServerResponse(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordNobidErrPrebidServerResponse", arg0) +} + +// RecordNobidErrPrebidServerResponse indicates an expected call of RecordNobidErrPrebidServerResponse +func (mr *MockMetricsEngineMockRecorder) RecordNobidErrPrebidServerResponse(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordNobidErrPrebidServerResponse", reflect.TypeOf((*MockMetricsEngine)(nil).RecordNobidErrPrebidServerResponse), arg0) +} + +// RecordNobidErrorStats mocks base method +func (m *MockMetricsEngine) RecordNobidErrorStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordNobidErrorStats", arg0, arg1) +} + +// RecordNobidErrorStats indicates an expected call of RecordNobidErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordNobidErrorStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordNobidErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordNobidErrorStats), arg0, arg1) +} + +// RecordNobiderStatusErrorStats mocks base method +func (m *MockMetricsEngine) RecordNobiderStatusErrorStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordNobiderStatusErrorStats", arg0, arg1) +} + +// RecordNobiderStatusErrorStats indicates an expected call of RecordNobiderStatusErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordNobiderStatusErrorStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordNobiderStatusErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordNobiderStatusErrorStats), arg0, arg1) +} + +// RecordOpenWrapServerPanicStats mocks base method +func (m *MockMetricsEngine) RecordOpenWrapServerPanicStats() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordOpenWrapServerPanicStats") +} + +// RecordOpenWrapServerPanicStats indicates an expected call of RecordOpenWrapServerPanicStats +func (mr *MockMetricsEngineMockRecorder) RecordOpenWrapServerPanicStats() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordOpenWrapServerPanicStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordOpenWrapServerPanicStats)) +} + +// RecordPBSAuctionRequestsStats mocks base method +func (m *MockMetricsEngine) RecordPBSAuctionRequestsStats() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPBSAuctionRequestsStats") +} + +// RecordPBSAuctionRequestsStats indicates an expected call of RecordPBSAuctionRequestsStats +func (mr *MockMetricsEngineMockRecorder) RecordPBSAuctionRequestsStats() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPBSAuctionRequestsStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPBSAuctionRequestsStats)) +} + +// RecordPartnerResponseTimeStats mocks base method +func (m *MockMetricsEngine) RecordPartnerResponseTimeStats(arg0, arg1 string, arg2 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPartnerResponseTimeStats", arg0, arg1, arg2) +} + +// RecordPartnerResponseTimeStats indicates an expected call of RecordPartnerResponseTimeStats +func (mr *MockMetricsEngineMockRecorder) RecordPartnerResponseTimeStats(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerResponseTimeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerResponseTimeStats), arg0, arg1, arg2) +} + +// RecordPartnerTimeoutErrorStats mocks base method +func (m *MockMetricsEngine) RecordPartnerTimeoutErrorStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPartnerTimeoutErrorStats", arg0, arg1) +} + +// RecordPartnerTimeoutErrorStats indicates an expected call of RecordPartnerTimeoutErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordPartnerTimeoutErrorStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerTimeoutErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerTimeoutErrorStats), arg0, arg1) +} + +// RecordPartnerTimeoutInPBS mocks base method +func (m *MockMetricsEngine) RecordPartnerTimeoutInPBS(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPartnerTimeoutInPBS", arg0, arg1, arg2) +} + +// RecordPartnerTimeoutInPBS indicates an expected call of RecordPartnerTimeoutInPBS +func (mr *MockMetricsEngineMockRecorder) RecordPartnerTimeoutInPBS(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerTimeoutInPBS", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerTimeoutInPBS), arg0, arg1, arg2) +} + +// RecordPlatformPublisherPartnerReqStats mocks base method +func (m *MockMetricsEngine) RecordPlatformPublisherPartnerReqStats(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPlatformPublisherPartnerReqStats", arg0, arg1, arg2) +} + +// RecordPlatformPublisherPartnerReqStats indicates an expected call of RecordPlatformPublisherPartnerReqStats +func (mr *MockMetricsEngineMockRecorder) RecordPlatformPublisherPartnerReqStats(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPlatformPublisherPartnerReqStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPlatformPublisherPartnerReqStats), arg0, arg1, arg2) +} + +// RecordPlatformPublisherPartnerResponseStats mocks base method +func (m *MockMetricsEngine) RecordPlatformPublisherPartnerResponseStats(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPlatformPublisherPartnerResponseStats", arg0, arg1, arg2) +} + +// RecordPlatformPublisherPartnerResponseStats indicates an expected call of RecordPlatformPublisherPartnerResponseStats +func (mr *MockMetricsEngineMockRecorder) RecordPlatformPublisherPartnerResponseStats(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPlatformPublisherPartnerResponseStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPlatformPublisherPartnerResponseStats), arg0, arg1, arg2) +} + +// RecordPreProcessingTimeStats mocks base method +func (m *MockMetricsEngine) RecordPreProcessingTimeStats(arg0 string, arg1 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPreProcessingTimeStats", arg0, arg1) +} + +// RecordPreProcessingTimeStats indicates an expected call of RecordPreProcessingTimeStats +func (mr *MockMetricsEngineMockRecorder) RecordPreProcessingTimeStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPreProcessingTimeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPreProcessingTimeStats), arg0, arg1) +} + +// RecordPrebidTimeoutRequests mocks base method +func (m *MockMetricsEngine) RecordPrebidTimeoutRequests(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPrebidTimeoutRequests", arg0, arg1) +} + +// RecordPrebidTimeoutRequests indicates an expected call of RecordPrebidTimeoutRequests +func (mr *MockMetricsEngineMockRecorder) RecordPrebidTimeoutRequests(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPrebidTimeoutRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPrebidTimeoutRequests), arg0, arg1) +} + +// RecordPublisherInvalidProfileImpressions mocks base method +func (m *MockMetricsEngine) RecordPublisherInvalidProfileImpressions(arg0, arg1 string, arg2 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherInvalidProfileImpressions", arg0, arg1, arg2) +} + +// RecordPublisherInvalidProfileImpressions indicates an expected call of RecordPublisherInvalidProfileImpressions +func (mr *MockMetricsEngineMockRecorder) RecordPublisherInvalidProfileImpressions(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherInvalidProfileImpressions", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherInvalidProfileImpressions), arg0, arg1, arg2) +} + +// RecordPublisherInvalidProfileRequests mocks base method +func (m *MockMetricsEngine) RecordPublisherInvalidProfileRequests(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherInvalidProfileRequests", arg0, arg1, arg2) +} + +// RecordPublisherInvalidProfileRequests indicates an expected call of RecordPublisherInvalidProfileRequests +func (mr *MockMetricsEngineMockRecorder) RecordPublisherInvalidProfileRequests(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherInvalidProfileRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherInvalidProfileRequests), arg0, arg1, arg2) +} + +// RecordPublisherNoConsentImpressions mocks base method +func (m *MockMetricsEngine) RecordPublisherNoConsentImpressions(arg0 string, arg1 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherNoConsentImpressions", arg0, arg1) +} + +// RecordPublisherNoConsentImpressions indicates an expected call of RecordPublisherNoConsentImpressions +func (mr *MockMetricsEngineMockRecorder) RecordPublisherNoConsentImpressions(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherNoConsentImpressions", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherNoConsentImpressions), arg0, arg1) +} + +// RecordPublisherNoConsentRequests mocks base method +func (m *MockMetricsEngine) RecordPublisherNoConsentRequests(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherNoConsentRequests", arg0) +} + +// RecordPublisherNoConsentRequests indicates an expected call of RecordPublisherNoConsentRequests +func (mr *MockMetricsEngineMockRecorder) RecordPublisherNoConsentRequests(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherNoConsentRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherNoConsentRequests), arg0) +} + +// RecordPublisherPartnerImpStats mocks base method +func (m *MockMetricsEngine) RecordPublisherPartnerImpStats(arg0, arg1 string, arg2 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherPartnerImpStats", arg0, arg1, arg2) +} + +// RecordPublisherPartnerImpStats indicates an expected call of RecordPublisherPartnerImpStats +func (mr *MockMetricsEngineMockRecorder) RecordPublisherPartnerImpStats(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherPartnerImpStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherPartnerImpStats), arg0, arg1, arg2) +} + +// RecordPublisherPartnerNoCookieStats mocks base method +func (m *MockMetricsEngine) RecordPublisherPartnerNoCookieStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherPartnerNoCookieStats", arg0, arg1) +} + +// RecordPublisherPartnerNoCookieStats indicates an expected call of RecordPublisherPartnerNoCookieStats +func (mr *MockMetricsEngineMockRecorder) RecordPublisherPartnerNoCookieStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherPartnerNoCookieStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherPartnerNoCookieStats), arg0, arg1) +} + +// RecordPublisherPartnerStats mocks base method +func (m *MockMetricsEngine) RecordPublisherPartnerStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherPartnerStats", arg0, arg1) +} + +// RecordPublisherPartnerStats indicates an expected call of RecordPublisherPartnerStats +func (mr *MockMetricsEngineMockRecorder) RecordPublisherPartnerStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherPartnerStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherPartnerStats), arg0, arg1) +} + +// RecordPublisherProfileRequests mocks base method +func (m *MockMetricsEngine) RecordPublisherProfileRequests(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherProfileRequests", arg0, arg1) +} + +// RecordPublisherProfileRequests indicates an expected call of RecordPublisherProfileRequests +func (mr *MockMetricsEngineMockRecorder) RecordPublisherProfileRequests(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherProfileRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherProfileRequests), arg0, arg1) +} + +// RecordPublisherRequestStats mocks base method +func (m *MockMetricsEngine) RecordPublisherRequestStats(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherRequestStats", arg0) +} + +// RecordPublisherRequestStats indicates an expected call of RecordPublisherRequestStats +func (mr *MockMetricsEngineMockRecorder) RecordPublisherRequestStats(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherRequestStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherRequestStats), arg0) +} + +// RecordPublisherRequests mocks base method +func (m *MockMetricsEngine) RecordPublisherRequests(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherRequests", arg0, arg1, arg2) +} + +// RecordPublisherRequests indicates an expected call of RecordPublisherRequests +func (mr *MockMetricsEngineMockRecorder) RecordPublisherRequests(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherRequests), arg0, arg1, arg2) +} + +// RecordPublisherResponseEncodingErrorStats mocks base method +func (m *MockMetricsEngine) RecordPublisherResponseEncodingErrorStats(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherResponseEncodingErrorStats", arg0) +} + +// RecordPublisherResponseEncodingErrorStats indicates an expected call of RecordPublisherResponseEncodingErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordPublisherResponseEncodingErrorStats(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherResponseEncodingErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherResponseEncodingErrorStats), arg0) +} + +// RecordPublisherResponseTimeStats mocks base method +func (m *MockMetricsEngine) RecordPublisherResponseTimeStats(arg0 string, arg1 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherResponseTimeStats", arg0, arg1) +} + +// RecordPublisherResponseTimeStats indicates an expected call of RecordPublisherResponseTimeStats +func (mr *MockMetricsEngineMockRecorder) RecordPublisherResponseTimeStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherResponseTimeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherResponseTimeStats), arg0, arg1) +} + +// RecordPublisherWrapperLoggerFailure mocks base method +func (m *MockMetricsEngine) RecordPublisherWrapperLoggerFailure(arg0, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPublisherWrapperLoggerFailure", arg0, arg1, arg2) +} + +// RecordPublisherWrapperLoggerFailure indicates an expected call of RecordPublisherWrapperLoggerFailure +func (mr *MockMetricsEngineMockRecorder) RecordPublisherWrapperLoggerFailure(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherWrapperLoggerFailure", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherWrapperLoggerFailure), arg0, arg1, arg2) +} + +// RecordReqImpsWithAppContentCount mocks base method +func (m *MockMetricsEngine) RecordReqImpsWithAppContentCount(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordReqImpsWithAppContentCount", arg0) +} + +// RecordReqImpsWithAppContentCount indicates an expected call of RecordReqImpsWithAppContentCount +func (mr *MockMetricsEngineMockRecorder) RecordReqImpsWithAppContentCount(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordReqImpsWithAppContentCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordReqImpsWithAppContentCount), arg0) +} + +// RecordReqImpsWithSiteContentCount mocks base method +func (m *MockMetricsEngine) RecordReqImpsWithSiteContentCount(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordReqImpsWithSiteContentCount", arg0) +} + +// RecordReqImpsWithSiteContentCount indicates an expected call of RecordReqImpsWithSiteContentCount +func (mr *MockMetricsEngineMockRecorder) RecordReqImpsWithSiteContentCount(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordReqImpsWithSiteContentCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordReqImpsWithSiteContentCount), arg0) +} + +// RecordRequestAdPodGeneratedImpressionsCount mocks base method +func (m *MockMetricsEngine) RecordRequestAdPodGeneratedImpressionsCount(arg0 int, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordRequestAdPodGeneratedImpressionsCount", arg0, arg1) +} + +// RecordRequestAdPodGeneratedImpressionsCount indicates an expected call of RecordRequestAdPodGeneratedImpressionsCount +func (mr *MockMetricsEngineMockRecorder) RecordRequestAdPodGeneratedImpressionsCount(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequestAdPodGeneratedImpressionsCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequestAdPodGeneratedImpressionsCount), arg0, arg1) +} + +// RecordSSTimeoutRequests mocks base method +func (m *MockMetricsEngine) RecordSSTimeoutRequests(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordSSTimeoutRequests", arg0, arg1) +} + +// RecordSSTimeoutRequests indicates an expected call of RecordSSTimeoutRequests +func (mr *MockMetricsEngineMockRecorder) RecordSSTimeoutRequests(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordSSTimeoutRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordSSTimeoutRequests), arg0, arg1) +} + +// RecordSlotNotMappedErrorStats mocks base method +func (m *MockMetricsEngine) RecordSlotNotMappedErrorStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordSlotNotMappedErrorStats", arg0, arg1) +} + +// RecordSlotNotMappedErrorStats indicates an expected call of RecordSlotNotMappedErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordSlotNotMappedErrorStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordSlotNotMappedErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordSlotNotMappedErrorStats), arg0, arg1) +} + +// RecordStatsKeyCTVPrebidFailedImpression mocks base method +func (m *MockMetricsEngine) RecordStatsKeyCTVPrebidFailedImpression(arg0 int, arg1, arg2 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordStatsKeyCTVPrebidFailedImpression", arg0, arg1, arg2) +} + +// RecordStatsKeyCTVPrebidFailedImpression indicates an expected call of RecordStatsKeyCTVPrebidFailedImpression +func (mr *MockMetricsEngineMockRecorder) RecordStatsKeyCTVPrebidFailedImpression(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordStatsKeyCTVPrebidFailedImpression", reflect.TypeOf((*MockMetricsEngine)(nil).RecordStatsKeyCTVPrebidFailedImpression), arg0, arg1, arg2) +} + +// RecordUidsCookieNotPresentErrorStats mocks base method +func (m *MockMetricsEngine) RecordUidsCookieNotPresentErrorStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordUidsCookieNotPresentErrorStats", arg0, arg1) +} + +// RecordUidsCookieNotPresentErrorStats indicates an expected call of RecordUidsCookieNotPresentErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordUidsCookieNotPresentErrorStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordUidsCookieNotPresentErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordUidsCookieNotPresentErrorStats), arg0, arg1) +} + +// RecordUnkownPrebidErrorStats mocks base method +func (m *MockMetricsEngine) RecordUnkownPrebidErrorStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordUnkownPrebidErrorStats", arg0, arg1) +} + +// RecordUnkownPrebidErrorStats indicates an expected call of RecordUnkownPrebidErrorStats +func (mr *MockMetricsEngineMockRecorder) RecordUnkownPrebidErrorStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordUnkownPrebidErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordUnkownPrebidErrorStats), arg0, arg1) +} + +// RecordVideoImpDisabledViaConnTypeStats mocks base method +func (m *MockMetricsEngine) RecordVideoImpDisabledViaConnTypeStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordVideoImpDisabledViaConnTypeStats", arg0, arg1) +} + +// RecordVideoImpDisabledViaConnTypeStats indicates an expected call of RecordVideoImpDisabledViaConnTypeStats +func (mr *MockMetricsEngineMockRecorder) RecordVideoImpDisabledViaConnTypeStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordVideoImpDisabledViaConnTypeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordVideoImpDisabledViaConnTypeStats), arg0, arg1) +} + +// RecordVideoInstlImpsStats mocks base method +func (m *MockMetricsEngine) RecordVideoInstlImpsStats(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordVideoInstlImpsStats", arg0, arg1) +} + +// RecordVideoInstlImpsStats indicates an expected call of RecordVideoInstlImpsStats +func (mr *MockMetricsEngineMockRecorder) RecordVideoInstlImpsStats(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordVideoInstlImpsStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordVideoInstlImpsStats), arg0, arg1) +} + +// Shutdown mocks base method +func (m *MockMetricsEngine) Shutdown() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Shutdown") +} + +// Shutdown indicates an expected call of Shutdown +func (mr *MockMetricsEngineMockRecorder) Shutdown() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockMetricsEngine)(nil).Shutdown)) +} diff --git a/modules/pubmatic/openwrap/metrics/stats/config.go b/modules/pubmatic/openwrap/metrics/stats/config.go new file mode 100644 index 00000000000..1b60c388e12 --- /dev/null +++ b/modules/pubmatic/openwrap/metrics/stats/config.go @@ -0,0 +1,18 @@ +package stats + +type Stats struct { + UseHostName bool // if true use actual_node_name:actual_pod_name into stats key + DefaultHostName string // combination of node:pod, default value is N:P + Endpoint string // stat-server's endpoint + PublishInterval int // interval (in minutes) to publish stats to server + PublishThreshold int // publish stats if number of stat-records present in map is higher than this threshold + Retries int // max retries to publish stats to server + DialTimeout int // http connection dial-timeout (in seconds) + KeepAliveDuration int // http connection keep-alive-duration (in minutes) + MaxIdleConnections int // maximum idle connections across all hosts + MaxIdleConnectionsPerHost int // maximum idle connections per host + ResponseHeaderTimeout int // amount of time (in seconds) to wait for server's response header + MaxChannelLength int // max number of allowed stat keys + PoolMaxWorkers int // max number of workers that will actually send the data to stats-server + PoolMaxCapacity int // number of tasks that can be hold by the pool +} diff --git a/modules/pubmatic/openwrap/metrics/stats/constants.go b/modules/pubmatic/openwrap/metrics/stats/constants.go index 361e552a7f7..5ee89d2b822 100644 --- a/modules/pubmatic/openwrap/metrics/stats/constants.go +++ b/modules/pubmatic/openwrap/metrics/stats/constants.go @@ -24,15 +24,6 @@ const ( //statsKeyOpenWrapServerPanic stats Key for Server Panic Hits statsKeyOpenWrapServerPanic = iota - //statsKeyPublisherNoConsentRequests stats Key for Counting requests for Publisher with no GDPR consent request respective publisher - statsKeyPublisherNoConsentRequests - - //statsKeyPublisherNoConsentImpressions stats Key for Counting number of impressions lost in request due to no GDPR consent for respective publisher - statsKeyPublisherNoConsentImpressions - - //statsKeyPublisherPrebidRequests stats Key to count Requests to Prebid Server for respective publisher - statsKeyPublisherPrebidRequests - //statsKeyNobidErrPrebidServerRequests stats Key to count Prebid Server Requests with No AdUnit for respective publisher statsKeyNobidErrPrebidServerRequests @@ -69,12 +60,6 @@ const ( //statsKeyVideoImpDisabledViaConnType stats Key for Counting video interstitial impressions that are disabled because of connection type for a publisher/profile statsKeyVideoImpDisabledViaConnType - //statsKeyPublisherPartnerRequests stats Key for counting Publisher Partner level Requests - statsKeyPublisherPartnerRequests - - //statsKeyPublisherPartnerImpressions stats Key for counting Publisher Partner level Impressions - statsKeyPublisherPartnerImpressions - //statsKeyPublisherPartnerNoCookieRequests stats Key for counting requests without cookie at Publisher Partner level statsKeyPublisherPartnerNoCookieRequests @@ -93,9 +78,6 @@ const ( //statsKeyNobidErrorRequests stats Key for counting No Bid cases from respective partner statsKeyNobidErrorRequests - //statsKeyNobidderStatusErrorRequests stats Key for counting No Bidders Status present in Prebid Server response - statsKeyNobidderStatusErrorRequests - //statsKeyLoggerErrorRequests stats Key for counting number of Wrapper logger failures for a given publisher,profile and version statsKeyLoggerErrorRequests @@ -205,23 +187,16 @@ const ( statsKeyCTVHTTPMethodRequests //statsKeyCTVValidationDetail for tracking error with granularity statsKeyCTVValidationErr - //statsKeyIncompleteAdPods for tracking incomplete AdPods because of any reason - statsKeyIncompleteAdPods //statsKeyCTVReqImpstWithConfig for tracking requests that had config and were not overwritten by database config statsKeyCTVReqImpstWithConfig //statsKeyTotalAdPodImpression for tracking no of AdPod impressions statsKeyTotalAdPodImpression //statsKeyAdPodSecondsMissed for tracking no pf seconds that were missed because of our algos statsKeyReqTotalAdPodImpression - //statsKeyReqAdPodSecondsMissed for tracking no pf seconds that were missed because of our algos - statsKeyAdPodSecondsMissed //statsKeyReqImpDurationYield is for tracking the number on adpod impressions generated for give min and max request imp durations statsKeyReqImpDurationYield //statsKeyReqWithAdPodCount if for counting requests with AdPods statsKeyReqWithAdPodCount - //statsKeyBidDuration for counting number of bids of video duration - statsKeyBidDuration - //statsKeyPBSAuctionRequests stats Key for counting PBS Auction endpoint Requests statsKeyPBSAuctionRequests diff --git a/modules/pubmatic/openwrap/metrics/stats/init.go b/modules/pubmatic/openwrap/metrics/stats/init.go index 0cead3602ea..e963e6f3df0 100644 --- a/modules/pubmatic/openwrap/metrics/stats/init.go +++ b/modules/pubmatic/openwrap/metrics/stats/init.go @@ -44,15 +44,6 @@ func initStatKeys(defaultServerName, actualServerName string) { statKeys[statsKeyOpenWrapServerPanic] = "hb:panic:" + actualServerName //hb:panic: - //publisher level stats - statKeys[statsKeyPublisherNoConsentRequests] = "hb:pubnocnsreq:%s:" + defaultServerName - //hb:pubnocnsreq:: - - statKeys[statsKeyPublisherNoConsentImpressions] = "hb:pubnocnsimp:%s:" + defaultServerName - //hb:pubnocnsimp:: - - statKeys[statsKeyPublisherPrebidRequests] = "hb:pubrq:%s:" + defaultServerName - // statKeys[statsKeyNobidErrPrebidServerRequests] = "hb:pubnbreq:%s:", SendThresh: criticalThreshold, SendTimeInterval: time.Minute * time.Duration(criticalInterval)} statKeys[statsKeyNobidErrPrebidServerRequests] = "hb:pubnbreq:%s:" + defaultServerName //hb:pubnbreq:: @@ -91,13 +82,6 @@ func initStatKeys(defaultServerName, actualServerName string) { statKeys[statsKeyVideoImpDisabledViaConnType] = "hb:ppdisimpct:%s:%s:" + defaultServerName //hb:ppdisimpct::: - //publisher-partner level stats - statKeys[statsKeyPublisherPartnerRequests] = "hb:pprq:%s:%s:" + defaultServerName - //hb:pprq::: - - statKeys[statsKeyPublisherPartnerImpressions] = "hb:ppimp:%s:%s:" + defaultServerName - //hb:ppimp::: - statKeys[statsKeyPublisherPartnerNoCookieRequests] = "hb:ppnc:%s:%s:" + defaultServerName //hb:ppnc::: @@ -116,9 +100,6 @@ func initStatKeys(defaultServerName, actualServerName string) { statKeys[statsKeyNobidErrorRequests] = "hb:nber:%s:%s:" + defaultServerName //hb:nber::: - statKeys[statsKeyNobidderStatusErrorRequests] = "hb:nbse:%s:%s:" + defaultServerName - //hb:nbse::: - statKeys[statsKeyLoggerErrorRequests] = "hb:wle:%s:%s:%s:" + defaultServerName //hb:nber:::: @@ -252,9 +233,6 @@ func initStatKeys(defaultServerName, actualServerName string) { statKeys[statsKeyCTVValidationErr] = "hb:lfv:ivr:%d:%s:" + defaultServerName //hb:lfv:ivr::: - statKeys[statsKeyIncompleteAdPods] = "hb:lfv:nip:%s:%s:" + defaultServerName - //hb:lfv:nip::: - statKeys[statsKeyCTVReqImpstWithConfig] = "hb:lfv:rwc:%s:%s:" + defaultServerName //hb:lfv:rwc::: @@ -264,18 +242,12 @@ func initStatKeys(defaultServerName, actualServerName string) { statKeys[statsKeyReqTotalAdPodImpression] = "hb:lfv:rtpi:%s:" + defaultServerName //hb:lfv:rtpi:: - statKeys[statsKeyAdPodSecondsMissed] = "hb:lfv:sm:%s:" + defaultServerName - //hb:lfv:sm:: - statKeys[statsKeyReqImpDurationYield] = "hb:lfv:impy:%d:%d:%s:" + defaultServerName //hb:lfv:impy:::: statKeys[statsKeyReqWithAdPodCount] = "hb:lfv:rwap:%s:%s:" + defaultServerName //hb:lfv:rwap::: - statKeys[statsKeyBidDuration] = "hb:lfv:dur:%d:%s:%s:" + defaultServerName - //hb:lfv:dur::::: - statKeys[statsKeyPBSAuctionRequests] = "hb:pbs:auc:" + defaultServerName //hb:pbs:auc: - no of PBS auction endpoint requests diff --git a/modules/pubmatic/openwrap/metrics/stats/init_test.go b/modules/pubmatic/openwrap/metrics/stats/init_test.go index 49a023f89f0..92aea299b25 100644 --- a/modules/pubmatic/openwrap/metrics/stats/init_test.go +++ b/modules/pubmatic/openwrap/metrics/stats/init_test.go @@ -30,9 +30,6 @@ func TestInitStatKeys(t *testing.T) { want: want{ testKeys: [maxNumOfStats]string{ "hb:panic:sv3:node123.sv3:ssheaderbidding", - "hb:pubnocnsreq:%s:sv3:N:P", - "hb:pubnocnsimp:%s:sv3:N:P", - "hb:pubrq:%s:sv3:N:P", "hb:pubnbreq:%s:sv3:N:P", "hb:pubnbres:%s:sv3:N:P", "hb:cnt:%s:%s:sv3:N:P", @@ -45,15 +42,12 @@ func TestInitStatKeys(t *testing.T) { "hb:ppvidinstlimps:%s:%s:sv3:N:P", "hb:ppdisimpcfg:%s:%s:sv3:N:P", "hb:ppdisimpct:%s:%s:sv3:N:P", - "hb:pprq:%s:%s:sv3:N:P", - "hb:ppimp:%s:%s:sv3:N:P", "hb:ppnc:%s:%s:sv3:N:P", "hb:sler:%s:%s:sv3:N:P", "hb:cfer:%s:%s:sv3:N:P", "hb:toer:%s:%s:sv3:N:P", "hb:uner:%s:%s:sv3:N:P", "hb:nber:%s:%s:sv3:N:P", - "hb:nbse:%s:%s:sv3:N:P", "hb:wle:%s:%s:%s:sv3:N:P", "hb:2.4:%s:pbrq:%s:sv3:N:P", "hb:2.5:badreq:sv3:N:P", @@ -96,14 +90,11 @@ func TestInitStatKeys(t *testing.T) { "hb:lfv:%v:%v:pbrq:%v:sv3:N:P", "hb:lfv:%v:mtd:%v:%v:sv3:N:P", "hb:lfv:ivr:%d:%s:sv3:N:P", - "hb:lfv:nip:%s:%s:sv3:N:P", "hb:lfv:rwc:%s:%s:sv3:N:P", "hb:lfv:tpi:%s:%s:sv3:N:P", "hb:lfv:rtpi:%s:sv3:N:P", - "hb:lfv:sm:%s:sv3:N:P", "hb:lfv:impy:%d:%d:%s:sv3:N:P", "hb:lfv:rwap:%s:%s:sv3:N:P", - "hb:lfv:dur:%d:%s:%s:sv3:N:P", "hb:pbs:auc:sv3:N:P", "hb:mistrack:%s:%s:%s:sv3:N:P", "hb:pbs:dbc:%s:%s:%s:%s:sv3:N:P", diff --git a/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go b/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go index b2372fa954a..566132369c6 100644 --- a/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go +++ b/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go @@ -42,14 +42,6 @@ func (st *StatsTCP) RecordOpenWrapServerPanicStats() { st.statsClient.PublishStat(statKeys[statsKeyOpenWrapServerPanic], 1) } -func (st *StatsTCP) RecordPublisherPartnerStats(publisher, partner string) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyPublisherPartnerRequests], publisher, partner), 1) -} - -func (st *StatsTCP) RecordPublisherPartnerImpStats(publisher, partner string, impCount int) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyPublisherPartnerImpressions], publisher, partner), impCount) -} - func (st *StatsTCP) RecordPublisherPartnerNoCookieStats(publisher, partner string) { st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyPublisherPartnerNoCookieRequests], publisher, partner), 1) } @@ -58,10 +50,6 @@ func (st *StatsTCP) RecordPartnerTimeoutErrorStats(publisher, partner string) { st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyPartnerTimeoutErrorRequests], publisher, partner), 1) } -func (st *StatsTCP) RecordNobiderStatusErrorStats(publisher, partner string) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyNobidderStatusErrorRequests], publisher, partner), 1) -} - func (st *StatsTCP) RecordNobidErrorStats(publisher, partner string) { st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyNobidErrorRequests], publisher, partner), 1) } @@ -99,18 +87,6 @@ func (st *StatsTCP) RecordPublisherInvalidProfileImpressions(publisher, profileI //TODO @viral ;previously by 1 but now by impCount } -func (st *StatsTCP) RecordPublisherNoConsentRequests(publisher string) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyPublisherNoConsentRequests], publisher), 1) -} - -func (st *StatsTCP) RecordPublisherNoConsentImpressions(publisher string, impCount int) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyPublisherNoConsentImpressions], publisher), impCount) -} - -func (st *StatsTCP) RecordPublisherRequestStats(publisher string) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyPublisherPrebidRequests], publisher), 1) -} - func (st *StatsTCP) RecordNobidErrPrebidServerRequests(publisher string) { st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyNobidErrPrebidServerRequests], publisher), 1) } @@ -224,10 +200,6 @@ func (st *StatsTCP) RecordCTVInvalidReasonCount(errorCode int, publisher string) st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyCTVValidationErr], errorCode, publisher), 1) } -func (st *StatsTCP) RecordCTVIncompleteAdPodsCount(impCount int, reason string, publisher string) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyIncompleteAdPods], reason, publisher), 1) -} - func (st *StatsTCP) RecordCTVReqImpsWithDbConfigCount(publisher string) { st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyCTVReqImpstWithConfig], "db", publisher), 1) } @@ -254,10 +226,6 @@ func (st *StatsTCP) RecordRequestAdPodGeneratedImpressionsCount(impCount int, pu st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyReqTotalAdPodImpression], publisher), impCount) } -func (st *StatsTCP) RecordAdPodSecondsMissedCount(seconds int, publisher string) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyAdPodSecondsMissed], publisher), seconds) -} - func (st *StatsTCP) RecordReqImpsWithAppContentCount(publisher string) { st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyContentObjectPresent], "app", publisher), 1) } @@ -274,10 +242,6 @@ func (st *StatsTCP) RecordCTVReqCountWithAdPod(publisherID, profileID string) { st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyReqWithAdPodCount], publisherID, profileID), 1) } -func (st *StatsTCP) RecordCTVKeyBidDuration(duration int, publisherID, profileID string) { - st.statsClient.PublishStat(fmt.Sprintf(statKeys[statsKeyBidDuration], duration, publisherID, profileID), 1) -} - func (st *StatsTCP) RecordPBSAuctionRequestsStats() { st.statsClient.PublishStat(statKeys[statsKeyPBSAuctionRequests], 1) } @@ -356,3 +320,7 @@ func getStatsKeyIndexForResponseTime(responseTime int) int { } return statKey } + +func (st *StatsTCP) Shutdown() { + st.statsClient.ShutdownProcess() +} diff --git a/modules/pubmatic/openwrap/metrics/stats/tcp_stats_test.go b/modules/pubmatic/openwrap/metrics/stats/tcp_stats_test.go index 71f685d4d2b..84a95539ed6 100644 --- a/modules/pubmatic/openwrap/metrics/stats/tcp_stats_test.go +++ b/modules/pubmatic/openwrap/metrics/stats/tcp_stats_test.go @@ -150,44 +150,6 @@ func TestRecordFunctions(t *testing.T) { st.RecordOpenWrapServerPanicStats() }, }, - { - name: "RecordPublisherPartnerStats", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 1), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyPublisherPartnerRequests], "5890", "pubmatic"): 1, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordPublisherPartnerStats("5890", "pubmatic") - }, - }, - { - name: "RecordPublisherPartnerImpStats", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 1), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyPublisherPartnerImpressions], "5890", "pubmatic"): 10, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordPublisherPartnerImpStats("5890", "pubmatic", 10) - }, - }, { name: "RecordPublisherPartnerNoCookieStats", args: args{ @@ -226,25 +188,6 @@ func TestRecordFunctions(t *testing.T) { st.RecordPartnerTimeoutErrorStats("5890", "pubmatic") }, }, - { - name: "RecordNobiderStatusErrorStats", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 1), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyNobidderStatusErrorRequests], "5890", "pubmatic"): 1, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordNobiderStatusErrorStats("5890", "pubmatic") - }, - }, { name: "RecordNobidErrorStats", args: args{ @@ -382,63 +325,6 @@ func TestRecordFunctions(t *testing.T) { st.RecordPublisherInvalidProfileImpressions("5890", "pubmatic", 10) }, }, - { - name: "RecordPublisherNoConsentRequests", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 1), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyPublisherNoConsentRequests], "5890"): 1, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordPublisherNoConsentRequests("5890") - }, - }, - { - name: "RecordPublisherNoConsentImpressions", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 1), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyPublisherNoConsentImpressions], "5890"): 11, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordPublisherNoConsentImpressions("5890", 11) - }, - }, - { - name: "RecordPublisherRequestStats", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 1), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyPublisherPrebidRequests], "5890"): 1, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordPublisherRequestStats("5890") - }, - }, { name: "RecordNobidErrPrebidServerRequests", args: args{ @@ -912,25 +798,6 @@ func TestRecordFunctions(t *testing.T) { st.RecordCTVInvalidReasonCount(100, "5890") }, }, - { - name: "RecordCTVIncompleteAdPodsCount", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 5), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyIncompleteAdPods], "reason", "5890"): 1, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordCTVIncompleteAdPodsCount(1, "reason", "5890") - }, - }, { name: "RecordCTVReqImpsWithDbConfigCount", args: args{ @@ -994,25 +861,6 @@ func TestRecordFunctions(t *testing.T) { st.RecordAdPodGeneratedImpressionsCount(11, "5890") }, }, - { - name: "RecordAdPodSecondsMissedCount", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 4), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyAdPodSecondsMissed], "5890"): 3, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordAdPodSecondsMissedCount(3, "5890") - }, - }, { name: "RecordRequestAdPodGeneratedImpressionsCount", args: args{ @@ -1108,25 +956,6 @@ func TestRecordFunctions(t *testing.T) { st.RecordCTVReqCountWithAdPod("5890", "1234") }, }, - { - name: "RecordCTVKeyBidDuration", - args: args{ - statTCP: &StatsTCP{ - &Client{ - pubChan: make(chan stat, 1), - }, - }, - }, - want: want{ - expectedkeyVal: map[string]int{ - fmt.Sprintf(statKeys[statsKeyBidDuration], 10, "5890", "1234"): 1, - }, - channelSize: 1, - }, - callRecord: func(st *StatsTCP) { - st.RecordCTVKeyBidDuration(10, "5890", "1234") - }, - }, { name: "RecordPBSAuctionRequestsStats", args: args{ diff --git a/modules/pubmatic/openwrap/models/nbr/codes.go b/modules/pubmatic/openwrap/models/nbr/codes.go index 0f5bb0a2636..984bf16aa1b 100644 --- a/modules/pubmatic/openwrap/models/nbr/codes.go +++ b/modules/pubmatic/openwrap/models/nbr/codes.go @@ -20,4 +20,5 @@ const ( ServerSidePartnerNotConfigured AllSlotsDisabled InvalidVideoRequest + InvalidPlatform ) diff --git a/modules/pubmatic/openwrap/models/openwrap.go b/modules/pubmatic/openwrap/models/openwrap.go index bf24a72277c..0adaba23ee1 100644 --- a/modules/pubmatic/openwrap/models/openwrap.go +++ b/modules/pubmatic/openwrap/models/openwrap.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/prebid/openrtb/v19/openrtb2" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" ) @@ -69,6 +70,10 @@ type RequestCtx struct { NoSeatBids map[string]map[string][]openrtb2.Bid BidderResponseTimeMillis map[string]int + + Endpoint string + PubIDStr, ProfileIDStr string // TODO: remove this once we completely move away from header-bidding + MetricsEngine metrics.MetricsEngine } type OwBid struct { diff --git a/modules/pubmatic/openwrap/models/utils.go b/modules/pubmatic/openwrap/models/utils.go index 705534dd020..8d2da05ae57 100644 --- a/modules/pubmatic/openwrap/models/utils.go +++ b/modules/pubmatic/openwrap/models/utils.go @@ -12,8 +12,15 @@ import ( "strings" "github.com/buger/jsonparser" + "github.com/prebid/prebid-server/usersync" ) +var SyncerMap map[string]usersync.Syncer + +func SetSyncerMap(s map[string]usersync.Syncer) { + SyncerMap = s +} + // IsCTVAPIRequest will return true if reqAPI is from CTV EndPoint func IsCTVAPIRequest(api string) bool { return api == "/video/json" || api == "/video/vast" || api == "/video/openrtb" diff --git a/modules/pubmatic/openwrap/module.go b/modules/pubmatic/openwrap/module.go index bbf43136e7f..19dba0fefe5 100644 --- a/modules/pubmatic/openwrap/module.go +++ b/modules/pubmatic/openwrap/module.go @@ -24,6 +24,7 @@ func (m OpenWrap) HandleEntrypointHook( ) (hookstage.HookResult[hookstage.EntrypointPayload], error) { defer func() { if r := recover(); r != nil { + m.metricEngine.RecordOpenWrapServerPanicStats() glog.Error("body:" + string(payload.Body) + ". stacktrace:" + string(debug.Stack())) } }() @@ -39,6 +40,7 @@ func (m OpenWrap) HandleBeforeValidationHook( ) (hookstage.HookResult[hookstage.BeforeValidationRequestPayload], error) { defer func() { if r := recover(); r != nil { + m.metricEngine.RecordOpenWrapServerPanicStats() request, err := json.Marshal(payload) if err != nil { glog.Error("request:" + string(request) + ". err: " + err.Error() + ". stacktrace:" + string(debug.Stack())) @@ -58,6 +60,7 @@ func (m OpenWrap) HandleAuctionResponseHook( ) (hookstage.HookResult[hookstage.AuctionResponsePayload], error) { defer func() { if r := recover(); r != nil { + m.metricEngine.RecordOpenWrapServerPanicStats() response, err := json.Marshal(payload) if err != nil { glog.Error("response:" + string(response) + ". err: " + err.Error() + ". stacktrace:" + string(debug.Stack())) diff --git a/modules/pubmatic/openwrap/openwrap.go b/modules/pubmatic/openwrap/openwrap.go index 2ef08b3dc38..e6ad235d6c5 100644 --- a/modules/pubmatic/openwrap/openwrap.go +++ b/modules/pubmatic/openwrap/openwrap.go @@ -16,6 +16,8 @@ import ( ow_gocache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/gocache" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/database/mysql" + metrics "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics" + metrics_cfg "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/config" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" ) @@ -24,8 +26,9 @@ const ( ) type OpenWrap struct { - cfg config.Config - cache cache.Cache + cfg config.Config + cache cache.Cache + metricEngine metrics.MetricsEngine } func initOpenWrap(rawCfg json.RawMessage, _ moduledeps.ModuleDeps) (OpenWrap, error) { @@ -55,9 +58,15 @@ func initOpenWrap(rawCfg json.RawMessage, _ moduledeps.ModuleDeps) (OpenWrap, er return OpenWrap{}, errors.New("error while initializing bidder params") } + metricEngine, err := metrics_cfg.NewMetricsEngine(cfg) + if err != nil { + return OpenWrap{}, fmt.Errorf("error while initializing metrics-engine: %v", err) + } + return OpenWrap{ - cfg: cfg, - cache: ow_gocache.New(cache, db, cfg.Cache), + cfg: cfg, + cache: ow_gocache.New(cache, db, cfg.Cache), + metricEngine: &metricEngine, }, nil } diff --git a/modules/pubmatic/openwrap/tracker/inject.go b/modules/pubmatic/openwrap/tracker/inject.go index fc11bd93d95..f57bfd0b1f0 100644 --- a/modules/pubmatic/openwrap/tracker/inject.go +++ b/modules/pubmatic/openwrap/tracker/inject.go @@ -12,6 +12,7 @@ func InjectTrackers(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) ( var errs error for i, seatBid := range bidResponse.SeatBid { for j, bid := range seatBid.Bid { + var errMsg string tracker := rctx.Trackers[bid.ID] adformat := tracker.BidType if rctx.Platform == models.PLATFORM_VIDEO { @@ -27,15 +28,22 @@ func InjectTrackers(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) ( // trackers = append(trackers, tracker) // } trackers := []models.OWTracker{tracker} + var err error bidResponse.SeatBid[i].Bid[j].AdM, err = injectVideoCreativeTrackers(bid, trackers) if err != nil { - errs = errors.Wrap(errs, fmt.Sprintf("failed to inject tracker for bidid %s with error %s", bid.ID, err.Error())) + errMsg = fmt.Sprintf("failed to inject tracker for bidid %s with error %s", bid.ID, err.Error()) } case models.Native: default: - errs = errors.Wrap(errs, fmt.Sprintf("Invalid adformat %s for bidid %s", adformat, bid.ID)) + errMsg = fmt.Sprintf("Invalid adformat %s for bidid %s", adformat, bid.ID) + } + + if errMsg != "" { + rctx.MetricsEngine.RecordInjectTrackerErrorCount(adformat, rctx.PubIDStr, seatBid.Seat) + errs = errors.Wrap(errs, errMsg) } + } } return bidResponse, errs diff --git a/modules/pubmatic/openwrap/util.go b/modules/pubmatic/openwrap/util.go index 94c895450a6..c0eb4cf4ed7 100644 --- a/modules/pubmatic/openwrap/util.go +++ b/modules/pubmatic/openwrap/util.go @@ -1,13 +1,17 @@ package openwrap import ( + "net/http" "net/url" "os" "regexp" "strings" "github.com/prebid/openrtb/v19/openrtb2" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/adapters" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/nbr" + "github.com/prebid/prebid-server/usersync" ) var ( @@ -213,3 +217,65 @@ func getHostName() string { return serverName } + +// parseUIDCookies returns the parsed-cookie if uidCookie is nil else returns new cookie object +func parseUIDCookies(uidCookie *http.Cookie) *usersync.Cookie { + + if uidCookie != nil { + return usersync.ParseCookie(uidCookie) + } + return usersync.NewCookie() +} + +// RecordPublisherPartnerNoCookieStats parse request cookies and records the stats if cookie is not found for partner +func RecordPublisherPartnerNoCookieStats(rctx models.RequestCtx) { + + cookie := parseUIDCookies(rctx.UidCookie) + for _, partnerConfig := range rctx.PartnerConfigMap { + if partnerConfig[models.SERVER_SIDE_FLAG] == "0" { + continue + } + + partnerName := partnerConfig[models.PREBID_PARTNER_NAME] + syncer := models.SyncerMap[adapters.ResolveOWBidder(partnerName)] + if syncer != nil { + uid, _, _ := cookie.GetUID(syncer.Key()) + if uid != "" { + continue + } + } + rctx.MetricsEngine.RecordPublisherPartnerNoCookieStats(rctx.PubIDStr, partnerConfig[models.BidderCode]) + } +} + +// getPubmaticErrorCode is temporary function which returns the pubmatic specific error code for standardNBR code +func getPubmaticErrorCode(standardNBR int) int { + switch standardNBR { + case nbr.InvalidPublisherID: + return 604 // ErrMissingPublisherID + + case nbr.InvalidRequest: + return 18 // ErrBadRequest + + case nbr.InvalidProfileID: + return 700 // ErrMissingProfileID + + case nbr.AllPartnerThrottled: + return 11 // ErrAllPartnerThrottled + + case nbr.InvalidPriceGranularityConfig: + return 26 // ErrPrebidInvalidCustomPriceGranularity + + case nbr.InvalidImpressionTagID: + return 605 // ErrMissingTagID + + case nbr.InvalidProfileConfiguration, nbr.InvalidPlatform, nbr.AllSlotsDisabled, nbr.ServerSidePartnerNotConfigured: + return 6 // ErrInvalidConfiguration + + case nbr.InternalError: + return 17 // ErrInvalidImpression + + } + + return -1 +} diff --git a/modules/pubmatic/openwrap/util_test.go b/modules/pubmatic/openwrap/util_test.go new file mode 100644 index 00000000000..5ebe976dd73 --- /dev/null +++ b/modules/pubmatic/openwrap/util_test.go @@ -0,0 +1,172 @@ +package openwrap + +import ( + "net/http" + "testing" + + "github.com/golang/mock/gomock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/mock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/usersync" +) + +func TestRecordPublisherPartnerNoCookieStats(t *testing.T) { + + ctrl := gomock.NewController(t) + mockEngine := mock.NewMockMetricsEngine(ctrl) + defer ctrl.Finish() + + type args struct { + rctx models.RequestCtx + } + + tests := []struct { + name string + args args + setup func(*mock.MockMetricsEngine) + }{ + { + name: "Empty cookies and empty partner config map", + args: args{ + rctx: models.RequestCtx{}, + }, + setup: func(mme *mock.MockMetricsEngine) {}, + }, + { + name: "Non-empty cookie and empty partner config map", + args: args{ + rctx: models.RequestCtx{ + UidCookie: &http.Cookie{ + Name: "uid", + Value: "abc123", + }, + PartnerConfigMap: map[int]map[string]string{}, + }, + }, + setup: func(mme *mock.MockMetricsEngine) { + models.SyncerMap = make(map[string]usersync.Syncer) + }, + }, + { + name: "Empty cookie and non-empty partner config map", + args: args{ + rctx: models.RequestCtx{ + UidCookie: nil, + PartnerConfigMap: map[int]map[string]string{ + 1: { + models.SERVER_SIDE_FLAG: "1", + models.PREBID_PARTNER_NAME: "partner1", + models.BidderCode: "bidder1", + }, + }, + PubIDStr: "5890", + }, + }, + setup: func(mme *mock.MockMetricsEngine) { + models.SyncerMap = make(map[string]usersync.Syncer) + mme.EXPECT().RecordPublisherPartnerNoCookieStats("5890", "bidder1") + }, + }, + { + name: "Non-empty cookie and client side partner in config map", + args: args{ + rctx: models.RequestCtx{ + UidCookie: &http.Cookie{ + Name: "uid", + Value: "abc123", + }, + PartnerConfigMap: map[int]map[string]string{ + 1: { + models.SERVER_SIDE_FLAG: "0", + models.PREBID_PARTNER_NAME: "partner1", + models.BidderCode: "bidder1", + }, + }, + PubIDStr: "5890", + }, + }, + setup: func(mme *mock.MockMetricsEngine) { + models.SyncerMap = make(map[string]usersync.Syncer) + }, + }, + { + name: "Non-empty cookie and client side partner in config map", + args: args{ + rctx: models.RequestCtx{ + UidCookie: &http.Cookie{ + Name: "uid", + Value: "abc123", + }, + PartnerConfigMap: map[int]map[string]string{ + 1: { + models.SERVER_SIDE_FLAG: "0", + models.PREBID_PARTNER_NAME: "partner1", + models.BidderCode: "bidder1", + }, + }, + PubIDStr: "5890", + }, + }, + setup: func(mme *mock.MockMetricsEngine) { + models.SyncerMap = make(map[string]usersync.Syncer) + }, + }, + { + name: "GetUID returns empty uid", + args: args{ + rctx: models.RequestCtx{ + UidCookie: &http.Cookie{ + Name: "uid", + Value: "ewoJInRlbXBVSURzIjogewoJCSJwdWJtYXRpYyI6IHsKCQkJInVpZCI6ICI3RDc1RDI1Ri1GQUM5LTQ0M0QtQjJEMS1CMTdGRUUxMUUwMjciLAoJCQkiZXhwaXJlcyI6ICIyMDIyLTEwLTMxVDA5OjE0OjI1LjczNzI1Njg5OVoiCgkJfQoJfSwKCSJiZGF5IjogIjIwMjItMDUtMTdUMDY6NDg6MzguMDE3OTg4MjA2WiIKfQ==", + }, + PartnerConfigMap: map[int]map[string]string{ + 1: { + models.SERVER_SIDE_FLAG: "1", + models.PREBID_PARTNER_NAME: "pubmatic", + models.BidderCode: "pubmatic", + }, + }, + PubIDStr: "5890", + }, + }, + setup: func(mme *mock.MockMetricsEngine) { + models.SyncerMap = map[string]usersync.Syncer{ + "pubmatic": fakeSyncer{ + key: "pubmatic", + }, + } + + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup(mockEngine) + tc.args.rctx.MetricsEngine = mockEngine + RecordPublisherPartnerNoCookieStats(tc.args.rctx) + }) + } +} + +// fakeSyncer implements syncer interface for unit test cases +type fakeSyncer struct { + key string +} + +func (s fakeSyncer) Key() string { + return s.key +} + +func (s fakeSyncer) DefaultSyncType() usersync.SyncType { + return usersync.SyncType("") +} + +func (s fakeSyncer) SupportsType(syncTypes []usersync.SyncType) bool { + return false +} + +func (fakeSyncer) GetSync(syncTypes []usersync.SyncType, privacyPolicies privacy.Policies) (usersync.Sync, error) { + return usersync.Sync{}, nil +} diff --git a/router/router.go b/router/router.go index a1b3b040e5e..b6aa096b838 100644 --- a/router/router.go +++ b/router/router.go @@ -29,6 +29,7 @@ import ( metricsConf "github.com/prebid/prebid-server/metrics/config" "github.com/prebid/prebid-server/modules" "github.com/prebid/prebid-server/modules/moduledeps" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/prebid/prebid-server/openrtb_ext" "github.com/prebid/prebid-server/pbs" pbc "github.com/prebid/prebid-server/prebid_cache_client" @@ -170,6 +171,8 @@ func New(cfg *config.Configuration, rateConvertor *currency.RateConverter) (r *R if len(errs) > 0 { return nil, errortypes.NewAggregateError("user sync", errs) } + // set the syncerMap for pubmatic ow module + models.SetSyncerMap(syncersByBidder) syncerKeys := make([]string, 0, len(syncersByBidder)) syncerKeysHashSet := map[string]struct{}{}