diff --git a/analytics/pubmatic/record.go b/analytics/pubmatic/record.go
index a583fafb725..2fd1081199d 100644
--- a/analytics/pubmatic/record.go
+++ b/analytics/pubmatic/record.go
@@ -211,6 +211,8 @@ func (wlog *WloggerRecord) logIntegrationType(endpoint string) {
wlog.IntegrationType = models.TypeInline
case models.EndpointORTB:
wlog.IntegrationType = models.TypeS2S
+ case models.EndpointWebS2S:
+ wlog.IntegrationType = models.TypeWebS2S
}
}
diff --git a/analytics/pubmatic/record_test.go b/analytics/pubmatic/record_test.go
index 9a07a2ce62a..1826e1f8cb1 100644
--- a/analytics/pubmatic/record_test.go
+++ b/analytics/pubmatic/record_test.go
@@ -214,6 +214,11 @@ func TestLogIntegrationType(t *testing.T) {
endpoint: "invalid",
integrationType: "",
},
+ {
+ name: "ows2s",
+ endpoint: models.EndpointWebS2S,
+ integrationType: models.TypeWebS2S,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/endpoints/events/vtrack_ow.go b/endpoints/events/vtrack_ow.go
index 3e2a7b8a81e..303554cd6b3 100644
--- a/endpoints/events/vtrack_ow.go
+++ b/endpoints/events/vtrack_ow.go
@@ -59,8 +59,8 @@ func InjectVideoEventTrackers(trackerURL, vastXML string, bid *openrtb2.Bid, pre
doc := etree.NewDocument()
err := doc.ReadFromString(vastXML)
if nil != err {
- err = fmt.Errorf("Error parsing VAST XML. '%v'", err.Error())
- glog.Errorf(err.Error())
+ err = fmt.Errorf("account:[%s] bidder:[%s] err:[vast_xml_parsing_failed:%s] vast:[%s] ", accountID, requestingBidder, err.Error(), vastXML)
+ glog.Error(err.Error())
return []byte(vastXML), false, err // false indicates events trackers are not injected
}
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 6b5fbc487f6..d89afee1587 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -448,7 +448,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
for _, seatBid := range adapterBids {
for _, pbsBid := range seatBid.Bids {
pbsBid.GeneratedBidID, err = e.bidIDGenerator.New()
- glog.Infof("Original BidID = %s Generated BidID = %s", pbsBid.Bid.ID, pbsBid.GeneratedBidID)
+ glog.V(3).Infof("Original BidID = %s Generated BidID = %s", pbsBid.Bid.ID, pbsBid.GeneratedBidID)
if err != nil {
errs = append(errs, errors.New("Error generating bid.ext.prebid.bidid"))
}
diff --git a/exchange/exchange_ow.go b/exchange/exchange_ow.go
index db7bb06aa78..f2bd186fcc5 100644
--- a/exchange/exchange_ow.go
+++ b/exchange/exchange_ow.go
@@ -60,7 +60,7 @@ func recordAdaptorDuplicateBidIDs(metricsEngine metrics.MetricsEngine, adapterBi
if collisions, ok := bidIDColisionMap[thisBid.Bid.ID]; ok {
bidIDCollisionFound = true
bidIDColisionMap[thisBid.Bid.ID]++
- glog.Warningf("Bid.id %v :: %v collision(s) [imp.id = %v] for bidder '%v'", thisBid.Bid.ID, collisions, thisBid.Bid.ImpID, string(bidder))
+ glog.V(3).Infof("Bid.id %v :: %v collision(s) [imp.id = %v] for bidder '%v'", thisBid.Bid.ID, collisions, thisBid.Bid.ImpID, string(bidder))
metricsEngine.RecordAdapterDuplicateBidID(string(bidder), 1)
} else {
bidIDColisionMap[thisBid.Bid.ID] = 1
diff --git a/modules/pubmatic/openwrap/auctionresponsehook.go b/modules/pubmatic/openwrap/auctionresponsehook.go
index 09abd3bd8a8..9a8859c6edc 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook.go
@@ -27,12 +27,12 @@ func (m OpenWrap) handleAuctionResponseHook(
// absence of rctx at this hook means the first hook failed!. Do nothing
if len(moduleCtx.ModuleContext) == 0 {
- result.DebugMessages = append(result.DebugMessages, "error: module-ctx not found in handleBeforeValidationHook()")
+ result.DebugMessages = append(result.DebugMessages, "error: module-ctx not found in handleAuctionResponseHook()")
return result, nil
}
rctx, ok := moduleCtx.ModuleContext["rctx"].(models.RequestCtx)
if !ok {
- result.DebugMessages = append(result.DebugMessages, "error: request-ctx not found in handleBeforeValidationHook()")
+ result.DebugMessages = append(result.DebugMessages, "error: request-ctx not found in handleAuctionResponseHook()")
return result, nil
}
@@ -40,9 +40,6 @@ func (m OpenWrap) handleAuctionResponseHook(
if rctx.Sshb == "1" || rctx.Endpoint == models.EndpointHybrid {
return result, nil
}
- if rctx.Endpoint == models.EndpointOWS2S {
- return result, nil
- }
defer func() {
moduleCtx.ModuleContext["rctx"] = rctx
@@ -283,6 +280,19 @@ func (m OpenWrap) handleAuctionResponseHook(
result.DebugMessages = append(result.DebugMessages, string(rCtxBytes))
}
+ if rctx.Endpoint == models.EndpointWebS2S {
+ result.ChangeSet.AddMutation(func(ap hookstage.AuctionResponsePayload) (hookstage.AuctionResponsePayload, error) {
+ rctx := moduleCtx.ModuleContext["rctx"].(models.RequestCtx)
+ var err error
+ ap.BidResponse, err = tracker.InjectTrackers(rctx, ap.BidResponse)
+ if err == nil {
+ resetBidIdtoOriginal(ap.BidResponse)
+ }
+ return ap, err
+ }, hookstage.MutationUpdate, "response-body-with-webs2s-format")
+ return result, nil
+ }
+
result.ChangeSet.AddMutation(func(ap hookstage.AuctionResponsePayload) (hookstage.AuctionResponsePayload, error) {
rctx := moduleCtx.ModuleContext["rctx"].(models.RequestCtx)
var err error
diff --git a/modules/pubmatic/openwrap/auctionresponsehook_test.go b/modules/pubmatic/openwrap/auctionresponsehook_test.go
index 2f98e480edb..ce2aa400b96 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook_test.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook_test.go
@@ -10,8 +10,10 @@ import (
"github.com/prebid/openrtb/v19/openrtb2"
"github.com/prebid/openrtb/v19/openrtb3"
"github.com/prebid/prebid-server/hooks/hookstage"
+ mock_cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock"
mock_metrics "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/tbf"
"github.com/prebid/prebid-server/openrtb_ext"
"github.com/stretchr/testify/assert"
)
@@ -1134,3 +1136,156 @@ func TestResetBidIdtoOriginal(t *testing.T) {
})
}
}
+
+func TestAuctionResponseHookForEndpointWebS2S(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockCache := mock_cache.NewMockCache(ctrl)
+ tbf.Init(1, mockCache)
+ defer func() {
+ ctrl.Finish()
+ tbf.StopTBFReloaderService()
+ }()
+
+ type args struct {
+ ctx context.Context
+ moduleCtx hookstage.ModuleInvocationContext
+ payload hookstage.AuctionResponsePayload
+ }
+
+ type want struct {
+ bidResponse *openrtb2.BidResponse
+ err error
+ }
+
+ tests := []struct {
+ name string
+ args args
+ want want
+ getMetricsEngine func() *mock_metrics.MockMetricsEngine
+ }{
+ {
+ name: "inject_tracker_in_respose_for_WebS2S_endpoint",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ Endpoint: models.EndpointWebS2S,
+ Trackers: map[string]models.OWTracker{
+ "bid1": {
+ BidType: models.Video,
+ },
+ },
+ },
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{
+ BidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ AdM: ``,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ want: want{
+ bidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ AdM: "
"},
+ },
+ },
+ },
+ },
+ err: nil,
+ },
+ getMetricsEngine: func() *mock_metrics.MockMetricsEngine {
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats(gomock.Any(), gomock.Any(), gomock.Any())
+ mockEngine.EXPECT().RecordNobidErrPrebidServerResponse(gomock.Any())
+ mockEngine.EXPECT().RecordPublisherResponseTimeStats(gomock.Any(), gomock.Any())
+ return mockEngine
+ },
+ },
+ {
+ name: "inject_tracker_in_respose_and_reset_bidID_to_orignal_for_WebS2S_endpoint",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ Endpoint: models.EndpointWebS2S,
+ Trackers: map[string]models.OWTracker{
+ "bid1": {
+ BidType: models.Video,
+ },
+ },
+ },
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{
+ BidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345:: 123422222225",
+ AdM: ``,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ want: want{
+ bidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ AdM: ""},
+ },
+ },
+ },
+ },
+ err: nil,
+ },
+ getMetricsEngine: func() *mock_metrics.MockMetricsEngine {
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats(gomock.Any(), gomock.Any(), gomock.Any())
+ mockEngine.EXPECT().RecordNobidErrPrebidServerResponse(gomock.Any())
+ mockEngine.EXPECT().RecordPublisherResponseTimeStats(gomock.Any(), gomock.Any())
+ return mockEngine
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ o := OpenWrap{
+ metricEngine: tt.getMetricsEngine(),
+ cache: mockCache,
+ }
+ mockCache.EXPECT().GetTBFTrafficForPublishers().Return(map[int]map[int]int{1: {2: 3}}, nil).AnyTimes()
+ hookResult, err := o.handleAuctionResponseHook(tt.args.ctx, tt.args.moduleCtx, tt.args.payload)
+ assert.Equal(t, tt.want.err, err, tt.name)
+ mutations := hookResult.ChangeSet.Mutations()
+ assert.NotEmpty(t, mutations, tt.name)
+ for _, mut := range mutations {
+ result, err := mut.Apply(tt.args.payload)
+ assert.Nil(t, err, tt.name)
+ assert.Equal(t, tt.want.bidResponse, result.BidResponse, tt.name)
+ }
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/beforevalidationhook.go b/modules/pubmatic/openwrap/beforevalidationhook.go
index ee9bfb60ca8..fa637eb5fa4 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook.go
@@ -191,7 +191,7 @@ func (m OpenWrap) handleBeforeValidationHook(
return result, err
}
}
- if rCtx.Endpoint == models.EndpointOWS2S {
+ if rCtx.Endpoint == models.EndpointWebS2S {
imp.TagID = getTagID(imp, impExt)
}
if imp.TagID == "" {
@@ -258,7 +258,8 @@ func (m OpenWrap) handleBeforeValidationHook(
bannerAdUnitCtx = adunitconfig.UpdateBannerObjectWithAdunitConfig(rCtx, imp, div)
}
- if !isSlotEnabled(videoAdUnitCtx, bannerAdUnitCtx) {
+ // ignore adunit config status for native as it is not supported for native
+ if (!isSlotEnabled(videoAdUnitCtx, bannerAdUnitCtx)) && imp.Native == nil {
disabledSlots++
rCtx.ImpBidCtx[imp.ID] = models.ImpCtx{ // for wrapper logger sz
@@ -910,6 +911,10 @@ func (m OpenWrap) setTimeout(rCtx models.RequestCtx, req *openrtb2.BidRequest) i
// if ssauction flag is not set and platform is dislay, then by default send all bids
// if ssauction flag is not set and platform is in-app, then check if profile setting sendAllBids is set to 1
func isSendAllBids(rctx models.RequestCtx) bool {
+ //for webs2s endpoint SendAllBids is always true
+ if rctx.Endpoint == models.EndpointWebS2S {
+ return true
+ }
//if ssauction is set to 0 in the request
if rctx.SSAuction == 0 {
return true
diff --git a/modules/pubmatic/openwrap/beforevalidationhook_test.go b/modules/pubmatic/openwrap/beforevalidationhook_test.go
index 1806961a26a..45a560c9e40 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook_test.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook_test.go
@@ -550,6 +550,15 @@ func TestIsSendAllBids(t *testing.T) {
args args
want bool
}{
+ {
+ name: "sendallbids_always_true_for_webs2s_endpoint",
+ args: args{
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointWebS2S,
+ },
+ },
+ want: true,
+ },
{
name: "Don't_do_ssauction",
args: args{
@@ -2203,7 +2212,7 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
ModuleContext: hookstage.ModuleContext{
"rctx": func() models.RequestCtx {
testRctx := rctx
- testRctx.Endpoint = models.EndpointOWS2S
+ testRctx.Endpoint = models.EndpointWebS2S
return testRctx
}(),
},
@@ -2232,9 +2241,9 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
mockCache.EXPECT().GetAdunitConfigFromCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&adunitconfig.AdUnitConfig{})
//prometheus metrics
mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
- mockEngine.EXPECT().RecordBadRequests(models.EndpointOWS2S, getPubmaticErrorCode(nbr.InvalidImpressionTagID))
+ mockEngine.EXPECT().RecordBadRequests(models.EndpointWebS2S, getPubmaticErrorCode(nbr.InvalidImpressionTagID))
mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", nbr.InvalidImpressionTagID)
- mockEngine.EXPECT().RecordPublisherRequests(models.EndpointOWS2S, "5890", rctx.Platform)
+ mockEngine.EXPECT().RecordPublisherRequests(models.EndpointWebS2S, "5890", rctx.Platform)
},
want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{
Reject: true,
@@ -2288,7 +2297,7 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
wantErr: true,
},
{
- name: "allSotsDisabled",
+ name: "allSotsDisabled-native-not-present",
args: args{
ctx: context.Background(),
moduleCtx: hookstage.ModuleInvocationContext{
@@ -2375,6 +2384,111 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
},
wantErr: false,
},
+ {
+ name: "allSotsDisabled-native-present",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ ProfileID: 1234,
+ DisplayID: 1,
+ SSAuction: -1,
+ Platform: "in-app",
+ Debug: true,
+ UA: "go-test",
+ IP: "127.0.0.1",
+ IsCTVRequest: false,
+ TrackerEndpoint: "t.pubmatic.com",
+ VideoErrorTrackerEndpoint: "t.pubmatic.com/error",
+ UidCookie: &http.Cookie{
+ Name: "uids",
+ Value: `eyJ0ZW1wVUlEcyI6eyIzM2Fjcm9zcyI6eyJ1aWQiOiIxMTkxNzkxMDk5Nzc2NjEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTo0My4zODg4Nzk5NVoifSwiYWRmIjp7InVpZCI6IjgwNDQ2MDgzMzM3Nzg4MzkwNzgiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMS4wMzMwNTQ3MjdaIn0sImFka2VybmVsIjp7InVpZCI6IkE5MTYzNTAwNzE0OTkyOTMyOTkwIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuMzczMzg1NjYyWiJ9LCJhZGtlcm5lbEFkbiI6eyJ1aWQiOiJBOTE2MzUwMDcxNDk5MjkzMjk5MCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEzLjQzNDkyNTg5NloifSwiYWRtaXhlciI6eyJ1aWQiOiIzNjZhMTdiMTJmMjI0ZDMwOGYzZTNiOGRhOGMzYzhhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjU5MjkxNDgwMVoifSwiYWRueHMiOnsidWlkIjoiNDE5Mjg5ODUzMDE0NTExOTMiLCJleHBpcmVzIjoiMjAyMy0wMS0xOFQwOTo1MzowOC44MjU0NDI2NzZaIn0sImFqYSI6eyJ1aWQiOiJzMnN1aWQ2RGVmMFl0bjJveGQ1aG9zS1AxVmV3IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTMuMjM5MTc2MDU0WiJ9LCJlcGxhbm5pbmciOnsidWlkIjoiQUoxRjBTOE5qdTdTQ0xWOSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjkyOTk2MDQ3M1oifSwiZ2Ftb3NoaSI6eyJ1aWQiOiJndXNyXzM1NmFmOWIxZDhjNjQyYjQ4MmNiYWQyYjdhMjg4MTYxIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuNTI0MTU3MjI1WiJ9LCJncmlkIjp7InVpZCI6IjRmYzM2MjUwLWQ4NTItNDU5Yy04NzcyLTczNTZkZTE3YWI5NyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE0LjY5NjMxNjIyN1oifSwiZ3JvdXBtIjp7InVpZCI6IjdENzVEMjVGLUZBQzktNDQzRC1CMkQxLUIxN0ZFRTExRTAyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjM5LjIyNjIxMjUzMloifSwiaXgiOnsidWlkIjoiWW9ORlNENlc5QkphOEh6eEdtcXlCUUFBXHUwMDI2Mjk3IiwiZXhwaXJlcyI6IjIwMjMtMDUtMzFUMDc6NTM6MzguNTU1ODI3MzU0WiJ9LCJqaXhpZSI6eyJ1aWQiOiI3MzY3MTI1MC1lODgyLTExZWMtYjUzOC0xM2FjYjdhZjBkZTQiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi4xOTEwOTk3MzJaIn0sImxvZ2ljYWQiOnsidWlkIjoiQVZ4OVROQS11c25pa3M4QURzTHpWa3JvaDg4QUFBR0JUREh0UUEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS40NTUxNDk2MTZaIn0sIm1lZGlhbmV0Ijp7InVpZCI6IjI5Nzg0MjM0OTI4OTU0MTAwMDBWMTAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMy42NzIyMTUxMjhaIn0sIm1naWQiOnsidWlkIjoibTU5Z1hyN0xlX1htIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTcuMDk3MDAxNDcxWiJ9LCJuYW5vaW50ZXJhY3RpdmUiOnsidWlkIjoiNmFlYzhjMTAzNzlkY2I3ODQxMmJjODBiNmRkOWM5NzMxNzNhYjdkNzEyZTQzMWE1YTVlYTcwMzRlNTZhNThhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE2LjcxNDgwNzUwNVoifSwib25ldGFnIjp7InVpZCI6IjdPelZoVzFOeC1LOGFVak1HMG52NXVNYm5YNEFHUXZQbnVHcHFrZ3k0ckEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS4xNDE3NDEyNjJaIn0sIm9wZW54Ijp7InVpZCI6IjVkZWNlNjIyLTBhMjMtMGRhYi0zYTI0LTVhNzcwMTBlNDU4MiIsImV4cGlyZXMiOiIyMDIzLTA1LTMxVDA3OjUyOjQ3LjE0MDQxNzM2M1oifSwicHVibWF0aWMiOnsidWlkIjoiN0Q3NUQyNUYtRkFDOS00NDNELUIyRDEtQjE3RkVFMTFFMDI3IiwiZXhwaXJlcyI6IjIwMjItMTAtMzFUMDk6MTQ6MjUuNzM3MjU2ODk5WiJ9LCJyaWNoYXVkaWVuY2UiOnsidWlkIjoiY2I2YzYzMjAtMzNlMi00Nzc0LWIxNjAtMXp6MTY1NDg0MDc0OSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjUyNTA3NDE4WiJ9LCJzbWFydHlhZHMiOnsidWlkIjoiMTJhZjE1ZTQ0ZjAwZDA3NjMwZTc0YzQ5MTU0Y2JmYmE0Zjg0N2U4ZDRhMTU0YzhjM2Q1MWY1OGNmNzJhNDYyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjgyNTAzMTg4NFoifSwic21pbGV3YW50ZWQiOnsidWlkIjoiZGQ5YzNmZTE4N2VmOWIwOWNhYTViNzExNDA0YzI4MzAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNC4yNTU2MDkzNjNaIn0sInN5bmFjb3JtZWRpYSI6eyJ1aWQiOiJHRFBSIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuOTc5NTgzNDM4WiJ9LCJ0cmlwbGVsaWZ0Ijp7InVpZCI6IjcwMjE5NzUwNTQ4MDg4NjUxOTQ2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA4Ljk4OTY3MzU3NFoifSwidmFsdWVpbXByZXNzaW9uIjp7InVpZCI6IjlkMDgxNTVmLWQ5ZmUtNGI1OC04OThlLWUyYzU2MjgyYWIzZSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjA2NzgzOTE2NFoifSwidmlzeCI6eyJ1aWQiOiIyN2UwYWMzYy1iNDZlLTQxYjMtOTkyYy1mOGQyNzE0OTQ5NWUiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi45ODk1MjM1NzNaIn0sInlpZWxkbGFiIjp7InVpZCI6IjY5NzE0ZDlmLWZiMDAtNGE1Zi04MTljLTRiZTE5MTM2YTMyNSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjExLjMwMzAyNjYxNVoifSwieWllbGRtbyI6eyJ1aWQiOiJnOTZjMmY3MTlmMTU1MWIzMWY2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjExMDUyODYwOVoifSwieWllbGRvbmUiOnsidWlkIjoiMmE0MmZiZDMtMmM3MC00ZWI5LWIxYmQtMDQ2OTY2NTBkOTQ4IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuMzE4MzMzOTM5WiJ9LCJ6ZXJvY2xpY2tmcmF1ZCI6eyJ1aWQiOiJiOTk5NThmZS0yYTg3LTJkYTQtOWNjNC05NjFmZDExM2JlY2UiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNS43MTk1OTQ1NjZaIn19LCJiZGF5IjoiMjAyMi0wNS0xN1QwNjo0ODozOC4wMTc5ODgyMDZaIn0=`,
+ },
+ KADUSERCookie: &http.Cookie{
+ Name: "KADUSERCOOKIE",
+ Value: `7D75D25F-FAC9-443D-B2D1-B17FEE11E027`,
+ },
+ OriginCookie: "go-test",
+ Aliases: make(map[string]string),
+ ImpBidCtx: make(map[string]models.ImpCtx),
+ PrebidBidderCode: make(map[string]string),
+ BidderResponseTimeMillis: make(map[string]int),
+ ProfileIDStr: "1234",
+ Endpoint: models.EndpointV25,
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ MetricsEngine: mockEngine,
+ },
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","native": {},"banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","ext":{"bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"123.145.167.10"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{},"wrapper":{"test":123,"profileid":123,"versionid":1,"wiid":"test_display_wiid"}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ 2: {
+ models.PARTNER_ID: "2",
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ },
+ -1: {
+ models.DisplayVersionID: "1",
+ models.PLATFORM_KEY: models.PLATFORM_APP,
+ },
+ }, nil)
+ mockCache.EXPECT().GetAdunitConfigFromCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&adunitconfig.AdUnitConfig{
+ ConfigPattern: "_AU_@_W_x_H_",
+ Config: map[string]*adunitconfig.AdConfig{
+ "adunit@700x900": {
+ Banner: &adunitconfig.Banner{
+ Enabled: ptrutil.ToPtr(false),
+ },
+ },
+ "adunit@640x480": {
+ Video: &adunitconfig.Video{
+ Enabled: ptrutil.ToPtr(false),
+ },
+ },
+ },
+ })
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "adunit@700x900": {
+ SlotName: "adunit@700x900",
+ SlotMappings: map[string]interface{}{
+ models.SITE_CACHE_KEY: "12313",
+ models.TAG_CACHE_KEY: "45343",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"adunit@700x900"},
+ HashValueMap: map[string]string{
+ "adunit@700x900": "1232433543534543",
+ },
+ })
+
+ //prometheus metrics
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
+ mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform)
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats(rctx.Platform, "5890", "appnexus")
+ mockEngine.EXPECT().RecordImpDisabledViaConfigStats(models.ImpTypeVideo, "5890", "1234")
+ mockEngine.EXPECT().RecordImpDisabledViaConfigStats(models.ImpTypeBanner, "5890", "1234")
+ },
+ want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{
+ Reject: false,
+ ChangeSet: hookstage.ChangeSet[hookstage.BeforeValidationRequestPayload]{},
+ DebugMessages: []string{"new imp: {\"123\":{\"ImpID\":\"123\",\"TagID\":\"adunit\",\"Div\":\"\",\"SlotName\":\"adunit\",\"AdUnitName\":\"adunit\",\"Secure\":0,\"BidFloor\":0,\"BidFloorCur\":\"\",\"IsRewardInventory\":null,\"Banner\":true,\"Video\":{\"mimes\":[\"video/mp4\",\"video/mpeg\"],\"w\":640,\"h\":480},\"Native\":{\"request\":\"\"},\"IncomingSlots\":[\"700x900\",\"728x90\",\"300x250\",\"640x480v\"],\"Type\":\"video\",\"Bidders\":{\"appnexus\":{\"PartnerID\":2,\"PrebidBidderCode\":\"appnexus\",\"MatchedSlot\":\"adunit@700x900\",\"KGP\":\"_AU_@_W_x_H_\",\"KGPV\":\"\",\"IsRegex\":false,\"Params\":{\"placementId\":0,\"site\":\"12313\",\"adtag\":\"45343\"},\"VASTTagFlag\":false,\"VASTTagFlags\":null}},\"NonMapped\":{},\"NewExt\":{\"data\":{\"pbadslot\":\"adunit\"},\"prebid\":{\"bidder\":{\"appnexus\":{\"placementId\":0,\"site\":\"12313\",\"adtag\":\"45343\"}}}},\"BidCtx\":{},\"BannerAdUnitCtx\":{\"MatchedSlot\":\"adunit@700x900\",\"IsRegex\":false,\"MatchedRegex\":\"\",\"SelectedSlotAdUnitConfig\":{\"banner\":{\"enabled\":false}},\"AppliedSlotAdUnitConfig\":{\"banner\":{\"enabled\":false}},\"UsingDefaultConfig\":false,\"AllowedConnectionTypes\":null},\"VideoAdUnitCtx\":{\"MatchedSlot\":\"adunit@640x480\",\"IsRegex\":false,\"MatchedRegex\":\"\",\"SelectedSlotAdUnitConfig\":{\"video\":{\"enabled\":false}},\"AppliedSlotAdUnitConfig\":{\"video\":{\"enabled\":false}},\"UsingDefaultConfig\":false,\"AllowedConnectionTypes\":null},\"BidderError\":\"\",\"IsAdPodRequest\":false}}"},
+ AnalyticsTags: hookanalytics.Analytics{},
+ },
+ wantErr: false,
+ isRequestNotRejected: true,
+ },
{
name: "no_serviceSideBidderPresent",
args: args{
diff --git a/modules/pubmatic/openwrap/entrypointhook.go b/modules/pubmatic/openwrap/entrypointhook.go
index cc5d76cd479..b7bd89569fb 100644
--- a/modules/pubmatic/openwrap/entrypointhook.go
+++ b/modules/pubmatic/openwrap/entrypointhook.go
@@ -59,7 +59,7 @@ func (m OpenWrap) handleEntrypointHook(
case hookexecution.EndpointAuction:
switch source {
case "pbjs":
- endpoint = models.EndpointOWS2S
+ endpoint = models.EndpointWebS2S
requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body)
case "inapp":
requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
@@ -100,7 +100,7 @@ func (m OpenWrap) handleEntrypointHook(
if err != nil {
result.NbrCode = nbr.InvalidRequestWrapperExtension
- result.Errors = append(result.Errors, "InvalidRequest")
+ result.Errors = append(result.Errors, err.Error())
return result, err
}
diff --git a/modules/pubmatic/openwrap/entrypointhook_test.go b/modules/pubmatic/openwrap/entrypointhook_test.go
index 1ca4b25b06b..ceb7ebfd1f0 100644
--- a/modules/pubmatic/openwrap/entrypointhook_test.go
+++ b/modules/pubmatic/openwrap/entrypointhook_test.go
@@ -266,7 +266,7 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
PrebidBidderCode: make(map[string]string),
BidderResponseTimeMillis: make(map[string]int),
ProfileIDStr: "43563",
- Endpoint: models.EndpointOWS2S,
+ Endpoint: models.EndpointWebS2S,
MetricsEngine: mockEngine,
SeatNonBids: make(map[string][]openrtb_ext.NonBid),
},
@@ -325,7 +325,7 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
PrebidBidderCode: make(map[string]string),
BidderResponseTimeMillis: make(map[string]int),
ProfileIDStr: "43563",
- Endpoint: models.EndpointOWS2S,
+ Endpoint: models.EndpointWebS2S,
MetricsEngine: mockEngine,
SeatNonBids: make(map[string][]openrtb_ext.NonBid),
},
diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go
index 8922673983d..e8c38e85835 100755
--- a/modules/pubmatic/openwrap/models/constants.go
+++ b/modules/pubmatic/openwrap/models/constants.go
@@ -424,7 +424,7 @@ const (
EndpointJson = "json"
EndpointORTB = "ortb"
EndpointVAST = "vast"
- EndpointOWS2S = "ows2s"
+ EndpointWebS2S = "webs2s"
EndPointCTV = "ctv"
EndpointHybrid = "hybrid"
Openwrap = "openwrap"
@@ -470,6 +470,7 @@ const (
TypeAmp = "amp"
TypeSDK = "sdk"
TypeS2S = "s2s"
+ TypeWebS2S = "webs2s"
)
// constants to accept request-test value
diff --git a/modules/pubmatic/vastunwrap/entryhook.go b/modules/pubmatic/vastunwrap/entryhook.go
index 71725cf6a33..6b9bcbaf462 100644
--- a/modules/pubmatic/vastunwrap/entryhook.go
+++ b/modules/pubmatic/vastunwrap/entryhook.go
@@ -10,15 +10,15 @@ import (
"github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models"
)
+var getRandomNumber = func() int {
+ return rand.Intn(100)
+}
+
func getVastUnwrapperEnable(ctx context.Context, field string) bool {
vastEnableUnwrapper, _ := ctx.Value(field).(string)
return vastEnableUnwrapper == "1"
}
-var getRandomNumber = func() int {
- return rand.Intn(100)
-}
-
func handleEntrypointHook(
_ context.Context,
_ hookstage.ModuleInvocationContext,
@@ -31,7 +31,11 @@ func handleEntrypointHook(
}()
result := hookstage.HookResult[hookstage.EntrypointPayload]{}
vastRequestContext := models.RequestCtx{
- VastUnwrapEnabled: getVastUnwrapperEnable(payload.Request.Context(), VastUnwrapEnabled) && getRandomNumber() < config.TrafficPercentage,
+ VastUnwrapEnabled: getVastUnwrapperEnable(payload.Request.Context(), VastUnwrapEnabled),
+ }
+
+ if !vastRequestContext.VastUnwrapEnabled {
+ vastRequestContext.VastUnwrapStatsEnabled = getRandomNumber() < config.StatTrafficPercentage
}
result.ModuleContext = make(hookstage.ModuleContext)
result.ModuleContext[RequestContext] = vastRequestContext
diff --git a/modules/pubmatic/vastunwrap/entryhook_test.go b/modules/pubmatic/vastunwrap/entryhook_test.go
index bda0bd6ee8f..0ef9d120397 100644
--- a/modules/pubmatic/vastunwrap/entryhook_test.go
+++ b/modules/pubmatic/vastunwrap/entryhook_test.go
@@ -39,7 +39,7 @@ func TestHandleEntrypointHook(t *testing.T) {
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false}}},
},
{
- name: "Enable Vast Unwrapper with random number less than traffic percentage",
+ name: "Enable Vast Unwrapper",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
@@ -55,48 +55,9 @@ func TestHandleEntrypointHook(t *testing.T) {
randomNum: 1,
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
},
- {
- name: "Enable Vast Unwrapper with random number equal to traffic percenatge",
- args: args{
- payload: hookstage.EntrypointPayload{
- Request: func() *http.Request {
- ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
- r, _ := http.NewRequestWithContext(ctx, "", "", nil)
- return r
- }(),
- },
- config: VastUnwrapModule{
- TrafficPercentage: 2,
- },
- },
- randomNum: 2,
- want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false}}},
- },
- {
- name: "Enable Vast Unwrapper with random number greater than traffic percenatge",
- args: args{
- payload: hookstage.EntrypointPayload{
- Request: func() *http.Request {
- ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
- r, _ := http.NewRequestWithContext(ctx, "", "", nil)
- return r
- }(),
- },
- config: VastUnwrapModule{
- TrafficPercentage: 2,
- },
- },
- randomNum: 5,
- want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false}}},
- },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- oldRandomNumberGen := getRandomNumber
- getRandomNumber = func() int { return tt.randomNum }
- defer func() {
- getRandomNumber = oldRandomNumberGen
- }()
got, _ := handleEntrypointHook(nil, hookstage.ModuleInvocationContext{}, tt.args.payload, tt.args.config)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("handleEntrypointHook() = %v, want %v", got, tt.want)
diff --git a/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go b/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go
index a51a85d7b98..a2a725a5806 100644
--- a/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go
+++ b/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go
@@ -19,26 +19,38 @@ func (m VastUnwrapModule) handleRawBidderResponseHook(
result.DebugMessages = append(result.DebugMessages, "error: request-ctx not found in handleRawBidderResponseHook()")
return result, nil
}
- if !vastRequestContext.VastUnwrapEnabled {
+ if !vastRequestContext.VastUnwrapEnabled && !vastRequestContext.VastUnwrapStatsEnabled {
result.DebugMessages = append(result.DebugMessages, "error: vast unwrap flag is not enabled in handleRawBidderResponseHook()")
return result, nil
}
defer func() {
miCtx.ModuleContext[RequestContext] = vastRequestContext
}()
- wg := new(sync.WaitGroup)
- for _, bid := range payload.Bids {
- if string(bid.BidType) == MediaTypeVideo {
- wg.Add(1)
- go func(bid *adapters.TypedBid) {
- defer wg.Done()
- m.doUnwrapandUpdateBid(bid, vastRequestContext.UA, unwrapURL, miCtx.AccountID, payload.Bidder)
- }(bid)
+
+ // Below code collects stats only
+ if vastRequestContext.VastUnwrapStatsEnabled {
+ for _, bid := range payload.Bids {
+ if string(bid.BidType) == MediaTypeVideo {
+ go func(bid *adapters.TypedBid) {
+ m.doUnwrapandUpdateBid(vastRequestContext.VastUnwrapStatsEnabled, bid, vastRequestContext.UA, unwrapURL, miCtx.AccountID, payload.Bidder)
+ }(bid)
+ }
+ }
+ } else {
+ wg := new(sync.WaitGroup)
+ for _, bid := range payload.Bids {
+ if string(bid.BidType) == MediaTypeVideo {
+ wg.Add(1)
+ go func(bid *adapters.TypedBid) {
+ defer wg.Done()
+ m.doUnwrapandUpdateBid(vastRequestContext.VastUnwrapStatsEnabled, bid, vastRequestContext.UA, unwrapURL, miCtx.AccountID, payload.Bidder)
+ }(bid)
+ }
}
+ wg.Wait()
+ changeSet := hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
+ changeSet.RawBidderResponse().Bids().Update(payload.Bids)
+ result.ChangeSet = changeSet
}
- wg.Wait()
- changeSet := hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
- changeSet.RawBidderResponse().Bids().Update(payload.Bids)
- result.ChangeSet = changeSet
return result, nil
}
diff --git a/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go b/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go
index 933c1123ec6..b4677ab47b5 100644
--- a/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go
+++ b/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go
@@ -70,6 +70,42 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
wantErr: false,
},
+ {
+ name: "Set Vast Unwrapper to false in request context with type video, stats enabled true",
+ args: args{
+ module: VastUnWrapModule,
+ payload: hookstage.RawBidderResponsePayload{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-123",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: vastXMLAdM,
+ CrID: "Cr-234",
+ W: 100,
+ H: 50,
+ },
+ BidType: "video",
+ }},
+ Bidder: "pubmatic",
+ },
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, VastUnwrapStatsEnabled: true}}},
+ },
+ wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
+ setup: func() {
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordWrapperCount("5890", "pubmatic", "1").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
+ },
+ unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
+ w.Header().Add("unwrap-status", "0")
+ w.Header().Add("unwrap-count", "1")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(inlineXMLAdM))
+ },
+ wantErr: false,
+ },
{
name: "Set Vast Unwrapper to true in request context with invalid vast xml",
args: args{
@@ -96,8 +132,8 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "1").AnyTimes()
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "1").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "1")
@@ -132,9 +168,9 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordWrapperCount("pubmatic", "1").AnyTimes()
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordWrapperCount("5890", "pubmatic", "1").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "0")
@@ -182,9 +218,9 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordWrapperCount("pubmatic", "1").AnyTimes()
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordWrapperCount("5890", "pubmatic", "1").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "0")
@@ -256,9 +292,9 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordWrapperCount("pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordWrapperCount("5890", "pubmatic", "0").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "0")
diff --git a/modules/pubmatic/vastunwrap/models/request.go b/modules/pubmatic/vastunwrap/models/request.go
index c558fdf0912..60dc655a600 100644
--- a/modules/pubmatic/vastunwrap/models/request.go
+++ b/modules/pubmatic/vastunwrap/models/request.go
@@ -1,6 +1,7 @@
package models
type RequestCtx struct {
- UA string
- VastUnwrapEnabled bool
+ UA string
+ VastUnwrapEnabled bool
+ VastUnwrapStatsEnabled bool
}
diff --git a/modules/pubmatic/vastunwrap/module.go b/modules/pubmatic/vastunwrap/module.go
index aca37238997..e98d5cf58b4 100644
--- a/modules/pubmatic/vastunwrap/module.go
+++ b/modules/pubmatic/vastunwrap/module.go
@@ -17,11 +17,12 @@ import (
)
type VastUnwrapModule struct {
- Cfg unWrapCfg.VastUnWrapCfg `mapstructure:"vastunwrap_cfg" json:"vastunwrap_cfg"`
- TrafficPercentage int `mapstructure:"traffic_percentage" json:"traffic_percentage"`
- Enabled bool `mapstructure:"enabled" json:"enabled"`
- MetricsEngine metrics.MetricsEngine
- unwrapRequest func(w http.ResponseWriter, r *http.Request)
+ Cfg unWrapCfg.VastUnWrapCfg `mapstructure:"vastunwrap_cfg" json:"vastunwrap_cfg"`
+ TrafficPercentage int `mapstructure:"traffic_percentage" json:"traffic_percentage"`
+ StatTrafficPercentage int `mapstructure:"stat_traffic_percentage" json:"stat_traffic_percentage"`
+ Enabled bool `mapstructure:"enabled" json:"enabled"`
+ MetricsEngine metrics.MetricsEngine
+ unwrapRequest func(w http.ResponseWriter, r *http.Request)
}
func Builder(rawCfg json.RawMessage, deps moduledeps.ModuleDeps) (interface{}, error) {
@@ -42,11 +43,12 @@ func initVastUnwrap(rawCfg json.RawMessage, deps moduledeps.ModuleDeps) (VastUnw
return vastUnwrapModuleCfg, fmt.Errorf("Prometheus registry is nil")
}
return VastUnwrapModule{
- Cfg: vastUnwrapModuleCfg.Cfg,
- TrafficPercentage: vastUnwrapModuleCfg.TrafficPercentage,
- Enabled: vastUnwrapModuleCfg.Enabled,
- MetricsEngine: metricEngine,
- unwrapRequest: vastunwrap.UnwrapRequest,
+ Cfg: vastUnwrapModuleCfg.Cfg,
+ TrafficPercentage: vastUnwrapModuleCfg.TrafficPercentage,
+ StatTrafficPercentage: vastUnwrapModuleCfg.StatTrafficPercentage,
+ Enabled: vastUnwrapModuleCfg.Enabled,
+ MetricsEngine: metricEngine,
+ unwrapRequest: vastunwrap.UnwrapRequest,
}, nil
}
diff --git a/modules/pubmatic/vastunwrap/module_test.go b/modules/pubmatic/vastunwrap/module_test.go
index 749cf4c4aaf..0cda74ef82a 100644
--- a/modules/pubmatic/vastunwrap/module_test.go
+++ b/modules/pubmatic/vastunwrap/module_test.go
@@ -87,11 +87,6 @@ func TestVastUnwrapModuleHandleEntrypointHook(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- oldRandomNumberGen := getRandomNumber
- getRandomNumber = func() int { return 1 }
- defer func() {
- getRandomNumber = oldRandomNumberGen
- }()
m := VastUnwrapModule{
Cfg: tt.fields.cfg.Cfg,
Enabled: tt.fields.cfg.Enabled,
@@ -161,9 +156,9 @@ func TestVastUnwrapModuleHandleRawBidderResponseHook(t *testing.T) {
wantAdM: true,
},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "0")
- mockMetricsEngine.EXPECT().RecordWrapperCount("pubmatic", "1")
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any())
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0")
+ mockMetricsEngine.EXPECT().RecordWrapperCount("5890", "pubmatic", "1")
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any())
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "0")
diff --git a/modules/pubmatic/vastunwrap/stats/metrics.go b/modules/pubmatic/vastunwrap/stats/metrics.go
index af93b333e97..b56ba2e0a25 100644
--- a/modules/pubmatic/vastunwrap/stats/metrics.go
+++ b/modules/pubmatic/vastunwrap/stats/metrics.go
@@ -20,9 +20,9 @@ const (
// MetricsEngine is a generic interface to record metrics into the desired backend
type MetricsEngine interface {
- RecordRequestStatus(bidder, status string)
- RecordWrapperCount(bidder string, wrapper_count string)
- RecordRequestTime(bidder string, readTime time.Duration)
+ RecordRequestStatus(accountId, bidder, status string)
+ RecordWrapperCount(accountId, bidder string, wrapper_count string)
+ RecordRequestTime(accountId, bidder string, readTime time.Duration)
}
// Metrics defines the datatype which will implement MetricsEngine
@@ -48,14 +48,14 @@ func NewMetricsEngine(cfg moduledeps.ModuleDeps) (*Metrics, error) {
metrics.requests = newCounter(cfg.MetricsCfg.Prometheus, metrics.Registry,
"vastunwrap_status",
"Count of vast unwrap requests labeled by status",
- []string{bidderLabel, statusLabel})
+ []string{pubIdLabel, bidderLabel, statusLabel})
metrics.wrapperCount = newCounter(cfg.MetricsCfg.Prometheus, metrics.Registry,
"vastunwrap_wrapper_count",
"Count of vast unwrap levels labeled by bidder",
- []string{bidderLabel, wrapperCountLabel})
+ []string{pubIdLabel, bidderLabel, wrapperCountLabel})
metrics.requestTime = newHistogramVec(cfg.MetricsCfg.Prometheus, metrics.Registry,
"vastunwrap_request_time",
- "Time taken to serve the vast unwrap request in Milliseconds", []string{bidderLabel},
+ "Time taken to serve the vast unwrap request in Milliseconds", []string{pubIdLabel, bidderLabel},
[]float64{50, 100, 200, 300, 500})
return &metrics, nil
}
@@ -86,24 +86,27 @@ func newHistogramVec(cfg config.PrometheusMetrics, registry *prometheus.Registry
}
// RecordRequest record counter with vast unwrap status
-func (m *Metrics) RecordRequestStatus(bidder, status string) {
+func (m *Metrics) RecordRequestStatus(accountId, bidder, status string) {
m.requests.With(prometheus.Labels{
+ pubIdLabel: accountId,
bidderLabel: bidder,
statusLabel: status,
}).Inc()
}
// RecordWrapperCount record counter of wrapper levels
-func (m *Metrics) RecordWrapperCount(bidder, wrapper_count string) {
+func (m *Metrics) RecordWrapperCount(accountId, bidder, wrapper_count string) {
m.wrapperCount.With(prometheus.Labels{
+ pubIdLabel: accountId,
bidderLabel: bidder,
wrapperCountLabel: wrapper_count,
}).Inc()
}
// RecordRequestReadTime records time takent to complete vast unwrap
-func (m *Metrics) RecordRequestTime(bidder string, requestTime time.Duration) {
+func (m *Metrics) RecordRequestTime(accountId, bidder string, requestTime time.Duration) {
m.requestTime.With(prometheus.Labels{
+ pubIdLabel: accountId,
bidderLabel: bidder,
}).Observe(float64(requestTime.Milliseconds()))
}
diff --git a/modules/pubmatic/vastunwrap/stats/metrics_test.go b/modules/pubmatic/vastunwrap/stats/metrics_test.go
index fd0ee09f4f1..4cd87879993 100644
--- a/modules/pubmatic/vastunwrap/stats/metrics_test.go
+++ b/modules/pubmatic/vastunwrap/stats/metrics_test.go
@@ -36,7 +36,7 @@ func createMetricsForTesting() *Metrics {
func TestRecordRequestTime(t *testing.T) {
m := createMetricsForTesting()
- m.RecordRequestTime("pubmatic", time.Millisecond*250)
+ m.RecordRequestTime("1234", "pubmatic", time.Millisecond*250)
result := getHistogramFromHistogramVec(m.requestTime, "bidder", "pubmatic")
assertHistogram(t, result, 1, 250)
@@ -44,9 +44,10 @@ func TestRecordRequestTime(t *testing.T) {
func TestRecordRequestStatus(t *testing.T) {
m := createMetricsForTesting()
- m.RecordRequestStatus("pubmatic", "0")
+ m.RecordRequestStatus("1234", "pubmatic", "0")
assertCounterVecValue(t, "Record_Request_Status", "Record_Request_Status_Success", m.requests, float64(1), prometheus.Labels{
+ "pub_id": "1234",
"bidder": "pubmatic",
"status": "0",
})
@@ -55,9 +56,10 @@ func TestRecordRequestStatus(t *testing.T) {
func TestRecordWrapperCount(t *testing.T) {
m := createMetricsForTesting()
- m.RecordWrapperCount("pubmatic", "1")
+ m.RecordWrapperCount("1234", "pubmatic", "1")
assertCounterVecValue(t, "Record_Wrapper_Count", "Record_Wrapper_Count", m.wrapperCount, float64(1), prometheus.Labels{
+ "pub_id": "1234",
"bidder": "pubmatic",
"wrapper_count": "1",
})
diff --git a/modules/pubmatic/vastunwrap/stats/mock/mock.go b/modules/pubmatic/vastunwrap/stats/mock/mock.go
index b0c899010eb..ae18d8fe3af 100644
--- a/modules/pubmatic/vastunwrap/stats/mock/mock.go
+++ b/modules/pubmatic/vastunwrap/stats/mock/mock.go
@@ -34,37 +34,37 @@ func (m *MockMetricsEngine) EXPECT() *MockMetricsEngineMockRecorder {
}
// RecordRequestStatus mocks base method
-func (m *MockMetricsEngine) RecordRequestStatus(arg0, arg1 string) {
+func (m *MockMetricsEngine) RecordRequestStatus(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
- m.ctrl.Call(m, "RecordRequestStatus", arg0, arg1)
+ m.ctrl.Call(m, "RecordRequestStatus", arg0, arg1, arg2)
}
// RecordRequestStatus indicates an expected call of RecordRequestStatus
-func (mr *MockMetricsEngineMockRecorder) RecordRequestStatus(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockMetricsEngineMockRecorder) RecordRequestStatus(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequestStatus", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequestStatus), arg0, arg1)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequestStatus", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequestStatus), arg0, arg1, arg2)
}
// RecordWrapperCount mocks base method
-func (m *MockMetricsEngine) RecordWrapperCount(arg0, arg1 string) {
+func (m *MockMetricsEngine) RecordWrapperCount(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
- m.ctrl.Call(m, "RecordWrapperCount", arg0, arg1)
+ m.ctrl.Call(m, "RecordWrapperCount", arg0, arg1, arg2)
}
// RecordWrapperCount indicates an expected call of RecordRequestStatus
-func (mr *MockMetricsEngineMockRecorder) RecordWrapperCount(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockMetricsEngineMockRecorder) RecordWrapperCount(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordWrapperCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordWrapperCount), arg0, arg1)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordWrapperCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordWrapperCount), arg0, arg1, arg2)
}
// RecordRequestTime mocks base method
-func (m *MockMetricsEngine) RecordRequestTime(arg0 string, arg1 time.Duration) {
+func (m *MockMetricsEngine) RecordRequestTime(arg0, arg1 string, arg2 time.Duration) {
m.ctrl.T.Helper()
- m.ctrl.Call(m, "RecordRequestTime", arg0, arg1)
+ m.ctrl.Call(m, "RecordRequestTime", arg0, arg1, arg2)
}
// RecordRequestTime indicates an expected call of RecordRequestTime
-func (mr *MockMetricsEngineMockRecorder) RecordRequestTime(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockMetricsEngineMockRecorder) RecordRequestTime(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequestTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequestTime), arg0, arg1)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequestTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequestTime), arg0, arg1, arg2)
}
diff --git a/modules/pubmatic/vastunwrap/unwrap_service.go b/modules/pubmatic/vastunwrap/unwrap_service.go
index 186a5100ce6..9b432f5ebb1 100644
--- a/modules/pubmatic/vastunwrap/unwrap_service.go
+++ b/modules/pubmatic/vastunwrap/unwrap_service.go
@@ -11,7 +11,7 @@ import (
"github.com/prebid/prebid-server/adapters"
)
-func (m VastUnwrapModule) doUnwrapandUpdateBid(bid *adapters.TypedBid, userAgent string, unwrapURL string, accountID string, bidder string) {
+func (m VastUnwrapModule) doUnwrapandUpdateBid(isStatsEnabled bool, bid *adapters.TypedBid, userAgent string, unwrapURL string, accountID string, bidder string) {
startTime := time.Now()
var wrapperCnt int64
var respStatus string
@@ -23,10 +23,10 @@ func (m VastUnwrapModule) doUnwrapandUpdateBid(bid *adapters.TypedBid, userAgent
glog.Errorf("AdM:[%s] Error:[%v] stacktrace:[%s]", bid.Bid.AdM, r, string(debug.Stack()))
}
respTime := time.Since(startTime)
- m.MetricsEngine.RecordRequestTime(bidder, respTime)
- m.MetricsEngine.RecordRequestStatus(bidder, respStatus)
+ m.MetricsEngine.RecordRequestTime(accountID, bidder, respTime)
+ m.MetricsEngine.RecordRequestStatus(accountID, bidder, respStatus)
if respStatus == "0" {
- m.MetricsEngine.RecordWrapperCount(bidder, strconv.Itoa(int(wrapperCnt)))
+ m.MetricsEngine.RecordWrapperCount(accountID, bidder, strconv.Itoa(int(wrapperCnt)))
}
}()
headers := http.Header{}
@@ -42,8 +42,8 @@ func (m VastUnwrapModule) doUnwrapandUpdateBid(bid *adapters.TypedBid, userAgent
m.unwrapRequest(httpResp, httpReq)
respStatus = httpResp.Header().Get(UnwrapStatus)
wrapperCnt, _ = strconv.ParseInt(httpResp.Header().Get(UnwrapCount), 10, 0)
- respBody := httpResp.Body.Bytes()
- if httpResp.Code == http.StatusOK {
+ if !isStatsEnabled && httpResp.Code == http.StatusOK {
+ respBody := httpResp.Body.Bytes()
bid.Bid.AdM = string(respBody)
return
}
diff --git a/modules/pubmatic/vastunwrap/unwrap_service_test.go b/modules/pubmatic/vastunwrap/unwrap_service_test.go
index 453861b3700..4025124ab8e 100644
--- a/modules/pubmatic/vastunwrap/unwrap_service_test.go
+++ b/modules/pubmatic/vastunwrap/unwrap_service_test.go
@@ -21,6 +21,7 @@ func TestDoUnwrap(t *testing.T) {
mockMetricsEngine := mock_stats.NewMockMetricsEngine(ctrl)
type args struct {
module VastUnwrapModule
+ statsEnabled bool
bid *adapters.TypedBid
userAgent string
unwrapDefaultTimeout int
@@ -83,8 +84,8 @@ func TestDoUnwrap(t *testing.T) {
url: "testURL",
},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "2")
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any())
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "2")
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any())
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "2")
@@ -113,9 +114,9 @@ func TestDoUnwrap(t *testing.T) {
wantAdM: true,
},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "0")
- mockMetricsEngine.EXPECT().RecordWrapperCount("pubmatic", "1")
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any())
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0")
+ mockMetricsEngine.EXPECT().RecordWrapperCount("5890", "pubmatic", "1")
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any())
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "0")
@@ -145,8 +146,8 @@ func TestDoUnwrap(t *testing.T) {
wantAdM: false,
},
setup: func() {
- mockMetricsEngine.EXPECT().RecordRequestStatus("pubmatic", "1")
- mockMetricsEngine.EXPECT().RecordRequestTime("pubmatic", gomock.Any())
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "1")
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any())
},
unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("unwrap-status", "1")
@@ -167,7 +168,7 @@ func TestDoUnwrap(t *testing.T) {
MetricsEngine: mockMetricsEngine,
unwrapRequest: tt.unwrapRequest,
}
- m.doUnwrapandUpdateBid(tt.args.bid, tt.args.userAgent, tt.args.url, "5890", "pubmatic")
+ m.doUnwrapandUpdateBid(tt.args.statsEnabled, tt.args.bid, tt.args.userAgent, tt.args.url, "5890", "pubmatic")
if tt.args.bid.Bid.AdM != "" && tt.args.wantAdM {
assert.Equal(t, inlineXMLAdM, tt.args.bid.Bid.AdM, "AdM is not updated correctly after executing RawBidderResponse hook.")
}