diff --git a/adapters/vastbidder/etree_parser.go b/adapters/vastbidder/etree_parser.go
index ed8163783a5..fcf06a40c98 100644
--- a/adapters/vastbidder/etree_parser.go
+++ b/adapters/vastbidder/etree_parser.go
@@ -2,7 +2,6 @@ package vastbidder
import (
"strconv"
- "strings"
"github.com/beevik/etree"
"github.com/prebid/prebid-server/v2/openrtb_ext"
@@ -70,7 +69,7 @@ func (p *etreeXMLParser) GetPricingDetails() (price float64, currency string) {
return 0.0, ""
}
- priceValue, err := strconv.ParseFloat(strings.TrimSpace(node.Text()), 64)
+ priceValue, err := strconv.ParseFloat(node.TrimmedText(), 64)
if nil != err {
return 0.0, ""
}
@@ -89,7 +88,7 @@ func (p *etreeXMLParser) GetAdvertiser() (advertisers []string) {
if ext.SelectAttrValue("type", "") == "advertiser" {
ele := ext.SelectElement("Advertiser")
if ele != nil {
- if value := strings.TrimSpace(ele.Text()); len(value) > 0 {
+ if value := ele.TrimmedText(); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
@@ -98,7 +97,7 @@ func (p *etreeXMLParser) GetAdvertiser() (advertisers []string) {
case vastVersion4x:
if ele := p.adElement.SelectElement("Advertiser"); ele != nil {
- if value := strings.TrimSpace(ele.Text()); len(value) > 0 {
+ if value := ele.TrimmedText(); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
@@ -126,7 +125,7 @@ func (p *etreeXMLParser) GetDuration() (int, error) {
if node == nil {
return 0, errEmptyVideoDuration
}
- return parseDuration(strings.TrimSpace(node.Text()))
+ return parseDuration(node.TrimmedText())
}
func (p *etreeXMLParser) getAdElement(vast *etree.Element) *etree.Element {
diff --git a/adapters/vastbidder/etree_parser_test.go b/adapters/vastbidder/etree_parser_test.go
index dd50ded2dad..43b79a46562 100644
--- a/adapters/vastbidder/etree_parser_test.go
+++ b/adapters/vastbidder/etree_parser_test.go
@@ -342,6 +342,12 @@ func getPricingDetailsTestCases() []struct {
wantPrice: 0,
wantCurrency: "",
},
+ {
+ name: "bug",
+ vastXML: "\n\t\n\t\t\n\t\t\tPubMatic\n\t\t\tscenario_9\n\t\t\tTest Ad scenario_9\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\tTest Advertiser\n\t\t\tIAB1-1\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t8465_scenario_9\n\t\t\t\t\t\n\t\t\t\t\t\t00:00:10\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\n ",
+ wantPrice: 5,
+ wantCurrency: "USD",
+ },
// TODO: Add test cases.
}
}
diff --git a/adapters/vastbidder/fastxml_parser.go b/adapters/vastbidder/fastxml_parser.go
index dfbde606db7..a83cfd293f0 100644
--- a/adapters/vastbidder/fastxml_parser.go
+++ b/adapters/vastbidder/fastxml_parser.go
@@ -70,7 +70,7 @@ func (p *fastXMLParser) GetPricingDetails() (price float64, currency string) {
return 0.0, ""
}
- priceValue, err := strconv.ParseFloat(strings.TrimSpace(p.reader.Text(node, true)), 64)
+ priceValue, err := strconv.ParseFloat(strings.TrimSpace(p.reader.RawText(node)), 64)
if nil != err {
return 0.0, ""
}
@@ -89,7 +89,7 @@ func (p *fastXMLParser) GetAdvertiser() (advertisers []string) {
if p.reader.SelectAttrValue(ext, "type") == "advertiser" {
ele := p.reader.SelectElement(ext, "Advertiser")
if ele != nil {
- if value := strings.TrimSpace(p.reader.Text(ele, true)); len(value) > 0 {
+ if value := strings.TrimSpace(p.reader.Text(ele)); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
@@ -98,7 +98,7 @@ func (p *fastXMLParser) GetAdvertiser() (advertisers []string) {
case vastVersion4x:
if ele := p.reader.SelectElement(p.adElement, "Advertiser"); ele != nil {
- if value := strings.TrimSpace(p.reader.Text(ele, true)); len(value) > 0 {
+ if value := strings.TrimSpace(p.reader.Text(ele)); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
@@ -126,7 +126,7 @@ func (p *fastXMLParser) GetDuration() (int, error) {
if node == nil {
return 0, errEmptyVideoDuration
}
- return parseDuration(strings.TrimSpace(p.reader.Text(node, true)))
+ return parseDuration(strings.TrimSpace(p.reader.RawText(node)))
}
func (p *fastXMLParser) getAdElement(vast *fastxml.Element) *fastxml.Element {
diff --git a/adapters/vastbidder/vastbidder.go b/adapters/vastbidder/vastbidder.go
index 06b3abff67a..778b809ba96 100644
--- a/adapters/vastbidder/vastbidder.go
+++ b/adapters/vastbidder/vastbidder.go
@@ -12,9 +12,9 @@ import (
// VASTBidder is default implementation of ITagBidder
type VASTBidder struct {
adapters.Bidder
- bidderName openrtb_ext.BidderName
- adapterConfig *config.Adapter
- fastXMLExperiment bool
+ bidderName openrtb_ext.BidderName
+ adapterConfig *config.Adapter
+ fastXMLEnabledPercentage int
}
// MakeRequests will contains default definition for processing queries
@@ -76,7 +76,7 @@ func (a *VASTBidder) MakeBids(internalRequest *openrtb2.BidRequest, externalRequ
responseData, errs := handler.MakeBids()
- if a.fastXMLExperiment && len(errs) == 0 {
+ if openrtb_ext.IsFastXMLEnabled(a.fastXMLEnabledPercentage) && len(errs) == 0 {
a.fastXMLTesting(
newResponseHandler(internalRequest, externalRequest, response, getXMLParser(fastXMLParserType)),
responseData,
@@ -101,26 +101,26 @@ func (a *VASTBidder) fastXMLTesting(handler *responseHandler, responseData *adap
}
}
- vastBidderInfo := &openrtb_ext.FastXMLMetrics{
+ xmlParsingMetrics := &openrtb_ext.FastXMLMetrics{
XMLParserTime: handlerTime,
EtreeParserTime: etreeParserTime,
IsRespMismatch: isVASTMismatch,
}
- responseData.FastXMLMetrics = vastBidderInfo
+ responseData.FastXMLMetrics = xmlParsingMetrics
}
// NewTagBidder is an constructor for TagBidder
-func NewTagBidder(bidderName openrtb_ext.BidderName, config config.Adapter, enableFastXML bool) *VASTBidder {
+func NewTagBidder(bidderName openrtb_ext.BidderName, config config.Adapter, enableFastXML int) *VASTBidder {
obj := &VASTBidder{
- bidderName: bidderName,
- adapterConfig: &config,
- fastXMLExperiment: enableFastXML,
+ bidderName: bidderName,
+ adapterConfig: &config,
+ fastXMLEnabledPercentage: enableFastXML,
}
return obj
}
// Builder builds a new instance of the 33Across adapter for the given bidder with the given config.
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, serverConfig config.Server) (adapters.Bidder, error) {
- return NewTagBidder(bidderName, config, serverConfig.EnableFastXML), nil
+ return NewTagBidder(bidderName, config, serverConfig.FastXMLEnabledPercentage), nil
}
diff --git a/adapters/vastbidder/vastbidder_test.go b/adapters/vastbidder/vastbidder_test.go
index f53abe23209..6f7652e8519 100644
--- a/adapters/vastbidder/vastbidder_test.go
+++ b/adapters/vastbidder/vastbidder_test.go
@@ -137,7 +137,7 @@ func TestMakeRequests(t *testing.T) {
RegisterNewBidderMacro(bidderName, func() IBidderMacro {
return newMyVastBidderMacro(tt.args.customHeaders)
})
- bidder := NewTagBidder(bidderName, config.Adapter{}, false)
+ bidder := NewTagBidder(bidderName, config.Adapter{}, 0)
reqData, err := bidder.MakeRequests(tt.args.req, nil)
assert.Nil(t, err)
for _, req := range reqData {
diff --git a/analytics/pubmatic/logger.go b/analytics/pubmatic/logger.go
index 597c4320801..75364070d55 100644
--- a/analytics/pubmatic/logger.go
+++ b/analytics/pubmatic/logger.go
@@ -383,6 +383,9 @@ func getPartnerRecordsByImp(ao analytics.AuctionObject, rCtx *models.RequestCtx)
}
price := bid.Price
+ // If bids are rejected before setting bidExt.OriginalBidCPM, calculate the price and ocpm values based on the currency and revshare.
+ price = computeBidPriceForBidsRejectedBeforeSettingOCPM(rCtx, &bidExt, price, revShare, ao)
+ bid.Price = price
if ao.Response.Cur != models.USD {
if bidCtx.EN != 0 { // valid-bids + dropped-bids+ default-bids
price = bidCtx.EN
@@ -564,3 +567,32 @@ func getAdPodSlot(adPodConfig *models.AdPod) *AdPodSlot {
return &adPodSlot
}
+
+func GetBidPriceAfterCurrencyConversion(price float64, requestCurrencies []string, responseCurrency string,
+ currencyConverter func(fromCurrency string, toCurrency string, value float64) (float64, error)) float64 {
+ if len(requestCurrencies) == 0 {
+ requestCurrencies = []string{models.USD}
+ }
+ for _, requestCurrency := range requestCurrencies {
+ if value, err := currencyConverter(responseCurrency, requestCurrency, price); err == nil {
+ return value
+ }
+ }
+ return 0 // in case of error, send 0 value to make it consistent with prebid
+}
+
+func computeBidPriceForBidsRejectedBeforeSettingOCPM(rCtx *models.RequestCtx, bidExt *models.BidExt,
+ price, revshare float64, ao analytics.AuctionObject) float64 {
+ if price != 0 && bidExt.OriginalBidCPM == 0 {
+ if len(bidExt.OriginalBidCur) == 0 {
+ bidExt.OriginalBidCur = models.USD
+ }
+ bidExt.OriginalBidCPM = price
+ price = price * models.GetBidAdjustmentValue(revshare)
+ if cpmUSD, err := rCtx.CurrencyConversion(bidExt.OriginalBidCur, models.USD, price); err == nil {
+ bidExt.OriginalBidCPMUSD = cpmUSD
+ }
+ price = GetBidPriceAfterCurrencyConversion(price, ao.RequestWrapper.Cur, bidExt.OriginalBidCur, rCtx.CurrencyConversion)
+ }
+ return price
+}
diff --git a/analytics/pubmatic/logger_test.go b/analytics/pubmatic/logger_test.go
index b01f1f7b501..41ef74a283f 100644
--- a/analytics/pubmatic/logger_test.go
+++ b/analytics/pubmatic/logger_test.go
@@ -2,6 +2,7 @@ package pubmatic
import (
"encoding/json"
+ "fmt"
"net/http"
"net/url"
"testing"
@@ -294,7 +295,8 @@ func TestGetPartnerRecordsByImp(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
},
},
},
@@ -347,7 +349,8 @@ func TestGetPartnerRecordsByImp(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
},
},
},
@@ -403,7 +406,8 @@ func TestGetPartnerRecordsByImp(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
},
},
},
@@ -459,7 +463,8 @@ func TestGetPartnerRecordsByImp(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
},
},
},
@@ -512,7 +517,8 @@ func TestGetPartnerRecordsByImp(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
},
},
},
@@ -564,7 +570,8 @@ func TestGetPartnerRecordsByImp(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
},
},
},
@@ -709,7 +716,8 @@ func TestGetPartnerRecordsByImpForTracker(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
+ ExtBid: openrtb_ext.ExtBid{},
},
},
},
@@ -771,6 +779,7 @@ func TestGetPartnerRecordsByImpForTracker(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
+ OriginalBidCPM: 12,
ExtBid: openrtb_ext.ExtBid{
Prebid: &openrtb_ext.ExtBidPrebid{
Floors: &openrtb_ext.ExtBidPrebidFloors{
@@ -1015,7 +1024,8 @@ func TestGetPartnerRecordsByImpForDefaultBids(t *testing.T) {
BidCtx: map[string]models.BidCtx{
"bid-id-1": {
BidExt: models.BidExt{
- ExtBid: openrtb_ext.ExtBid{},
+ ExtBid: openrtb_ext.ExtBid{},
+ OriginalBidCPM: 10,
},
},
},
@@ -1287,6 +1297,7 @@ func TestGetPartnerRecordsByImpForDefaultBids(t *testing.T) {
}
}
func TestGetPartnerRecordsByImpForSeatNonBid(t *testing.T) {
+ pg, _ := openrtb_ext.NewPriceGranularityFromLegacyID("med")
type args struct {
ao analytics.AuctionObject
rCtx *models.RequestCtx
@@ -1420,6 +1431,301 @@ func TestGetPartnerRecordsByImpForSeatNonBid(t *testing.T) {
},
},
},
+ {
+ name: "log rejected non-bid having bidder_response_currency EUR and request_currency USD",
+ args: args{
+ ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Cur: []string{models.USD},
+ },
+ },
+ Response: &openrtb2.BidResponse{Cur: models.USD},
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "appnexus",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: int(nbr.LossBidLostInVastUnwrap),
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
+ Price: 10,
+ ID: "bid-id-1",
+ W: 10,
+ H: 50,
+ OriginalBidCur: "EUR",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ rCtx: &models.RequestCtx{
+ PriceGranularity: &pg,
+ CurrencyConversion: func(from, to string, value float64) (float64, error) {
+ if from == "USD" && to == "EUR" {
+ return value * 1.2, nil
+ }
+ if from == "EUR" && to == "USD" {
+ return value * 0.8, nil
+ }
+ return 0, nil
+ },
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp1": {
+ Bidders: map[string]models.PartnerData{
+ "appnexus": {
+ PartnerID: 1,
+ PrebidBidderCode: "appnexus",
+ KGP: "kgp",
+ KGPV: "kgpv",
+ },
+ },
+ BidCtx: map[string]models.BidCtx{
+ "bid-id-1": {
+ BidExt: models.BidExt{
+ ExtBid: openrtb_ext.ExtBid{},
+ Nbr: ptrutil.ToPtr(nbr.LossBidLostInVastUnwrap),
+ },
+ },
+ },
+ BidFloor: 10.5,
+ BidFloorCur: "USD",
+ },
+ },
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ "rev_share": "0",
+ },
+ },
+ WinningBids: make(models.WinningBids),
+ Platform: models.PLATFORM_APP,
+ },
+ },
+ partners: map[string][]PartnerRecord{
+ "imp1": {
+ {
+ PartnerID: "appnexus",
+ BidderCode: "appnexus",
+ KGPV: "kgpv",
+ KGPSV: "kgpv",
+ PartnerSize: "10x50",
+ GrossECPM: 8,
+ NetECPM: 8,
+ BidID: "bid-id-1",
+ OrigBidID: "bid-id-1",
+ DealID: "-1",
+ ServerSide: 1,
+ OriginalCPM: 10,
+ OriginalCur: "EUR",
+ FloorValue: 10.5,
+ FloorRuleValue: 10.5,
+ PriceBucket: "8.00",
+ Nbr: ptrutil.ToPtr(nbr.LossBidLostInVastUnwrap),
+ },
+ },
+ },
+ },
+ {
+ name: "log rejected non-bid having bidder_response_currency EUR and request_currency USD and having 50% revshare",
+ args: args{
+ ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Cur: []string{models.USD},
+ },
+ },
+ Response: &openrtb2.BidResponse{Cur: models.USD},
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "appnexus",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: int(nbr.LossBidLostInVastUnwrap),
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
+ Price: 10,
+ ID: "bid-id-1",
+ W: 10,
+ H: 50,
+ OriginalBidCur: "EUR",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ rCtx: &models.RequestCtx{
+ PriceGranularity: &pg,
+ CurrencyConversion: func(from, to string, value float64) (float64, error) {
+ if from == "USD" && to == "EUR" {
+ return value * 1.2, nil
+ }
+ if from == "EUR" && to == "USD" {
+ return value * 0.8, nil
+ }
+ return 0, nil
+ },
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp1": {
+ Bidders: map[string]models.PartnerData{
+ "appnexus": {
+ PartnerID: 1,
+ PrebidBidderCode: "appnexus",
+ KGP: "kgp",
+ KGPV: "kgpv",
+ },
+ },
+ BidCtx: map[string]models.BidCtx{
+ "bid-id-1": {
+ BidExt: models.BidExt{
+ ExtBid: openrtb_ext.ExtBid{},
+ Nbr: ptrutil.ToPtr(nbr.LossBidLostInVastUnwrap),
+ },
+ },
+ },
+ BidFloor: 10.5,
+ BidFloorCur: "USD",
+ },
+ },
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ "rev_share": "50",
+ },
+ },
+ WinningBids: make(models.WinningBids),
+ Platform: models.PLATFORM_APP,
+ },
+ },
+ partners: map[string][]PartnerRecord{
+ "imp1": {
+ {
+ PartnerID: "appnexus",
+ BidderCode: "appnexus",
+ KGPV: "kgpv",
+ KGPSV: "kgpv",
+ PartnerSize: "10x50",
+ GrossECPM: 8,
+ NetECPM: 4,
+ PriceBucket: "4.00",
+ BidID: "bid-id-1",
+ OrigBidID: "bid-id-1",
+ DealID: "-1",
+ ServerSide: 1,
+ OriginalCPM: 10,
+ OriginalCur: "EUR",
+ FloorValue: 10.5,
+ FloorRuleValue: 10.5,
+ Nbr: ptrutil.ToPtr(nbr.LossBidLostInVastUnwrap),
+ },
+ },
+ },
+ },
+ {
+ name: "log rejected non-bid having response_currency USD and request_currency EUR and having 50% revshare",
+ args: args{
+ ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Cur: []string{"EUR"},
+ },
+ },
+ Response: &openrtb2.BidResponse{Cur: "EUR"},
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "appnexus",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: int(nbr.LossBidLostInVastUnwrap),
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
+ Price: 10,
+ ID: "bid-id-1",
+ W: 10,
+ H: 50,
+ OriginalBidCur: models.USD,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ rCtx: &models.RequestCtx{
+ CurrencyConversion: func(from, to string, value float64) (float64, error) {
+ if from == "USD" && to == "EUR" {
+ return value * 1.2, nil
+ }
+ if from == "EUR" && to == "USD" {
+ return value * 0.8, nil
+ }
+ return value, nil
+ },
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp1": {
+ Bidders: map[string]models.PartnerData{
+ "appnexus": {
+ PartnerID: 1,
+ PrebidBidderCode: "appnexus",
+ KGP: "kgp",
+ KGPV: "kgpv",
+ },
+ },
+ BidCtx: map[string]models.BidCtx{
+ "bid-id-1": {
+ BidExt: models.BidExt{
+ ExtBid: openrtb_ext.ExtBid{},
+ Nbr: ptrutil.ToPtr(nbr.LossBidLostInVastUnwrap),
+ },
+ },
+ },
+ BidFloor: 10.5,
+ BidFloorCur: "USD",
+ },
+ },
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ "rev_share": "50",
+ },
+ },
+ WinningBids: make(models.WinningBids),
+ Platform: models.PLATFORM_APP,
+ },
+ },
+ partners: map[string][]PartnerRecord{
+ "imp1": {
+ {
+ PartnerID: "appnexus",
+ BidderCode: "appnexus",
+ KGPV: "kgpv",
+ KGPSV: "kgpv",
+ PartnerSize: "10x50",
+ GrossECPM: 10,
+ NetECPM: 5,
+ BidID: "bid-id-1",
+ OrigBidID: "bid-id-1",
+ DealID: "-1",
+ ServerSide: 1,
+ OriginalCPM: 10,
+ OriginalCur: "USD",
+ FloorValue: 10.5,
+ FloorRuleValue: 10.5,
+ Nbr: ptrutil.ToPtr(nbr.LossBidLostInVastUnwrap),
+ },
+ },
+ },
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -1461,6 +1767,7 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
FloorValue: 1,
FloorCurrency: models.USD,
},
+ OriginalBidCPM: 10,
},
},
},
@@ -1527,6 +1834,7 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
FloorValue: 0,
FloorCurrency: models.USD,
},
+ OriginalBidCPM: 10,
},
},
},
@@ -1593,6 +1901,7 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
FloorValue: 10,
FloorCurrency: models.USD,
},
+ OriginalBidCPM: 10,
},
},
},
@@ -1651,8 +1960,9 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
Ext: openrtb_ext.ExtNonBid{
Prebid: openrtb_ext.ExtNonBidPrebid{
Bid: openrtb_ext.ExtNonBidPrebidBid{
- Price: 10,
- ID: "bid-id-1",
+ Price: 10,
+ ID: "bid-id-1",
+ OriginalBidCPM: 10,
},
},
},
@@ -1711,8 +2021,9 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
Ext: openrtb_ext.ExtNonBid{
Prebid: openrtb_ext.ExtNonBidPrebid{
Bid: openrtb_ext.ExtNonBidPrebidBid{
- Price: 10,
- ID: "bid-id-1",
+ Price: 10,
+ ID: "bid-id-1",
+ OriginalBidCPM: 10,
},
},
},
@@ -1782,6 +2093,7 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
FloorValue: 1,
FloorCurrency: "JPY",
},
+ OriginalBidCPM: 10,
},
},
},
@@ -1988,6 +2300,7 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
BidId: "uuid",
},
},
+ OriginalBidCPM: 10,
},
},
},
@@ -2017,6 +2330,11 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
name: "valid bid, but json unmarshal fails",
args: args{
ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Cur: []string{},
+ },
+ },
Response: &openrtb2.BidResponse{
SeatBid: []openrtb2.SeatBid{
{
@@ -2046,11 +2364,13 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
BidId: "uuid",
},
},
+ OriginalBidCPM: 10,
},
},
},
},
},
+ CurrencyConversion: func(from, to string, value float64) (float64, error) { return 10, nil },
},
},
partners: map[string][]PartnerRecord{
@@ -2066,6 +2386,7 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
OriginalCur: models.USD,
NetECPM: 10,
GrossECPM: 10,
+ OriginalCPM: 10,
DealPriority: 0,
},
},
@@ -2103,7 +2424,8 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
DealTierSatisfied: true,
},
},
- Nbr: nbr.LossBidLostToHigherBid.Ptr(),
+ OriginalBidCPM: 10,
+ Nbr: nbr.LossBidLostToHigherBid.Ptr(),
},
},
},
@@ -2195,9 +2517,10 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
Ext: openrtb_ext.ExtNonBid{
Prebid: openrtb_ext.ExtNonBidPrebid{
Bid: openrtb_ext.ExtNonBidPrebidBid{
- Price: 10,
- ID: "bid-id-1",
- BidId: "uuid",
+ Price: 10,
+ ID: "bid-id-1",
+ BidId: "uuid",
+ OriginalBidCPM: 10,
},
},
},
@@ -2263,6 +2586,7 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
BidId: "uuid",
},
},
+ OriginalBidCPM: 10,
},
},
},
@@ -2318,6 +2642,9 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
name: "valid bid, but bid.ext is empty",
args: args{
ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{},
+ },
Response: &openrtb2.BidResponse{
SeatBid: []openrtb2.SeatBid{
{
@@ -2352,6 +2679,7 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
},
},
},
+ CurrencyConversion: func(from, to string, value float64) (float64, error) { return 10, nil },
},
},
partners: map[string][]PartnerRecord{
@@ -2367,6 +2695,7 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
OriginalCur: models.USD,
NetECPM: 10,
GrossECPM: 10,
+ OriginalCPM: 10,
DealPriority: 0,
},
},
@@ -2376,6 +2705,9 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
name: "dropped bid, bidExt unmarshal fails",
args: args{
ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{},
+ },
Response: &openrtb2.BidResponse{
SeatBid: []openrtb2.SeatBid{
{
@@ -2410,6 +2742,7 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
},
},
},
+ CurrencyConversion: func(from, to string, value float64) (float64, error) { return 10, nil },
},
},
partners: map[string][]PartnerRecord{
@@ -2425,6 +2758,7 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
OriginalCur: models.USD,
NetECPM: 10,
GrossECPM: 10,
+ OriginalCPM: 10,
DealPriority: 0,
Nbr: nil,
},
@@ -3246,6 +3580,9 @@ func TestGetPartnerRecordsByImpForMarketPlaceBidders(t *testing.T) {
name: "overwrite marketplace bid details",
args: args{
ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{},
+ },
Response: &openrtb2.BidResponse{
SeatBid: []openrtb2.SeatBid{
{
@@ -3294,6 +3631,7 @@ func TestGetPartnerRecordsByImpForMarketPlaceBidders(t *testing.T) {
},
},
},
+ CurrencyConversion: func(from, to string, value float64) (float64, error) { return value, nil },
},
},
partners: map[string][]PartnerRecord{
@@ -3309,6 +3647,7 @@ func TestGetPartnerRecordsByImpForMarketPlaceBidders(t *testing.T) {
OriginalCur: models.USD,
GrossECPM: 1,
NetECPM: 1,
+ OriginalCPM: 1,
KGPV: "apnx_kgpv",
KGPSV: "apnx_kgpv",
},
@@ -3323,6 +3662,7 @@ func TestGetPartnerRecordsByImpForMarketPlaceBidders(t *testing.T) {
OriginalCur: models.USD,
GrossECPM: 2,
NetECPM: 2,
+ OriginalCPM: 2,
KGPV: "pubm_kgpv",
KGPSV: "pubm_kgpv",
},
@@ -3337,6 +3677,7 @@ func TestGetPartnerRecordsByImpForMarketPlaceBidders(t *testing.T) {
OriginalCur: models.USD,
GrossECPM: 3,
NetECPM: 3,
+ OriginalCPM: 3,
KGPV: "pubm_kgpv",
KGPSV: "pubm_kgpv",
},
@@ -4600,129 +4941,129 @@ func TestSlotRecordsInGetLogAuctionObjectAsURL(t *testing.T) {
args args
want want
}{
- // {
- // name: "req.Imp not mapped in ImpBidCtx",
- // args: args{
- // ao: analytics.AuctionObject{
- // RequestWrapper: &openrtb_ext.RequestWrapper{
- // BidRequest: &openrtb2.BidRequest{
- // Imp: []openrtb2.Imp{
- // {
- // ID: "imp1",
- // TagID: "tagid",
- // },
- // },
- // },
- // },
- // Response: &openrtb2.BidResponse{},
- // },
- // rCtx: &models.RequestCtx{
- // Endpoint: models.EndpointV25,
- // PubID: 5890,
- // },
- // logInfo: false,
- // forRespExt: true,
- // },
- // want: want{
- // logger: ow.cfg.Endpoint + `?json={"pubid":5890,"pid":"0","pdvid":"0","sl":1,"dvc":{},"ft":0,"it":"sdk"}&pubid=5890`,
- // header: http.Header{
- // models.USER_AGENT_HEADER: []string{""},
- // models.IP_HEADER: []string{""},
- // },
- // },
- // },
- // {
- // name: "multi imps request",
- // args: args{
- // ao: analytics.AuctionObject{
- // RequestWrapper: &openrtb_ext.RequestWrapper{
- // BidRequest: &openrtb2.BidRequest{
- // Imp: []openrtb2.Imp{
- // {
- // ID: "imp_1",
- // TagID: "tagid_1",
- // },
- // {
- // ID: "imp_2",
- // TagID: "tagid_2",
- // },
- // },
- // },
- // },
- // Response: &openrtb2.BidResponse{},
- // },
- // rCtx: &models.RequestCtx{
- // PubID: 5890,
- // Endpoint: models.EndpointV25,
- // ImpBidCtx: map[string]models.ImpCtx{
- // "imp_1": {
- // SlotName: "imp_1_tagid_1",
- // AdUnitName: "tagid_1",
- // },
- // "imp_2": {
- // AdUnitName: "tagid_2",
- // SlotName: "imp_2_tagid_2",
- // },
- // },
- // },
- // logInfo: false,
- // forRespExt: true,
- // },
- // want: want{
- // logger: ow.cfg.Endpoint + `?json={"pubid":5890,"pid":"0","pdvid":"0","sl":1,"s":[{"sid":"sid","sn":"imp_1_tagid_1","au":"tagid_1","ps":[]},{"sid":"sid","sn":"imp_2_tagid_2","au":"tagid_2","ps":[]}],"dvc":{},"ft":0,"it":"sdk"}&pubid=5890`,
- // header: http.Header{
- // models.USER_AGENT_HEADER: []string{""},
- // models.IP_HEADER: []string{""},
- // },
- // },
- // },
- // {
- // name: "multi imps request and one request has incomingslots",
- // args: args{
- // ao: analytics.AuctionObject{
- // RequestWrapper: &openrtb_ext.RequestWrapper{
- // BidRequest: &openrtb2.BidRequest{
- // Imp: []openrtb2.Imp{
- // {
- // ID: "imp_1",
- // TagID: "tagid_1",
- // },
- // {
- // ID: "imp_2",
- // TagID: "tagid_2",
- // },
- // },
- // },
- // },
- // Response: &openrtb2.BidResponse{},
- // },
- // rCtx: &models.RequestCtx{
- // PubID: 5890,
- // Endpoint: models.EndpointV25,
- // ImpBidCtx: map[string]models.ImpCtx{
- // "imp_1": {
- // IncomingSlots: []string{"0x0v", "100x200"},
- // IsRewardInventory: ptrutil.ToPtr(int8(1)),
- // SlotName: "imp_1_tagid_1",
- // AdUnitName: "tagid_1",
- // },
- // "imp_2": {
- // AdUnitName: "tagid_2",
- // SlotName: "imp_2_tagid_2",
- // },
- // },
- // },
- // logInfo: false,
- // forRespExt: true,
- // },
- // want: want{
- // logger: ow.cfg.Endpoint + `?json={"pubid":5890,"pid":"0","pdvid":"0","sl":1,"s":[{"sid":"sid","sn":"imp_1_tagid_1","sz":["0x0v","100x200"],"au":"tagid_1","ps":[],"rwrd":1},{"sid":"sid","sn":"imp_2_tagid_2","au":"tagid_2","ps":[]}],"dvc":{},"ft":0,"it":"sdk"}&pubid=5890`,
- // header: http.Header{
- // models.USER_AGENT_HEADER: []string{""},
- // models.IP_HEADER: []string{""},
- // },
- // },
- // },
+ {
+ name: "req.Imp not mapped in ImpBidCtx",
+ args: args{
+ ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp1",
+ TagID: "tagid",
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{},
+ },
+ rCtx: &models.RequestCtx{
+ Endpoint: models.EndpointV25,
+ PubID: 5890,
+ },
+ logInfo: false,
+ forRespExt: true,
+ },
+ want: want{
+ logger: ow.cfg.Endpoint + `?json={"pubid":5890,"pid":"0","pdvid":"0","sl":1,"dvc":{},"ft":0,"it":"sdk"}&pubid=5890`,
+ header: http.Header{
+ models.USER_AGENT_HEADER: []string{""},
+ models.IP_HEADER: []string{""},
+ },
+ },
+ },
+ {
+ name: "multi imps request",
+ args: args{
+ ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp_1",
+ TagID: "tagid_1",
+ },
+ {
+ ID: "imp_2",
+ TagID: "tagid_2",
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{},
+ },
+ rCtx: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ SlotName: "imp_1_tagid_1",
+ AdUnitName: "tagid_1",
+ },
+ "imp_2": {
+ AdUnitName: "tagid_2",
+ SlotName: "imp_2_tagid_2",
+ },
+ },
+ },
+ logInfo: false,
+ forRespExt: true,
+ },
+ want: want{
+ logger: ow.cfg.Endpoint + `?json={"pubid":5890,"pid":"0","pdvid":"0","sl":1,"s":[{"sid":"sid","sn":"imp_1_tagid_1","au":"tagid_1","ps":[]},{"sid":"sid","sn":"imp_2_tagid_2","au":"tagid_2","ps":[]}],"dvc":{},"ft":0,"it":"sdk"}&pubid=5890`,
+ header: http.Header{
+ models.USER_AGENT_HEADER: []string{""},
+ models.IP_HEADER: []string{""},
+ },
+ },
+ },
+ {
+ name: "multi imps request and one request has incomingslots",
+ args: args{
+ ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp_1",
+ TagID: "tagid_1",
+ },
+ {
+ ID: "imp_2",
+ TagID: "tagid_2",
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{},
+ },
+ rCtx: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ IncomingSlots: []string{"0x0v", "100x200"},
+ IsRewardInventory: ptrutil.ToPtr(int8(1)),
+ SlotName: "imp_1_tagid_1",
+ AdUnitName: "tagid_1",
+ },
+ "imp_2": {
+ AdUnitName: "tagid_2",
+ SlotName: "imp_2_tagid_2",
+ },
+ },
+ },
+ logInfo: false,
+ forRespExt: true,
+ },
+ want: want{
+ logger: ow.cfg.Endpoint + `?json={"pubid":5890,"pid":"0","pdvid":"0","sl":1,"s":[{"sid":"sid","sn":"imp_1_tagid_1","sz":["0x0v","100x200"],"au":"tagid_1","ps":[],"rwrd":1},{"sid":"sid","sn":"imp_2_tagid_2","au":"tagid_2","ps":[]}],"dvc":{},"ft":0,"it":"sdk"}&pubid=5890`,
+ header: http.Header{
+ models.USER_AGENT_HEADER: []string{""},
+ models.IP_HEADER: []string{""},
+ },
+ },
+ },
{
name: "multi imps request and one imp has partner record",
args: args{
@@ -4943,3 +5284,97 @@ func Test_getFloorValueFromUpdatedRequest(t *testing.T) {
})
}
}
+
+func TestGetBidPriceAfterCurrencyConversion(t *testing.T) {
+ type args struct {
+ price float64
+ requestCurrencies []string
+ responseCurrency string
+ currencyConverter func(fromCurrency string, toCurrency string, value float64) (float64, error)
+ }
+ tests := []struct {
+ name string
+ args args
+ want float64
+ }{
+ {
+ name: "Single request currency - successful conversion",
+ args: args{
+ price: 100.0,
+ requestCurrencies: []string{"EUR"},
+ responseCurrency: "USD",
+ currencyConverter: func(fromCurrency string, toCurrency string, value float64) (float64, error) {
+ if fromCurrency == "USD" && toCurrency == "EUR" {
+ return 85.0, nil // Assuming conversion rate USD to EUR is 0.85
+ }
+ return 0, fmt.Errorf("unsupported conversion")
+ },
+ },
+ want: 85.0,
+ },
+ {
+ name: "Multiple request currencies - first successful conversion",
+ args: args{
+ price: 100.0,
+ requestCurrencies: []string{"EUR", "GBP"},
+ responseCurrency: "USD",
+ currencyConverter: func(fromCurrency string, toCurrency string, value float64) (float64, error) {
+ if fromCurrency == "USD" && toCurrency == "EUR" {
+ return 85.0, nil // Successful conversion to EUR
+ }
+ return 0, fmt.Errorf("unsupported conversion")
+ },
+ },
+ want: 85.0,
+ },
+ {
+ name: "Multiple request currencies - second successful conversion",
+ args: args{
+ price: 100.0,
+ requestCurrencies: []string{"JPY", "GBP"},
+ responseCurrency: "USD",
+ currencyConverter: func(fromCurrency string, toCurrency string, value float64) (float64, error) {
+ if fromCurrency == "USD" && toCurrency == "GBP" {
+ return 75.0, nil // Successful conversion to GBP
+ }
+ return 0, fmt.Errorf("unsupported conversion")
+ },
+ },
+ want: 75.0,
+ },
+ {
+ name: "No request currencies provided - default to USD",
+ args: args{
+ price: 100.0,
+ requestCurrencies: []string{},
+ responseCurrency: "USD",
+ currencyConverter: func(fromCurrency string, toCurrency string, value float64) (float64, error) {
+ if fromCurrency == "USD" && toCurrency == "USD" {
+ return 100.0, nil // No conversion needed
+ }
+ return 0, fmt.Errorf("unsupported conversion")
+ },
+ },
+ want: 100.0,
+ },
+ {
+ name: "Conversion fails for all currencies",
+ args: args{
+ price: 100.0,
+ requestCurrencies: []string{"JPY", "CNY"},
+ responseCurrency: "USD",
+ currencyConverter: func(fromCurrency string, toCurrency string, value float64) (float64, error) {
+ return 0, fmt.Errorf("conversion failed")
+ },
+ },
+ want: 0.0, // Default to 0 on failure
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := GetBidPriceAfterCurrencyConversion(tt.args.price, tt.args.requestCurrencies, tt.args.responseCurrency, tt.args.currencyConverter)
+ assert.Equal(t, tt.want, got, "mismatched price")
+ })
+ }
+}
diff --git a/config/config.go b/config/config.go
index bf98f35f406..e9f200a8341 100644
--- a/config/config.go
+++ b/config/config.go
@@ -675,10 +675,10 @@ type Debug struct {
}
type Server struct {
- ExternalUrl string
- GvlID int
- DataCenter string
- EnableFastXML bool
+ ExternalUrl string
+ GvlID int
+ DataCenter string
+ FastXMLEnabledPercentage int
}
func (server *Server) Empty() bool {
diff --git a/config/config_ow.go b/config/config_ow.go
index 562208ba0ca..5121f1f6095 100644
--- a/config/config_ow.go
+++ b/config/config_ow.go
@@ -2,10 +2,10 @@ package config
type OpenWrapConfig struct {
// OpenWrap Configurations
- EnableFastXML bool `mapstructure:"enable_fast_xml"`
- TrackerURL string `mapstructure:"tracker_url"`
- VendorListScheduler VendorListScheduler `mapstructure:"vendor_list_scheduler"`
- PriceFloorFetcher PriceFloorFetcher `mapstructure:"price_floor_fetcher"`
+ FastXMLEnabledPercentage int `mapstructure:"fast_xml_enabled_percentage"`
+ TrackerURL string `mapstructure:"tracker_url"`
+ VendorListScheduler VendorListScheduler `mapstructure:"vendor_list_scheduler"`
+ PriceFloorFetcher PriceFloorFetcher `mapstructure:"price_floor_fetcher"`
}
type PriceFloorFetcher struct {
diff --git a/endpoints/events/events_ow.go b/endpoints/events/events_ow.go
new file mode 100644
index 00000000000..00a7ba726ef
--- /dev/null
+++ b/endpoints/events/events_ow.go
@@ -0,0 +1,192 @@
+package events
+
+import (
+ "encoding/json"
+ "net/url"
+ "strings"
+
+ "github.com/golang/glog"
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
+)
+
+// standard VAST macros
+// https://interactiveadvertisingbureau.github.io/vast/vast4macros/vast4-macros-latest.html#macro-spec-adcount
+const (
+ VASTAdTypeMacro = "[ADTYPE]" //VASTAdTypeMacro openwrap macro for ADTYPE
+ VASTAppBundleMacro = "[APPBUNDLE]" //VASTAppBundleMacro openwrap macro for APPBUNDLE
+ VASTDomainMacro = "[DOMAIN]" //VASTDomainMacro openwrap macro for DOMAIN
+ VASTPageURLMacro = "[PAGEURL]" //VASTPageURLMacro openwrap macro for PAGEURL
+ PBSEventIDMacro = "[EVENT_ID]" // PBSEventIDMacro macro for injecting PBS defined video event tracker id
+ PBSAccountMacro = "[PBS-ACCOUNT]" // PBSAccountMacro represents publisher id / account id
+ PBSBidderMacro = "[PBS-BIDDER]" // PBSBidderMacro represents bidder name
+ PBSOrigBidIDMacro = "[PBS-ORIG_BIDID]" // PBSOrigBidIDMacro represents original bid id.
+ PBSBidIDMacro = "[PBS-BIDID]" // PBSBidIDMacro represents bid id. If auction.generate-bid-id config is on, then resolve with response.seatbid.bid.ext.prebid.bidid. Else replace with response.seatbid.bid.id
+ PBSAdvertiserNameMacro = "[ADVERTISER_NAME]" // [ADERVERTISER_NAME] represents advertiser name
+ PBSAdUnitIDMacro = "[AD_UNIT]" // PBSAdUnitIDMacro Pass imp.tagId using this macro
+ PBSBidderCodeMacro = "[BIDDER_CODE]" // PBSBidderCodeMacro represents an alias id or core bidder id.
+)
+
+// PubMatic specific event IDs
+// This will go in event-config once PreBid modular design is in place
+var trackingEventIDMap = map[string]string{
+ "start": "2",
+ "firstQuartile": "4",
+ "midpoint": "3",
+ "thirdQuartile": "5",
+ "complete": "6",
+}
+
+var trackingEvents = []string{"start", "firstQuartile", "midpoint", "thirdQuartile", "complete"}
+
+// GetVideoEventTracking returns map containing key as event name value as associaed video event tracking URL
+// By default PBS will expect [EVENT_ID] macro in trackerURL to inject event information
+// [EVENT_ID] will be injected with one of the following values
+//
+// firstQuartile, midpoint, thirdQuartile, complete
+//
+// If your company can not use [EVENT_ID] and has its own macro. provide config.TrackerMacros implementation
+// and ensure that your macro is part of trackerURL configuration
+// GetVideoEventTracking returns map containing key as event name value as associaed video event tracking URL
+// By default PBS will expect [EVENT_ID] macro in trackerURL to inject event information
+// [EVENT_ID] will be injected with one of the following values
+//
+// firstQuartile, midpoint, thirdQuartile, complete
+//
+// If your company can not use [EVENT_ID] and has its own macro. provide config.TrackerMacros implementation
+// and ensure that your macro is part of trackerURL configuration
+func GetVideoEventTracking(
+ req *openrtb2.BidRequest,
+ imp *openrtb2.Imp,
+ bid *openrtb2.Bid,
+ trackerURL string,
+ prebidGenBidId, requestingBidder, bidderCoreName string,
+ timestamp int64) map[string]string {
+
+ if req == nil || imp == nil || bid == nil || strings.TrimSpace(trackerURL) == "" {
+ return nil
+ }
+
+ // replace standard macros
+ // NYC shall we put all macros with their default values here?
+ macroMap := map[string]string{
+ PBSAdUnitIDMacro: imp.TagID,
+ PBSBidIDMacro: bid.ID,
+ PBSOrigBidIDMacro: bid.ID,
+ PBSBidderMacro: bidderCoreName,
+ PBSBidderCodeMacro: requestingBidder,
+ PBSAdvertiserNameMacro: "",
+ VASTAdTypeMacro: string(openrtb_ext.BidTypeVideo),
+ }
+
+ /* Use generated bidId if present, else use bid.ID */
+ if len(prebidGenBidId) > 0 && prebidGenBidId != bid.ID {
+ macroMap[PBSBidIDMacro] = prebidGenBidId
+ }
+
+ if len(bid.ADomain) > 0 {
+ var err error
+ //macroMap[PBSAdvertiserNameMacro] = strings.Join(bid.ADomain, ",")
+ macroMap[PBSAdvertiserNameMacro], err = extractDomain(bid.ADomain[0])
+ if err != nil {
+ glog.Warningf("Unable to extract domain from '%s'. [%s]", bid.ADomain[0], err.Error())
+ }
+ }
+
+ if req.App != nil {
+ // macroMap[VASTAppBundleMacro] = req.App.Bundle
+ macroMap[VASTDomainMacro] = req.App.Bundle
+ if req.App.Publisher != nil {
+ macroMap[PBSAccountMacro] = req.App.Publisher.ID
+ }
+ } else if req.Site != nil {
+ macroMap[VASTDomainMacro] = getDomain(req.Site)
+ macroMap[VASTPageURLMacro] = req.Site.Page
+ if req.Site.Publisher != nil {
+ macroMap[PBSAccountMacro] = req.Site.Publisher.ID
+ }
+ }
+
+ // lookup in custom macros - keep this block at last for highest priority
+ var reqExt openrtb_ext.ExtRequest
+ if req.Ext != nil {
+ err := json.Unmarshal(req.Ext, &reqExt)
+ if err != nil {
+ glog.Warningf("Error in unmarshling req.Ext.Prebid.Vast: [%s]", err.Error())
+ }
+ }
+ for key, value := range reqExt.Prebid.Macros {
+ macroMap[strings.TrimSpace(key)] = strings.TrimSpace(value)
+ }
+
+ eventURLMap := make(map[string]string)
+ for name, id := range trackingEventIDMap { // NYC check if trackingEvents and macroMap can be clubbed
+ // replace [EVENT_ID] macro with PBS defined event ID
+ macroMap[PBSEventIDMacro] = id
+ eventURLMap[name] = replaceMacros(trackerURL, macroMap)
+ }
+ return eventURLMap
+}
+
+func replaceMacros(trackerURL string, macroMap map[string]string) string {
+ var builder strings.Builder
+
+ for i := 0; i < len(trackerURL); i++ {
+ if trackerURL[i] == '[' {
+ found := false
+ j := i + 1
+ for ; j < len(trackerURL); j++ {
+ if trackerURL[j] == ']' {
+ found = true
+ break
+ }
+ }
+ if found {
+ n := j + 1
+ k := trackerURL[i:n]
+ if v, ok := macroMap[k]; ok {
+ v = url.QueryEscape(v) // NYC move QueryEscape while creating map, no need to do this everytime
+ _, _ = builder.Write([]byte(v))
+ i = j
+ continue
+ }
+ }
+ }
+ _ = builder.WriteByte(trackerURL[i])
+ }
+
+ return builder.String()
+}
+
+func extractDomain(rawURL string) (string, error) {
+ if !strings.HasPrefix(rawURL, "http") {
+ rawURL = "http://" + rawURL
+ }
+ // decode rawURL
+ rawURL, err := url.QueryUnescape(rawURL)
+ if nil != err {
+ return "", err
+ }
+ url, err := url.Parse(rawURL)
+ if nil != err {
+ return "", err
+ }
+ // remove www if present
+ return strings.TrimPrefix(url.Hostname(), "www."), nil
+}
+
+func getDomain(site *openrtb2.Site) string {
+ if site.Domain != "" {
+ return site.Domain
+ }
+
+ hostname := ""
+
+ if site.Page != "" {
+ pageURL, err := url.Parse(site.Page)
+ if err == nil && pageURL != nil {
+ hostname = pageURL.Host
+ }
+ }
+ return hostname
+}
diff --git a/endpoints/events/events_ow_test.go b/endpoints/events/events_ow_test.go
new file mode 100644
index 00000000000..300e3ed01b2
--- /dev/null
+++ b/endpoints/events/events_ow_test.go
@@ -0,0 +1,591 @@
+package events
+
+import (
+ "testing"
+
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetVideoEventTracking(t *testing.T) {
+ type args struct {
+ trackerURL string
+ bid *openrtb2.Bid
+ requestingBidder string
+ gen_bidid string
+ bidderCoreName string
+ timestamp int64
+ req *openrtb2.BidRequest
+ }
+ type want struct {
+ trackerURLMap map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want want
+ }{
+ {
+ name: "valid_scenario",
+ args: args{
+ trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ bid: &openrtb2.Bid{
+ // AdM: vastXMLWith2Creatives,
+ },
+ req: &openrtb2.BidRequest{
+ App: &openrtb2.App{
+ Bundle: "someappbundle",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=someappbundle",
+ "midpoint": "http://company.tracker.com?eventId=3&appbundle=someappbundle",
+ "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=someappbundle",
+ "start": "http://company.tracker.com?eventId=2&appbundle=someappbundle",
+ "complete": "http://company.tracker.com?eventId=6&appbundle=someappbundle"},
+ },
+ },
+ {
+ name: "no_macro_value", // expect no replacement
+ args: args{
+ trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ App: &openrtb2.App{}, // no app bundle value
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=",
+ "midpoint": "http://company.tracker.com?eventId=3&appbundle=",
+ "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=",
+ "start": "http://company.tracker.com?eventId=2&appbundle=",
+ "complete": "http://company.tracker.com?eventId=6&appbundle="},
+ },
+ },
+ {
+ name: "prefer_company_value_for_standard_macro",
+ args: args{
+ trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ App: &openrtb2.App{
+ Bundle: "myapp", // do not expect this value
+ },
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ Ext: []byte(`{"prebid":{
+ "macros": {
+ "[DOMAIN]": "my_custom_value"
+ }
+ }}`),
+ },
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=my_custom_value",
+ "midpoint": "http://company.tracker.com?eventId=3&appbundle=my_custom_value",
+ "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=my_custom_value",
+ "start": "http://company.tracker.com?eventId=2&appbundle=my_custom_value",
+ "complete": "http://company.tracker.com?eventId=6&appbundle=my_custom_value"},
+ },
+ },
+ {
+ name: "multireplace_macro",
+ args: args{
+ trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]¶meter2=[DOMAIN]",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ App: &openrtb2.App{
+ Bundle: "myapp123",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=myapp123¶meter2=myapp123",
+ "midpoint": "http://company.tracker.com?eventId=3&appbundle=myapp123¶meter2=myapp123",
+ "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=myapp123¶meter2=myapp123",
+ "start": "http://company.tracker.com?eventId=2&appbundle=myapp123¶meter2=myapp123",
+ "complete": "http://company.tracker.com?eventId=6&appbundle=myapp123¶meter2=myapp123"},
+ },
+ },
+ {
+ name: "custom_macro_without_prefix_and_suffix",
+ args: args{
+ trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]¶m1=[CUSTOM_MACRO]",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ Ext: []byte(`{"prebid":{
+ "macros": {
+ "CUSTOM_MACRO": "my_custom_value"
+ }
+ }}`),
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "http://company.tracker.com?eventId=4¶m1=[CUSTOM_MACRO]",
+ "midpoint": "http://company.tracker.com?eventId=3¶m1=[CUSTOM_MACRO]",
+ "thirdQuartile": "http://company.tracker.com?eventId=5¶m1=[CUSTOM_MACRO]",
+ "start": "http://company.tracker.com?eventId=2¶m1=[CUSTOM_MACRO]",
+ "complete": "http://company.tracker.com?eventId=6¶m1=[CUSTOM_MACRO]"},
+ },
+ },
+ {
+ name: "empty_macro",
+ args: args{
+ trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]¶m1=[CUSTOM_MACRO]",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ Ext: []byte(`{"prebid":{
+ "macros": {
+ "": "my_custom_value"
+ }
+ }}`),
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "http://company.tracker.com?eventId=4¶m1=[CUSTOM_MACRO]",
+ "midpoint": "http://company.tracker.com?eventId=3¶m1=[CUSTOM_MACRO]",
+ "thirdQuartile": "http://company.tracker.com?eventId=5¶m1=[CUSTOM_MACRO]",
+ "start": "http://company.tracker.com?eventId=2¶m1=[CUSTOM_MACRO]",
+ "complete": "http://company.tracker.com?eventId=6¶m1=[CUSTOM_MACRO]"},
+ },
+ },
+ {
+ name: "macro_is_case_sensitive",
+ args: args{
+ trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]¶m1=[CUSTOM_MACRO]",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ Ext: []byte(`{"prebid":{
+ "macros": {
+ "": "my_custom_value"
+ }
+ }}`),
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "http://company.tracker.com?eventId=4¶m1=[CUSTOM_MACRO]",
+ "midpoint": "http://company.tracker.com?eventId=3¶m1=[CUSTOM_MACRO]",
+ "thirdQuartile": "http://company.tracker.com?eventId=5¶m1=[CUSTOM_MACRO]",
+ "start": "http://company.tracker.com?eventId=2¶m1=[CUSTOM_MACRO]",
+ "complete": "http://company.tracker.com?eventId=6¶m1=[CUSTOM_MACRO]"},
+ },
+ },
+ {
+ name: "empty_tracker_url",
+ args: args{
+ trackerURL: " ",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ trackerURLMap: nil,
+ },
+ },
+ {
+ name: "site_domain_tracker_url",
+ args: args{
+ trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]",
+ bid: &openrtb2.Bid{},
+ req: &openrtb2.BidRequest{
+ Site: &openrtb2.Site{
+ Name: "test",
+ Domain: "www.test.com",
+ Publisher: &openrtb2.Publisher{
+ ID: "5890"},
+ },
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ map[string]string{
+ "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ },
+ },
+ },
+ {
+ name: "site_page_tracker_url",
+ args: args{trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]",
+ bid: &openrtb2.Bid{}, req: &openrtb2.BidRequest{
+ Site: &openrtb2.Site{
+ Name: "test",
+ Page: "https://www.test.com/",
+ Publisher: &openrtb2.Publisher{
+ ID: "5890",
+ },
+ },
+ Imp: []openrtb2.Imp{
+ {
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ },
+ want: want{
+ map[string]string{
+ "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ },
+ },
+ },
+ {
+ name: "all_macros with generated_bidId", // expect encoding for WRAPPER_IMPRESSION_ID macro
+ args: args{
+ trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]&origbidid=[PBS-ORIG_BIDID]&bc=[BIDDER_CODE]",
+ req: &openrtb2.BidRequest{
+ App: &openrtb2.App{Bundle: "com.someapp.com", Publisher: &openrtb2.Publisher{ID: "5890"}},
+ Ext: []byte(`{
+ "prebid": {
+ "macros": {
+ "[PROFILE_ID]": "100",
+ "[PROFILE_VERSION]": "2",
+ "[UNIX_TIMESTAMP]": "1234567890",
+ "[PLATFORM]": "7",
+ "[WRAPPER_IMPRESSION_ID]": "abc~!@#$%^&&*()_+{}|:\"<>?[]\\;',./"
+ }
+ }
+ }`),
+ Imp: []openrtb2.Imp{
+ {
+ TagID: "/testadunit/1",
+ ID: "imp_1",
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ bid: &openrtb2.Bid{ADomain: []string{"http://a.com/32?k=v", "b.com"}, ImpID: "imp_1", ID: "test_bid_id"},
+ gen_bidid: "random_bid_id",
+ requestingBidder: "test_bidder:234",
+ bidderCoreName: "test_core_bidder:234",
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234"},
+ },
+ },
+ {
+ name: "all_macros with empty generated_bidId", // expect encoding for WRAPPER_IMPRESSION_ID macro
+ args: args{
+ trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]&origbidid=[PBS-ORIG_BIDID]&bc=[BIDDER_CODE]",
+ req: &openrtb2.BidRequest{
+ App: &openrtb2.App{
+ Bundle: "com.someapp.com",
+ Publisher: &openrtb2.Publisher{
+ ID: "5890",
+ },
+ },
+ Ext: []byte(`{
+ "prebid": {
+ "macros": {
+ "[PROFILE_ID]": "100",
+ "[PROFILE_VERSION]": "2",
+ "[UNIX_TIMESTAMP]": "1234567890",
+ "[PLATFORM]": "7",
+ "[WRAPPER_IMPRESSION_ID]": "abc~!@#$%^&&*()_+{}|:\"<>?[]\\;',./"
+ }
+ }
+ }`),
+ Imp: []openrtb2.Imp{
+ {
+ TagID: "/testadunit/1",
+ ID: "imp_1",
+ Video: &openrtb2.Video{},
+ },
+ },
+ },
+ bid: &openrtb2.Bid{ADomain: []string{"http://a.com/32?k=v", "b.com"}, ImpID: "imp_1", ID: "test_bid_id"},
+ gen_bidid: "",
+ requestingBidder: "test_bidder:234",
+ bidderCoreName: "test_core_bidder:234",
+ },
+ want: want{
+ trackerURLMap: map[string]string{
+ "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
+ "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234"},
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ eventURLMap := GetVideoEventTracking(tc.args.req, &tc.args.req.Imp[0], tc.args.bid, tc.args.trackerURL, tc.args.gen_bidid, tc.args.requestingBidder, tc.args.bidderCoreName, tc.args.timestamp)
+ assert.Equal(t, tc.want.trackerURLMap, eventURLMap)
+ })
+ }
+}
+
+func TestExtractDomain(t *testing.T) {
+ testCases := []struct {
+ description string
+ url string
+ expectedDomain string
+ expectedErr error
+ }{
+ {description: "a.com", url: "a.com", expectedDomain: "a.com", expectedErr: nil},
+ {description: "a.com/123", url: "a.com/123", expectedDomain: "a.com", expectedErr: nil},
+ {description: "http://a.com/123", url: "http://a.com/123", expectedDomain: "a.com", expectedErr: nil},
+ {description: "https://a.com/123", url: "https://a.com/123", expectedDomain: "a.com", expectedErr: nil},
+ {description: "c.b.a.com", url: "c.b.a.com", expectedDomain: "c.b.a.com", expectedErr: nil},
+ {description: "url_encoded_http://c.b.a.com", url: "http%3A%2F%2Fc.b.a.com", expectedDomain: "c.b.a.com", expectedErr: nil},
+ {description: "url_encoded_with_www_http://c.b.a.com", url: "http%3A%2F%2Fwww.c.b.a.com", expectedDomain: "c.b.a.com", expectedErr: nil},
+ }
+ for _, test := range testCases {
+ t.Run(test.description, func(t *testing.T) {
+ domain, err := extractDomain(test.url)
+ assert.Equal(t, test.expectedDomain, domain)
+ assert.Equal(t, test.expectedErr, err)
+ })
+ }
+}
+
+// replaceMacros copied test cases from older replaceMacro(), will use gofuzzy once golang is upgraded
+func Test_replaceMacros(t *testing.T) {
+ type args struct {
+ trackerURL string
+ macroMap map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "empty_tracker_url",
+ args: args{
+ trackerURL: "",
+ macroMap: map[string]string{
+ "[TEST]": "testme",
+ },
+ },
+ want: "",
+ },
+ {
+ name: "tracker_url_with_macro",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]",
+ macroMap: map[string]string{
+ "[TEST]": "testme",
+ },
+ },
+ want: "http://something.com?test=testme",
+ },
+ {
+ name: "tracker_url_with_invalid_macro",
+ args: args{
+ trackerURL: "http://something.com?test=TEST]",
+ macroMap: map[string]string{
+ "[TEST]": "testme",
+ },
+ },
+ want: "http://something.com?test=TEST]",
+ },
+ {
+ name: "tracker_url_with_repeating_macro",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]&test1=[TEST]",
+ macroMap: map[string]string{
+ "[TEST]": "testme",
+ },
+ },
+ want: "http://something.com?test=testme&test1=testme",
+ },
+ {
+ name: "empty_macro",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]",
+ macroMap: map[string]string{
+ "": "testme",
+ },
+ },
+ want: "http://something.com?test=[TEST]",
+ },
+ {
+ name: "macro_without_[",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]",
+ macroMap: map[string]string{
+ "TEST]": "testme",
+ },
+ },
+ want: "http://something.com?test=[TEST]",
+ },
+ {
+ name: "macro_without_]",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]",
+ macroMap: map[string]string{
+ "[TEST": "testme",
+ },
+ },
+ want: "http://something.com?test=[TEST]",
+ },
+ {
+ name: "empty_value",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]",
+ macroMap: map[string]string{
+ "[TEST]": ""},
+ },
+ want: "http://something.com?test=",
+ },
+ {
+ name: "nested_macro_value",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]",
+ macroMap: map[string]string{
+ "[TEST]": "[TEST][TEST]",
+ },
+ },
+ want: "http://something.com?test=%5BTEST%5D%5BTEST%5D",
+ },
+ {
+ name: "url_as_macro_value",
+ args: args{
+ trackerURL: "http://something.com?test=[TEST]",
+ macroMap: map[string]string{
+ "[TEST]": "http://iamurl.com",
+ },
+ },
+ want: "http://something.com?test=http%3A%2F%2Fiamurl.com",
+ },
+ // { Moved this responsiblity to GetVideoEventTracking()
+ // name: "macro_with_spaces",
+ // args: args{
+ // trackerURL: "http://something.com?test=[TEST]",
+ // macroMap: map[string]string{
+ // " [TEST] ": "http://iamurl.com",
+ // },
+ // },
+ // want: "http://something.com?test=http%3A%2F%2Fiamurl.com",
+ // },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := replaceMacros(tt.args.trackerURL, tt.args.macroMap)
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
+
+// BenchmarkGetVideoEventTracking
+//
+// Original:
+// Running tool: /usr/local/go/bin/go test -benchmem -run=^$ -bench ^BenchmarkGetVideoEventTracking$ github.com/PubMatic-OpenWrap/prebid-server/endpoints/events
+
+// goos: linux
+// goarch: arm64
+// pkg: github.com/PubMatic-OpenWrap/prebid-server/endpoints/events
+// BenchmarkGetVideoEventTracking-8 19048 78882 ns/op 31590 B/op 128 allocs/op
+// BenchmarkGetVideoEventTracking-8 27333 40491 ns/op 31589 B/op 128 allocs/op
+// BenchmarkGetVideoEventTracking-8 28392 45111 ns/op 31586 B/op 128 allocs/op
+// BenchmarkGetVideoEventTracking-8 18160 83581 ns/op 31585 B/op 128 allocs/op
+// BenchmarkGetVideoEventTracking-8 16633 77993 ns/op 31591 B/op 128 allocs/op
+// PASS
+// ok github.com/PubMatic-OpenWrap/prebid-server/endpoints/events 1.807s
+
+// Refactored-GetVideoEventTracking:
+// BenchmarkGetVideoEventTracking-8 10000 108697 ns/op 33489 B/op 131 allocs/op
+// BenchmarkGetVideoEventTracking-8 10000 115349 ns/op 33489 B/op 131 allocs/op
+// BenchmarkGetVideoEventTracking-8 12678 80833 ns/op 33486 B/op 131 allocs/op
+// BenchmarkGetVideoEventTracking-8 18840 60841 ns/op 33493 B/op 131 allocs/op
+// BenchmarkGetVideoEventTracking-8 20086 57733 ns/op 33482 B/op 131 allocs/op
+
+// Refactored-GetVideoEventTracking-using-replaceMacros:
+// BenchmarkGetVideoEventTracking-8 65928 16866 ns/op 10434 B/op 96 allocs/op
+// BenchmarkGetVideoEventTracking-8 66710 18611 ns/op 10433 B/op 96 allocs/op
+// BenchmarkGetVideoEventTracking-8 66448 17244 ns/op 10433 B/op 96 allocs/op
+// BenchmarkGetVideoEventTracking-8 35112 38085 ns/op 10433 B/op 96 allocs/op
+// BenchmarkGetVideoEventTracking-8 40941 27584 ns/op 10434 B/op 96 allocs/op
+func BenchmarkGetVideoEventTracking(b *testing.B) {
+ // all_macros with generated_bidId
+ trackerURL := "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]&origbidid=[PBS-ORIG_BIDID]&bc=[BIDDER_CODE]"
+ req := &openrtb2.BidRequest{
+ App: &openrtb2.App{Bundle: "com.someapp.com", Publisher: &openrtb2.Publisher{ID: "5890"}},
+ Ext: []byte(`{
+ "prebid": {
+ "macros": {
+ "[PROFILE_ID]": "100",
+ "[PROFILE_VERSION]": "2",
+ "[UNIX_TIMESTAMP]": "1234567890",
+ "[PLATFORM]": "7",
+ "[WRAPPER_IMPRESSION_ID]": "abc~!@#$%^&&*()_+{}|:\"<>?[]\\;',./"
+ }
+ }
+ }`),
+ Imp: []openrtb2.Imp{
+ {TagID: "/testadunit/1", ID: "imp_1"},
+ },
+ }
+ bid := &openrtb2.Bid{ADomain: []string{"http://a.com/32?k=v", "b.com"}, ImpID: "imp_1", ID: "test_bid_id"}
+ gen_bidid := "random_bid_id"
+ requestingBidder := "test_bidder:234"
+ bidderCoreName := "test_core_bidder:234"
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _ = GetVideoEventTracking(req, &req.Imp[0], bid, trackerURL, gen_bidid, requestingBidder, bidderCoreName, 0)
+ }
+}
diff --git a/endpoints/events/test/benchmark_results.txt b/endpoints/events/test/benchmark_results.txt
new file mode 100644
index 00000000000..adc5267405e
--- /dev/null
+++ b/endpoints/events/test/benchmark_results.txt
@@ -0,0 +1,415 @@
+NEW
+---
+goos: linux
+goarch: arm64
+pkg: github.com/PubMatic-OpenWrap/prebid-server/endpoints/events
+BenchmarkInjectVideoEventTrackers-8 11994 99857 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108619 ns/op
+BenchmarkInjectVideoEventTrackers-8 7047 162741 ns/op
+BenchmarkInjectVideoEventTrackers-8 6451 156722 ns/op
+BenchmarkInjectVideoEventTrackers-8 8053 149871 ns/op
+BenchmarkInjectVideoEventTrackers-8 12775 95663 ns/op
+BenchmarkInjectVideoEventTrackers-8 12192 98921 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 119874 ns/op
+BenchmarkInjectVideoEventTrackers-8 8976 148432 ns/op
+BenchmarkInjectVideoEventTrackers-8 12175 104665 ns/op
+BenchmarkInjectVideoEventTrackers-8 12627 96783 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 142767 ns/op
+BenchmarkInjectVideoEventTrackers-8 8652 130018 ns/op
+BenchmarkInjectVideoEventTrackers-8 12621 94379 ns/op
+BenchmarkInjectVideoEventTrackers-8 12541 95631 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 145282 ns/op
+BenchmarkInjectVideoEventTrackers-8 12675 95240 ns/op
+BenchmarkInjectVideoEventTrackers-8 12620 93739 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 140531 ns/op
+BenchmarkInjectVideoEventTrackers-8 7932 134085 ns/op
+BenchmarkInjectVideoEventTrackers-8 12958 94909 ns/op
+BenchmarkInjectVideoEventTrackers-8 12896 100047 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 150835 ns/op
+BenchmarkInjectVideoEventTrackers-8 11193 93567 ns/op
+BenchmarkInjectVideoEventTrackers-8 12614 95702 ns/op
+BenchmarkInjectVideoEventTrackers-8 11172 147317 ns/op
+BenchmarkInjectVideoEventTrackers-8 10274 98216 ns/op
+BenchmarkInjectVideoEventTrackers-8 12525 94558 ns/op
+BenchmarkInjectVideoEventTrackers-8 12091 135374 ns/op
+BenchmarkInjectVideoEventTrackers-8 12649 92635 ns/op
+BenchmarkInjectVideoEventTrackers-8 12672 93532 ns/op
+BenchmarkInjectVideoEventTrackers-8 9829 160558 ns/op
+BenchmarkInjectVideoEventTrackers-8 9627 109390 ns/op
+BenchmarkInjectVideoEventTrackers-8 12559 95794 ns/op
+BenchmarkInjectVideoEventTrackers-8 12118 99115 ns/op
+BenchmarkInjectVideoEventTrackers-8 12313 96845 ns/op
+BenchmarkInjectVideoEventTrackers-8 12039 108354 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107922 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 130093 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109274 ns/op
+BenchmarkInjectVideoEventTrackers-8 12277 99076 ns/op
+BenchmarkInjectVideoEventTrackers-8 12220 97172 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106413 ns/op
+BenchmarkInjectVideoEventTrackers-8 12284 96475 ns/op
+BenchmarkInjectVideoEventTrackers-8 12369 97243 ns/op
+BenchmarkInjectVideoEventTrackers-8 12033 102589 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 101835 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 111323 ns/op
+BenchmarkInjectVideoEventTrackers-8 12139 102415 ns/op
+BenchmarkInjectVideoEventTrackers-8 12520 99148 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102187 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103977 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 117965 ns/op
+BenchmarkInjectVideoEventTrackers-8 12621 96923 ns/op
+BenchmarkInjectVideoEventTrackers-8 12276 97474 ns/op
+BenchmarkInjectVideoEventTrackers-8 12496 97902 ns/op
+BenchmarkInjectVideoEventTrackers-8 12639 95111 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105928 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107623 ns/op
+BenchmarkInjectVideoEventTrackers-8 12416 96683 ns/op
+BenchmarkInjectVideoEventTrackers-8 12476 94106 ns/op
+BenchmarkInjectVideoEventTrackers-8 12526 98440 ns/op
+BenchmarkInjectVideoEventTrackers-8 12543 98846 ns/op
+BenchmarkInjectVideoEventTrackers-8 12445 96899 ns/op
+BenchmarkInjectVideoEventTrackers-8 12355 96749 ns/op
+BenchmarkInjectVideoEventTrackers-8 12783 94215 ns/op
+BenchmarkInjectVideoEventTrackers-8 12560 101970 ns/op
+BenchmarkInjectVideoEventTrackers-8 12759 95018 ns/op
+BenchmarkInjectVideoEventTrackers-8 12870 95196 ns/op
+BenchmarkInjectVideoEventTrackers-8 12680 96009 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104518 ns/op
+BenchmarkInjectVideoEventTrackers-8 12334 95338 ns/op
+BenchmarkInjectVideoEventTrackers-8 12841 97060 ns/op
+BenchmarkInjectVideoEventTrackers-8 12570 95457 ns/op
+BenchmarkInjectVideoEventTrackers-8 12663 92850 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102418 ns/op
+BenchmarkInjectVideoEventTrackers-8 12525 93522 ns/op
+BenchmarkInjectVideoEventTrackers-8 12598 95461 ns/op
+BenchmarkInjectVideoEventTrackers-8 12654 95732 ns/op
+BenchmarkInjectVideoEventTrackers-8 12458 97007 ns/op
+BenchmarkInjectVideoEventTrackers-8 12796 95227 ns/op
+BenchmarkInjectVideoEventTrackers-8 12876 93244 ns/op
+BenchmarkInjectVideoEventTrackers-8 12872 94017 ns/op
+BenchmarkInjectVideoEventTrackers-8 12681 93816 ns/op
+BenchmarkInjectVideoEventTrackers-8 12339 95252 ns/op
+BenchmarkInjectVideoEventTrackers-8 12823 94395 ns/op
+BenchmarkInjectVideoEventTrackers-8 12694 94203 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100970 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 113119 ns/op
+BenchmarkInjectVideoEventTrackers-8 12094 94384 ns/op
+BenchmarkInjectVideoEventTrackers-8 12213 99525 ns/op
+BenchmarkInjectVideoEventTrackers-8 12580 93890 ns/op
+BenchmarkInjectVideoEventTrackers-8 12214 92876 ns/op
+BenchmarkInjectVideoEventTrackers-8 12493 95199 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102603 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102531 ns/op
+BenchmarkInjectVideoEventTrackers-8 11844 96529 ns/op
+BenchmarkInjectVideoEventTrackers-8 11839 98682 ns/op
+BenchmarkInjectVideoEventTrackers-8 12073 95432 ns/op
+BenchmarkInjectVideoEventTrackers-8 12178 93536 ns/op
+BenchmarkInjectVideoEventTrackers-8 12308 95322 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106285 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107198 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 127930 ns/op
+BenchmarkInjectVideoEventTrackers-8 11570 100564 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103107 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100232 ns/op
+BenchmarkInjectVideoEventTrackers-8 12183 98138 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 101463 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100976 ns/op
+BenchmarkInjectVideoEventTrackers-8 12136 101379 ns/op
+BenchmarkInjectVideoEventTrackers-8 12129 97470 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 101763 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105143 ns/op
+BenchmarkInjectVideoEventTrackers-8 12036 96395 ns/op
+BenchmarkInjectVideoEventTrackers-8 12370 103113 ns/op
+BenchmarkInjectVideoEventTrackers-8 12097 104316 ns/op
+BenchmarkInjectVideoEventTrackers-8 10578 102399 ns/op
+BenchmarkInjectVideoEventTrackers-8 12114 98435 ns/op
+BenchmarkInjectVideoEventTrackers-8 12199 96260 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100708 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100063 ns/op
+BenchmarkInjectVideoEventTrackers-8 12259 99365 ns/op
+BenchmarkInjectVideoEventTrackers-8 11527 105366 ns/op
+BenchmarkInjectVideoEventTrackers-8 12170 98071 ns/op
+BenchmarkInjectVideoEventTrackers-8 11662 98735 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100196 ns/op
+BenchmarkInjectVideoEventTrackers-8 12100 98485 ns/op
+BenchmarkInjectVideoEventTrackers-8 12154 97764 ns/op
+BenchmarkInjectVideoEventTrackers-8 12190 98722 ns/op
+BenchmarkInjectVideoEventTrackers-8 12804 93210 ns/op
+BenchmarkInjectVideoEventTrackers-8 12298 91861 ns/op
+BenchmarkInjectVideoEventTrackers-8 12411 97100 ns/op
+BenchmarkInjectVideoEventTrackers-8 12403 95998 ns/op
+BenchmarkInjectVideoEventTrackers-8 12729 93676 ns/op
+BenchmarkInjectVideoEventTrackers-8 12483 116678 ns/op
+BenchmarkInjectVideoEventTrackers-8 10972 94685 ns/op
+BenchmarkInjectVideoEventTrackers-8 12343 95353 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106452 ns/op
+BenchmarkInjectVideoEventTrackers-8 12540 95257 ns/op
+BenchmarkInjectVideoEventTrackers-8 12612 97109 ns/op
+BenchmarkInjectVideoEventTrackers-8 12655 95869 ns/op
+BenchmarkInjectVideoEventTrackers-8 12564 101473 ns/op
+BenchmarkInjectVideoEventTrackers-8 12268 95826 ns/op
+BenchmarkInjectVideoEventTrackers-8 12158 95248 ns/op
+BenchmarkInjectVideoEventTrackers-8 12248 93556 ns/op
+BenchmarkInjectVideoEventTrackers-8 12874 95673 ns/op
+BenchmarkInjectVideoEventTrackers-8 12544 98246 ns/op
+BenchmarkInjectVideoEventTrackers-8 12751 95809 ns/op
+BenchmarkInjectVideoEventTrackers-8 12650 94296 ns/op
+BenchmarkInjectVideoEventTrackers-8 12152 98760 ns/op
+BenchmarkInjectVideoEventTrackers-8 12526 93759 ns/op
+BenchmarkInjectVideoEventTrackers-8 12052 102301 ns/op
+BenchmarkInjectVideoEventTrackers-8 12291 96482 ns/op
+BenchmarkInjectVideoEventTrackers-8 12262 96106 ns/op
+BenchmarkInjectVideoEventTrackers-8 12348 95109 ns/op
+BenchmarkInjectVideoEventTrackers-8 12496 95862 ns/op
+BenchmarkInjectVideoEventTrackers-8 12453 93967 ns/op
+BenchmarkInjectVideoEventTrackers-8 12153 99390 ns/op
+BenchmarkInjectVideoEventTrackers-8 12423 95374 ns/op
+BenchmarkInjectVideoEventTrackers-8 12615 93599 ns/op
+BenchmarkInjectVideoEventTrackers-8 12516 94149 ns/op
+BenchmarkInjectVideoEventTrackers-8 12460 94459 ns/op
+BenchmarkInjectVideoEventTrackers-8 12094 95090 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106277 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 142040 ns/op
+BenchmarkInjectVideoEventTrackers-8 12156 94065 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100250 ns/op
+BenchmarkInjectVideoEventTrackers-8 12726 96447 ns/op
+BenchmarkInjectVideoEventTrackers-8 12765 102457 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 100640 ns/op
+BenchmarkInjectVideoEventTrackers-8 12506 100274 ns/op
+BenchmarkInjectVideoEventTrackers-8 12260 100070 ns/op
+BenchmarkInjectVideoEventTrackers-8 12308 98857 ns/op
+BenchmarkInjectVideoEventTrackers-8 12379 94057 ns/op
+BenchmarkInjectVideoEventTrackers-8 12340 94406 ns/op
+BenchmarkInjectVideoEventTrackers-8 12625 95022 ns/op
+BenchmarkInjectVideoEventTrackers-8 9602 127201 ns/op
+BenchmarkInjectVideoEventTrackers-8 12022 99407 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 101338 ns/op
+BenchmarkInjectVideoEventTrackers-8 12512 96420 ns/op
+BenchmarkInjectVideoEventTrackers-8 12604 93874 ns/op
+BenchmarkInjectVideoEventTrackers-8 12098 93844 ns/op
+BenchmarkInjectVideoEventTrackers-8 12193 100286 ns/op
+BenchmarkInjectVideoEventTrackers-8 12698 94057 ns/op
+BenchmarkInjectVideoEventTrackers-8 12655 95501 ns/op
+BenchmarkInjectVideoEventTrackers-8 12780 100857 ns/op
+BenchmarkInjectVideoEventTrackers-8 12702 95481 ns/op
+BenchmarkInjectVideoEventTrackers-8 12699 97814 ns/op
+BenchmarkInjectVideoEventTrackers-8 12127 98798 ns/op
+BenchmarkInjectVideoEventTrackers-8 12010 96081 ns/op
+BenchmarkInjectVideoEventTrackers-8 12501 95398 ns/op
+BenchmarkInjectVideoEventTrackers-8 12560 95790 ns/op
+BenchmarkInjectVideoEventTrackers-8 12624 95461 ns/op
+BenchmarkInjectVideoEventTrackers-8 12519 105760 ns/op
+BenchmarkInjectVideoEventTrackers-8 11209 108704 ns/op
+BenchmarkInjectVideoEventTrackers-8 12322 95732 ns/op
+BenchmarkInjectVideoEventTrackers-8 12771 96915 ns/op
+BenchmarkInjectVideoEventTrackers-8 12816 94830 ns/op
+BenchmarkInjectVideoEventTrackers-8 12598 95256 ns/op
+PASS
+ok github.com/PubMatic-OpenWrap/prebid-server/endpoints/events 384.888s
+
+OLD
+---
+goos: linux
+goarch: arm64
+pkg: github.com/PubMatic-OpenWrap/prebid-server/endpoints/events
+BenchmarkInjectVideoEventTrackers-8 11412 103337 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103241 ns/op
+BenchmarkInjectVideoEventTrackers-8 9614 107920 ns/op
+BenchmarkInjectVideoEventTrackers-8 7446 142613 ns/op
+BenchmarkInjectVideoEventTrackers-8 6985 152987 ns/op
+BenchmarkInjectVideoEventTrackers-8 9717 113304 ns/op
+BenchmarkInjectVideoEventTrackers-8 10687 111009 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103443 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 161335 ns/op
+BenchmarkInjectVideoEventTrackers-8 8612 141799 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104980 ns/op
+BenchmarkInjectVideoEventTrackers-8 8994 118290 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103775 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 117957 ns/op
+BenchmarkInjectVideoEventTrackers-8 7485 152072 ns/op
+BenchmarkInjectVideoEventTrackers-8 11416 102757 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106422 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103300 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 146524 ns/op
+BenchmarkInjectVideoEventTrackers-8 11280 106079 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105962 ns/op
+BenchmarkInjectVideoEventTrackers-8 11071 141065 ns/op
+BenchmarkInjectVideoEventTrackers-8 9565 108086 ns/op
+BenchmarkInjectVideoEventTrackers-8 9354 113106 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103729 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103996 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 157443 ns/op
+BenchmarkInjectVideoEventTrackers-8 11301 111289 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104083 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102001 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 126965 ns/op
+BenchmarkInjectVideoEventTrackers-8 6645 158038 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102666 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102557 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108698 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107614 ns/op
+BenchmarkInjectVideoEventTrackers-8 9088 133802 ns/op
+BenchmarkInjectVideoEventTrackers-8 6825 152288 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103996 ns/op
+BenchmarkInjectVideoEventTrackers-8 10992 118586 ns/op
+BenchmarkInjectVideoEventTrackers-8 9406 106554 ns/op
+BenchmarkInjectVideoEventTrackers-8 9822 165054 ns/op
+BenchmarkInjectVideoEventTrackers-8 8284 123469 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108410 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104649 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103888 ns/op
+BenchmarkInjectVideoEventTrackers-8 9793 103767 ns/op
+BenchmarkInjectVideoEventTrackers-8 8064 176493 ns/op
+BenchmarkInjectVideoEventTrackers-8 10224 103211 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106395 ns/op
+BenchmarkInjectVideoEventTrackers-8 11578 105227 ns/op
+BenchmarkInjectVideoEventTrackers-8 7761 160917 ns/op
+BenchmarkInjectVideoEventTrackers-8 9730 141976 ns/op
+BenchmarkInjectVideoEventTrackers-8 11352 106213 ns/op
+BenchmarkInjectVideoEventTrackers-8 8799 119790 ns/op
+BenchmarkInjectVideoEventTrackers-8 7743 175326 ns/op
+BenchmarkInjectVideoEventTrackers-8 9674 108504 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104176 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107588 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107367 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 132792 ns/op
+BenchmarkInjectVideoEventTrackers-8 11179 109587 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103266 ns/op
+BenchmarkInjectVideoEventTrackers-8 9483 116627 ns/op
+BenchmarkInjectVideoEventTrackers-8 9438 165878 ns/op
+BenchmarkInjectVideoEventTrackers-8 8343 121643 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104253 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 111989 ns/op
+BenchmarkInjectVideoEventTrackers-8 11624 102501 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 163193 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102279 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103620 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102954 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104372 ns/op
+BenchmarkInjectVideoEventTrackers-8 9360 121906 ns/op
+BenchmarkInjectVideoEventTrackers-8 11402 102374 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102101 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103073 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105181 ns/op
+BenchmarkInjectVideoEventTrackers-8 7383 171419 ns/op
+BenchmarkInjectVideoEventTrackers-8 11078 105008 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102512 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106887 ns/op
+BenchmarkInjectVideoEventTrackers-8 11018 174666 ns/op
+BenchmarkInjectVideoEventTrackers-8 11121 104063 ns/op
+BenchmarkInjectVideoEventTrackers-8 11512 113785 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108632 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103740 ns/op
+BenchmarkInjectVideoEventTrackers-8 11200 104223 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109149 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102092 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104393 ns/op
+BenchmarkInjectVideoEventTrackers-8 10462 104387 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107595 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108973 ns/op
+BenchmarkInjectVideoEventTrackers-8 11140 104834 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 114135 ns/op
+BenchmarkInjectVideoEventTrackers-8 9674 109976 ns/op
+BenchmarkInjectVideoEventTrackers-8 9894 102282 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104053 ns/op
+BenchmarkInjectVideoEventTrackers-8 9691 103451 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103017 ns/op
+BenchmarkInjectVideoEventTrackers-8 11432 106630 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 116968 ns/op
+BenchmarkInjectVideoEventTrackers-8 11148 111332 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106245 ns/op
+BenchmarkInjectVideoEventTrackers-8 11107 106324 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 125663 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109025 ns/op
+BenchmarkInjectVideoEventTrackers-8 9948 103579 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 111039 ns/op
+BenchmarkInjectVideoEventTrackers-8 9982 107039 ns/op
+BenchmarkInjectVideoEventTrackers-8 9532 119793 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108138 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107934 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107594 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103471 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103766 ns/op
+BenchmarkInjectVideoEventTrackers-8 11556 101248 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 114003 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103359 ns/op
+BenchmarkInjectVideoEventTrackers-8 9386 107104 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107333 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105346 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104383 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 103176 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107480 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102885 ns/op
+BenchmarkInjectVideoEventTrackers-8 9937 106700 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 112205 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 114893 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104802 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 122574 ns/op
+BenchmarkInjectVideoEventTrackers-8 9513 116394 ns/op
+BenchmarkInjectVideoEventTrackers-8 9439 108796 ns/op
+BenchmarkInjectVideoEventTrackers-8 8712 115626 ns/op
+BenchmarkInjectVideoEventTrackers-8 9792 104656 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 112900 ns/op
+BenchmarkInjectVideoEventTrackers-8 11197 108651 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106477 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106866 ns/op
+BenchmarkInjectVideoEventTrackers-8 11379 109056 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109240 ns/op
+BenchmarkInjectVideoEventTrackers-8 9552 108889 ns/op
+BenchmarkInjectVideoEventTrackers-8 11392 147023 ns/op
+BenchmarkInjectVideoEventTrackers-8 11553 104010 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102045 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 122656 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108962 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109847 ns/op
+BenchmarkInjectVideoEventTrackers-8 9756 111888 ns/op
+BenchmarkInjectVideoEventTrackers-8 11671 115049 ns/op
+BenchmarkInjectVideoEventTrackers-8 9361 108008 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 108039 ns/op
+BenchmarkInjectVideoEventTrackers-8 9820 107452 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104862 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 120423 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 102096 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105396 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105446 ns/op
+BenchmarkInjectVideoEventTrackers-8 9808 103055 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109139 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109291 ns/op
+BenchmarkInjectVideoEventTrackers-8 9427 113156 ns/op
+BenchmarkInjectVideoEventTrackers-8 10416 106213 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104006 ns/op
+BenchmarkInjectVideoEventTrackers-8 9496 106432 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 119959 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104761 ns/op
+BenchmarkInjectVideoEventTrackers-8 9834 112330 ns/op
+BenchmarkInjectVideoEventTrackers-8 9410 110560 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105160 ns/op
+BenchmarkInjectVideoEventTrackers-8 9613 109464 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 104137 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106862 ns/op
+BenchmarkInjectVideoEventTrackers-8 9986 107730 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105636 ns/op
+BenchmarkInjectVideoEventTrackers-8 9934 113900 ns/op
+BenchmarkInjectVideoEventTrackers-8 9727 119387 ns/op
+BenchmarkInjectVideoEventTrackers-8 9901 123299 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 116341 ns/op
+BenchmarkInjectVideoEventTrackers-8 9680 106484 ns/op
+BenchmarkInjectVideoEventTrackers-8 11455 105962 ns/op
+BenchmarkInjectVideoEventTrackers-8 10924 108121 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 206043 ns/op
+BenchmarkInjectVideoEventTrackers-8 7663 179629 ns/op
+BenchmarkInjectVideoEventTrackers-8 8349 146721 ns/op
+BenchmarkInjectVideoEventTrackers-8 9888 162455 ns/op
+BenchmarkInjectVideoEventTrackers-8 6970 167227 ns/op
+BenchmarkInjectVideoEventTrackers-8 9943 166298 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107951 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 177137 ns/op
+BenchmarkInjectVideoEventTrackers-8 11049 102284 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 106085 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 105527 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 110146 ns/op
+BenchmarkInjectVideoEventTrackers-8 11310 109212 ns/op
+BenchmarkInjectVideoEventTrackers-8 9882 108443 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 109327 ns/op
+BenchmarkInjectVideoEventTrackers-8 10000 107013 ns/op
+PASS
+ok github.com/PubMatic-OpenWrap/prebid-server/endpoints/events 268.193s
diff --git a/endpoints/events/test/ow_failed.txt b/endpoints/events/test/ow_failed.txt
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/endpoints/events/test/raw_vast.txt b/endpoints/events/test/raw_vast.txt
new file mode 100644
index 00000000000..2bd4a7e0d79
--- /dev/null
+++ b/endpoints/events/test/raw_vast.txt
@@ -0,0 +1,101 @@
+creative_url
+LoopMe LTD
+BidSwitch
+Yahoo Ad Manager PlusVAST 2.0 Linear AdVAST 2.0 Linear Ad00:00:15
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+\\n\\n \\n \\n \\n AdGear RTB\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n
+RhythmXchange Adserver
+RhythmXchange Adserver
+LoopMe LTD
+adnxs
+ebdr
+RhythmXchange Adserver
+RhythmXchange Adserver
+BidSwitch
+ebdr
+ebdr
+RhythmXchange Adserver
+RhythmXchange Adserver
+ebdr
+LoopMe LTD
+ebdr
+RhythmXchange Adserver
+PlayTime RTB
+PlayTime RTB
+RhythmXchange Adserver
+ebdr
+PlayTime RTB
+GumGum
+LoopMe LTD
+RhythmXchange Adserver
+ebdr
+GumGum
+RhythmXchange Adserver
+ebdr
+ebdr
+Yahoo Ad Manager PlusVAST 2.0 Linear AdVAST 2.0 Linear Ad00:00:15
+RhythmXchange Adserver
+RhythmXchange Adserver
+adnxs
+RhythmXchange Adserver
+adnxs
+adnxs
+adnxs
+PlayTime RTB
+ebdr
+BidSwitch
+RhythmXchange Adserver
+adnxs
+RhythmXchange Adserver
+ebdr
+RhythmXchange Adserver
+ebdr
+RhythmXchange Adserver
+ebdr
+RhythmXchange Adserver
+adnxs
+MediaMath T1 VADS
+adnxs
+MediaMath T1 VADS
+ebdr
+BidSwitch
+RhythmXchange Adserver
+BidSwitch
+Smadex
+ebdr
+adnxs
+GumGum
+RhythmXchange Adserver
+RhythmXchange Adserver
+ebdr
+RhythmXchange Adserver
+RhythmXchange Adserver
+Yahoo Ad Manager PlusVAST 2.0 Linear AdVAST 2.0 Linear Ad00:02:00
+RhythmXchange Adserver
+GumGum
+ebdr
+RhythmXchange Adserver
+RTB House
+ebdr
+BidSwitch
+Yahoo Ad Manager PlusVAST 2.0 Linear AdVAST 2.0 Linear Ad00:00:07
+ebdr
+RhythmXchange Adserver
+adnxs
+ebdr
+Yahoo Ad Manager PlusVAST 2.0 Linear AdVAST 2.0 Linear Ad00:00:07
+PlayTime RTB
+RhythmXchange Adserver
+RhythmXchange Adserver
+RhythmXchange Adserver
+RhythmXchange Adserver
+RhythmXchange Adserver
+ebdr
+adnxs
+adnxs
\ No newline at end of file
diff --git a/endpoints/events/vtrack_ow.go b/endpoints/events/vtrack_ow.go
index 76e7ff7b707..28b35eb8b0c 100644
--- a/endpoints/events/vtrack_ow.go
+++ b/endpoints/events/vtrack_ow.go
@@ -1,245 +1,232 @@
package events
import (
- "encoding/json"
+ "bytes"
+ "encoding/base64"
"errors"
- "fmt"
- "net/url"
"strings"
+ "time"
+ "github.com/PubMatic-OpenWrap/fastxml"
"github.com/beevik/etree"
- "github.com/golang/glog"
"github.com/prebid/openrtb/v20/adcom1"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/openrtb_ext"
)
-// standard VAST macros
-// https://interactiveadvertisingbureau.github.io/vast/vast4macros/vast4-macros-latest.html#macro-spec-adcount
-const (
- VASTAdTypeMacro = "[ADTYPE]"
- VASTAppBundleMacro = "[APPBUNDLE]"
- VASTDomainMacro = "[DOMAIN]"
- VASTPageURLMacro = "[PAGEURL]"
-
- // PBS specific macros
- PBSEventIDMacro = "[EVENT_ID]" // macro for injecting PBS defined video event tracker id
- //[PBS-ACCOUNT] represents publisher id / account id
- PBSAccountMacro = "[PBS-ACCOUNT]"
- // [PBS-BIDDER] represents bidder name
- PBSBidderMacro = "[PBS-BIDDER]"
- // [PBS-ORIG_BIDID] represents original bid id.
- PBSOrigBidIDMacro = "[PBS-ORIG_BIDID]"
- // [PBS-BIDID] represents bid id. If auction.generate-bid-id config is on, then resolve with response.seatbid.bid.ext.prebid.bidid. Else replace with response.seatbid.bid.id
- PBSBidIDMacro = "[PBS-BIDID]"
- // [ADERVERTISER_NAME] represents advertiser name
- PBSAdvertiserNameMacro = "[ADVERTISER_NAME]"
- // Pass imp.tagId using this macro
- PBSAdUnitIDMacro = "[AD_UNIT]"
- //PBSBidderCodeMacro represents an alias id or core bidder id.
- PBSBidderCodeMacro = "[BIDDER_CODE]"
+var (
+ errEventURLNotConfigured = errors.New("event urls not configured")
)
-var trackingEvents = []string{"start", "firstQuartile", "midpoint", "thirdQuartile", "complete"}
-
-// PubMatic specific event IDs
-// This will go in event-config once PreBid modular design is in place
-var eventIDMap = map[string]string{
- "start": "2",
- "firstQuartile": "4",
- "midpoint": "3",
- "thirdQuartile": "5",
- "complete": "6",
-}
-
// InjectVideoEventTrackers injects the video tracking events
// Returns VAST xml contains as first argument. Second argument indicates whether the trackers are injected and last argument indicates if there is any error in injecting the trackers
-func InjectVideoEventTrackers(trackerURL, vastXML string, bid *openrtb2.Bid, prebidGenBidId, requestingBidder, bidderCoreName, accountID string, timestamp int64, bidRequest *openrtb2.BidRequest) ([]byte, bool, error) {
- // parse VAST
- doc := etree.NewDocument()
- err := doc.ReadFromString(vastXML)
- if nil != err {
- 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
- }
+func InjectVideoEventTrackers(
+ bidRequest *openrtb2.BidRequest,
+ bid *openrtb2.Bid,
+ vastXML, trackerURL, prebidGenBidId, requestingBidder, bidderCoreName string,
+ timestamp int64, fastXMLExperiment bool) (response string, metrics *openrtb_ext.FastXMLMetrics, err error) {
//Maintaining BidRequest Impression Map (Copied from exchange.go#applyCategoryMapping)
//TODO: It should be optimized by forming once and reusing
- impMap := make(map[string]*openrtb2.Imp)
- for i := range bidRequest.Imp {
- impMap[bidRequest.Imp[i].ID] = &bidRequest.Imp[i]
+ var imp *openrtb2.Imp
+ for _, impr := range bidRequest.Imp {
+ if bid.ImpID == impr.ID && impr.Video != nil {
+ imp = &impr
+ break
+ }
+ }
+ if imp == nil {
+ return vastXML, nil, nil
}
- eventURLMap := GetVideoEventTracking(trackerURL, bid, prebidGenBidId, requestingBidder, bidderCoreName, accountID, timestamp, bidRequest, doc, impMap)
- trackersInjected := false
- // return if if no tracking URL
+ eventURLMap := GetVideoEventTracking(bidRequest, imp, bid, trackerURL, prebidGenBidId, requestingBidder, bidderCoreName, timestamp)
if len(eventURLMap) == 0 {
- return []byte(vastXML), false, errors.New("Event URLs are not found")
+ return vastXML, nil, errEventURLNotConfigured
}
- creatives := FindCreatives(doc)
+ adm := strings.TrimSpace(bid.AdM)
+ nurlPresent := (adm == "" || strings.HasPrefix(adm, "http"))
- if adm := strings.TrimSpace(bid.AdM); adm == "" || strings.HasPrefix(adm, "http") {
- // determine which creative type to be created based on linearity
- if imp, ok := impMap[bid.ImpID]; ok && nil != imp.Video {
- // create creative object
- creatives = doc.FindElements("VAST/Ad/Wrapper/Creatives")
- // var creative *etree.Element
- // if len(creatives) > 0 {
- // creative = creatives[0] // consider only first creative
- // } else {
- creative := doc.CreateElement("Creative")
- creatives[0].AddChild(creative)
-
- // }
-
- switch imp.Video.Linearity {
- case adcom1.LinearityLinear:
- creative.AddChild(doc.CreateElement("Linear"))
- case adcom1.LinearityNonLinear:
- creative.AddChild(doc.CreateElement("NonLinearAds"))
- default: // create both type of creatives
- creative.AddChild(doc.CreateElement("Linear"))
- creative.AddChild(doc.CreateElement("NonLinearAds"))
- }
- creatives = creative.ChildElements() // point to actual cratives
- }
- }
- for _, creative := range creatives {
- trackingEvents := creative.SelectElement("TrackingEvents")
- if nil == trackingEvents {
- trackingEvents = creative.CreateElement("TrackingEvents")
- creative.AddChild(trackingEvents)
+ _startTime := time.Now()
+ response, err = injectVideoEventsETree(vastXML, eventURLMap, nurlPresent, imp.Video.Linearity)
+ etreeParserTime := time.Since(_startTime)
+
+ if fastXMLExperiment && err == nil {
+ _startTime = time.Now()
+ fastXMLResponse, _ := injectVideoEventsFastXML(vastXML, eventURLMap, nurlPresent, imp.Video.Linearity)
+ fastXMLParserTime := time.Since(_startTime)
+
+ //temporary
+ if fastXMLResponse != vastXML {
+ fastXMLResponse = tmpFastXMLProcessing(fastXMLResponse)
}
- // Inject
- for event, url := range eventURLMap {
- trackingEle := trackingEvents.CreateElement("Tracking")
- trackingEle.CreateAttr("event", event)
- trackingEle.SetText(fmt.Sprintf("%s", url))
- trackersInjected = true
+
+ isResponseMismatch := (response != fastXMLResponse)
+
+ if isResponseMismatch {
+ openrtb_ext.FastXMLLogf("\n[XML_PARSER_TEST] method:[vcr] creative:[%s]", base64.StdEncoding.EncodeToString([]byte(vastXML)))
}
- }
- out := []byte(vastXML)
- var wErr error
- if trackersInjected {
- out, wErr = doc.WriteToBytes()
- trackersInjected = trackersInjected && nil == wErr
- if nil != wErr {
- glog.Errorf("%v", wErr.Error())
+ metrics = &openrtb_ext.FastXMLMetrics{
+ XMLParserTime: fastXMLParserTime,
+ EtreeParserTime: etreeParserTime,
+ IsRespMismatch: isResponseMismatch,
}
}
- return out, trackersInjected, wErr
+
+ return response, metrics, err
+}
+
+func tmpFastXMLProcessing(vast string) string {
+ //replace only if trackers are injected
+ vast = strings.ReplaceAll(vast, " >", ">")
+ // if strings.Contains(vast, "'") {
+ // if index := strings.Index(vast, " 0 {
- var err error
- //eventURL = replaceMacro(eventURL, PBSAdvertiserNameMacro, strings.Join(bid.ADomain, ","))
- domain, err = extractDomain(bid.ADomain[0])
- if err != nil {
- glog.Warningf("Unable to extract domain from '%s'. [%s]", bid.ADomain[0], err.Error())
- }
- }
+ if !trackersInjected {
+ return vastXML, nil
+ }
+
+ out, err := doc.WriteToBytes()
+ if err != nil {
+ return vastXML, err
+ }
+ return string(out), nil
+}
+
+func injectVideoEventsFastXML(vastXML string, eventURLMap map[string]string, nurlPresent bool, linearity adcom1.LinearityMode) (string, error) {
+
+ //parse vast xml
+ doc := fastxml.NewXMLReader(nil)
+ if err := doc.Parse([]byte(vastXML)); err != nil {
+ return vastXML, err
+ }
+
+ trackersInjected := false
+ xu := fastxml.NewXMLUpdater(doc, fastxml.WriteSettings{
+ CDATAWrap: true,
+ ExpandInline: true,
+ })
- eventURL = replaceMacro(eventURL, PBSAdvertiserNameMacro, domain)
+ if nurlPresent {
+ creative := doc.SelectElement(nil, "VAST", "Ad", "Wrapper", "Creatives")
+ if creative != nil {
+ cr := fastxml.CreateElement("Creative")
- eventURL = replaceMacro(eventURL, PBSBidderMacro, bidderCoreName)
- eventURL = replaceMacro(eventURL, PBSBidderCodeMacro, requestingBidder)
+ switch linearity {
+ case adcom1.LinearityLinear:
+ cr.AddChild(fastxml.CreateElement("Linear").AddChild(getTrackingEvents(true, eventURLMap)))
+ case adcom1.LinearityNonLinear:
+ cr.AddChild(fastxml.CreateElement("NonLinearAds").AddChild(getTrackingEvents(true, eventURLMap)))
+ default:
+ cr.AddChild(fastxml.CreateElement("Linear").AddChild(getTrackingEvents(true, eventURLMap)))
+ cr.AddChild(fastxml.CreateElement("NonLinearAds").AddChild(getTrackingEvents(true, eventURLMap)))
+ }
- /* Use generated bidId if present, else use bid.ID */
- if len(prebidGenBidId) > 0 && prebidGenBidId != bid.ID {
- eventURL = replaceMacro(eventURL, PBSBidIDMacro, prebidGenBidId)
- } else {
- eventURL = replaceMacro(eventURL, PBSBidIDMacro, bid.ID)
+ xu.AppendElement(creative, cr)
+ trackersInjected = true
}
- eventURL = replaceMacro(eventURL, PBSOrigBidIDMacro, bid.ID)
+ } else {
+ // Find creatives
+ creatives := doc.SelectElements(nil, "VAST", "Ad", "*", "Creatives", "Creative", "*")
- // replace [EVENT_ID] macro with PBS defined event ID
- eventURL = replaceMacro(eventURL, PBSEventIDMacro, eventIDMap[event])
+ for _, linearityElement := range creatives {
+ name := doc.Name(linearityElement)
+ if !(name == "Linear" || name == "NonLinearAds") {
+ continue
+ }
- if imp, ok := impMap[bid.ImpID]; ok {
- eventURL = replaceMacro(eventURL, PBSAdUnitIDMacro, imp.TagID)
- } else {
- glog.Warningf("Setting empty value for %s macro, as failed to determine imp.TagID for bid.ImpID: %s", PBSAdUnitIDMacro, bid.ImpID)
- eventURL = replaceMacro(eventURL, PBSAdUnitIDMacro, "")
+ createTrackingEvents := false
+ parent := doc.SelectElement(linearityElement, "TrackingEvents")
+ if parent == nil {
+ createTrackingEvents = true
+ parent = linearityElement //Linear/NonLinearAds
+ }
+
+ xu.AppendElement(parent, getTrackingEvents(createTrackingEvents, eventURLMap))
+ trackersInjected = true
}
+ }
- eventURLMap[event] = eventURL
+ if !trackersInjected {
+ return vastXML, nil
}
- return eventURLMap
+
+ //Add CDATA and Expand Inline Nodes
+ xu.ApplyXMLSettingsOperations()
+
+ var buf bytes.Buffer
+ xu.Build(&buf)
+ return buf.String(), nil
}
-func replaceMacro(trackerURL, macro, value string) string {
- macro = strings.TrimSpace(macro)
- trimmedValue := strings.TrimSpace(value)
+func getTrackingEvents(createTrackingEvents bool, eventURLMap map[string]string) *fastxml.XMLElement {
+ te := fastxml.CreateElement("")
+ if createTrackingEvents {
+ te.SetName("TrackingEvents")
+ }
- if strings.HasPrefix(macro, "[") && strings.HasSuffix(macro, "]") && len(trimmedValue) > 0 {
- trackerURL = strings.ReplaceAll(trackerURL, macro, url.QueryEscape(value))
- } else if strings.HasPrefix(macro, "[") && strings.HasSuffix(macro, "]") && len(trimmedValue) == 0 {
- trackerURL = strings.ReplaceAll(trackerURL, macro, url.QueryEscape(""))
- } else {
- glog.Warningf("Invalid macro '%v'. Either empty or missing prefix '[' or suffix ']", macro)
+ for _, event := range trackingEvents {
+ if url, ok := eventURLMap[event]; ok {
+ tracking := fastxml.CreateElement("Tracking").AddAttribute("", "event", event).SetText(url, true, fastxml.NoEscaping)
+ te.AddChild(tracking)
+ }
}
- return trackerURL
+ return te
}
-// FindCreatives finds Linear, NonLinearAds fro InLine and Wrapper Type of creatives
-// from input doc - VAST Document
-// NOTE: This function is temporarily seperated to reuse in ctv_auction.go. Because, in case of ctv
-// we generate bid.id
func FindCreatives(doc *etree.Document) []*etree.Element {
// Find Creatives of Linear and NonLinear Type
// Injecting Tracking Events for Companion is not supported here
@@ -249,36 +236,3 @@ func FindCreatives(doc *etree.Document) []*etree.Element {
creatives = append(creatives, doc.FindElements("VAST/Ad/Wrapper/Creatives/Creative/NonLinearAds")...)
return creatives
}
-
-func extractDomain(rawURL string) (string, error) {
- if !strings.HasPrefix(rawURL, "http") {
- rawURL = "http://" + rawURL
- }
- // decode rawURL
- rawURL, err := url.QueryUnescape(rawURL)
- if nil != err {
- return "", err
- }
- url, err := url.Parse(rawURL)
- if nil != err {
- return "", err
- }
- // remove www if present
- return strings.TrimPrefix(url.Hostname(), "www."), nil
-}
-
-func getDomain(site *openrtb2.Site) string {
- if site.Domain != "" {
- return site.Domain
- }
-
- hostname := ""
-
- if site.Page != "" {
- pageURL, err := url.Parse(site.Page)
- if err == nil && pageURL != nil {
- hostname = pageURL.Host
- }
- }
- return hostname
-}
diff --git a/endpoints/events/vtrack_ow_benchmark_test.go b/endpoints/events/vtrack_ow_benchmark_test.go
new file mode 100644
index 00000000000..4761164955f
--- /dev/null
+++ b/endpoints/events/vtrack_ow_benchmark_test.go
@@ -0,0 +1,68 @@
+package events
+
+import (
+ "testing"
+
+ "github.com/prebid/openrtb/v20/adcom1"
+ "github.com/prebid/openrtb/v20/openrtb2"
+)
+
+var benchMarkVAST, testVAST string
+var eventURLMap map[string]string
+
+func init() {
+ benchMarkVAST = `LoopMe LTD`
+
+ testVAST = `LoopMe LTD`
+ eventURLMap = map[string]string{
+ "firstQuartile": "http://example.com/tracking/firstQuartile?k1=v1&k2=v2",
+ "midpoint": "http://example.com/tracking/midpoint",
+ "thirdQuartile": "http://example.com/tracking/thirdQuartile",
+ "complete": "http://example.com/tracking/complete",
+ "start": "http://company.tracker.com?eventId=2&appbundle=abc",
+ }
+}
+
+func BenchmarkETreeVideoInjector(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ injectVideoEventsETree(benchMarkVAST, eventURLMap, false, adcom1.LinearityLinear)
+ }
+}
+
+func BenchmarkFastXMLVideoInjector(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ injectVideoEventsFastXML(benchMarkVAST, eventURLMap, false, adcom1.LinearityLinear)
+ }
+}
+
+// BenchmarkInjectVideoEventTrackers
+// nilesh@9fc43242aec1: git checkout origin/ci
+// nilesh@9fc43242aec1:~/go/src/github.com/PubMatic-OpenWrap/prebid-server/endpoints/events$ go test -bench=BenchmarkInjectVideoEventTrackers -count 200 -run=^# | tee old1.txt
+// nilesh@9fc43242aec1: git checkout origin/UOE-8632-ci-1
+// nilesh@9fc43242aec1:~/go/src/github.com/PubMatic-OpenWrap/prebid-server/endpoints/events$ go test -bench=BenchmarkInjectVideoEventTrackers -count 200 -run=^# | tee new1.txt
+// nilesh@9fc43242aec1:~/go/src/github.com/PubMatic-OpenWrap/prebid-server/endpoints/events$ benchstat old1.txt new1.txt
+// goos: linux
+// goarch: arm64
+// pkg: github.com/PubMatic-OpenWrap/prebid-server/endpoints/events
+//
+// │ old1.txt │ new1.txt │
+// │ sec/op │ sec/op vs base │
+//
+// InjectVideoEventTrackers-8 107.83µ ± 1% 97.62µ ± 1% -9.47% (n=200)
+func BenchmarkInjectVideoEventTrackers(b *testing.B) {
+ trackerURL := "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]"
+ vastXML := ``
+ bid := &openrtb2.Bid{
+ AdM: ``,
+ }
+ req := &openrtb2.BidRequest{
+ App: &openrtb2.App{Bundle: "abc"},
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ // no need to validate, using vast from test TestInjectVideoEventTrackers/all_inline_wrapper_liner_and_non_linear_creative
+ _, _, _ = InjectVideoEventTrackers(req, bid, vastXML, trackerURL, "", "test_bidder", "test_core_bidder", int64(0), false)
+ }
+}
diff --git a/endpoints/events/vtrack_ow_test.go b/endpoints/events/vtrack_ow_test.go
index ac4cbbd06ac..afa7d95e0ec 100644
--- a/endpoints/events/vtrack_ow_test.go
+++ b/endpoints/events/vtrack_ow_test.go
@@ -1,24 +1,33 @@
package events
import (
+ "bufio"
+ "bytes"
+ "encoding/base64"
"fmt"
- "net/url"
+ "os"
+ "sort"
+ "strings"
"testing"
- "github.com/beevik/etree"
+ "github.com/prebid/openrtb/v20/adcom1"
"github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/stretchr/testify/assert"
)
func TestInjectVideoEventTrackers(t *testing.T) {
type args struct {
externalURL string
+ vastXML string
genbidID string
bid *openrtb2.Bid
req *openrtb2.BidRequest
}
type want struct {
- eventURLs map[string][]string
+ wantVastXml string
+ wantErr error
+ metrics *openrtb_ext.FastXMLMetrics
}
tests := []struct {
name string
@@ -29,608 +38,508 @@ func TestInjectVideoEventTrackers(t *testing.T) {
name: "linear_creative",
args: args{
externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `http://example.com/tracking/midpointhttp://example.com/tracking/thirdQuartilehttp://example.com/tracking/completehttp://partner.tracking.url`,
bid: &openrtb2.Bid{
- AdM: `
-
-
-
- http://example.com/tracking/midpoint
- http://example.com/tracking/thirdQuartile
- http://example.com/tracking/complete
- http://partner.tracking.url
-
-
- `,
- },
- req: &openrtb2.BidRequest{App: &openrtb2.App{Bundle: "abc"}},
+ AdM: `http://example.com/tracking/midpointhttp://example.com/tracking/thirdQuartilehttp://example.com/tracking/completehttp://partner.tracking.url`,
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
+ },
},
want: want{
- eventURLs: map[string][]string{
- // "firstQuartile": {"http://example.com/tracking/firstQuartile?k1=v1&k2=v2", "http://company.tracker.com?eventId=1004&appbundle=abc"},
- // "midpoint": {"http://example.com/tracking/midpoint", "http://company.tracker.com?eventId=1003&appbundle=abc"},
- // "thirdQuartile": {"http://example.com/tracking/thirdQuartile", "http://company.tracker.com?eventId=1005&appbundle=abc"},
- // "complete": {"http://example.com/tracking/complete", "http://company.tracker.com?eventId=1006&appbundle=abc"},
- "firstQuartile": {"http://example.com/tracking/firstQuartile?k1=v1&k2=v2", "http://company.tracker.com?eventId=4&appbundle=abc"},
- "midpoint": {"http://example.com/tracking/midpoint", "http://company.tracker.com?eventId=3&appbundle=abc"},
- "thirdQuartile": {"http://example.com/tracking/thirdQuartile", "http://company.tracker.com?eventId=5&appbundle=abc"},
- "complete": {"http://example.com/tracking/complete", "http://company.tracker.com?eventId=6&appbundle=abc"},
- "start": {"http://company.tracker.com?eventId=2&appbundle=abc", "http://partner.tracking.url"},
- },
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
name: "non_linear_creative",
args: args{
externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
- bid: &openrtb2.Bid{ // Adm contains to TrackingEvents tag
- AdM: `
-
-
- http://something.com
-
-
- `,
+ vastXML: `http://something.com`,
+ bid: &openrtb2.Bid{
+ AdM: `http://something.com`,
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
- req: &openrtb2.BidRequest{App: &openrtb2.App{Bundle: "abc"}},
},
want: want{
- eventURLs: map[string][]string{
- // "firstQuartile": {"http://something.com", "http://company.tracker.com?eventId=1004&appbundle=abc"},
- // "midpoint": {"http://company.tracker.com?eventId=1003&appbundle=abc"},
- // "thirdQuartile": {"http://company.tracker.com?eventId=1005&appbundle=abc"},
- // "complete": {"http://company.tracker.com?eventId=1006&appbundle=abc"},
- "firstQuartile": {"http://something.com", "http://company.tracker.com?eventId=4&appbundle=abc"},
- "midpoint": {"http://company.tracker.com?eventId=3&appbundle=abc"},
- "thirdQuartile": {"http://company.tracker.com?eventId=5&appbundle=abc"},
- "complete": {"http://company.tracker.com?eventId=6&appbundle=abc"},
- "start": {"http://company.tracker.com?eventId=2&appbundle=abc"},
- },
- },
- }, {
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ },
+ },
+ {
+ name: "all_inline_wrapper_liner_and_non_linear_creative",
+ args: args{
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: ``,
+ bid: &openrtb2.Bid{
+ AdM: ``,
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
+ },
+ },
+ want: want{
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ },
+ },
+ {
name: "no_traker_url_configured", // expect no injection
args: args{
externalURL: "",
- bid: &openrtb2.Bid{ // Adm contains to TrackingEvents tag
- AdM: `
-
-
- `,
+ vastXML: ``,
+ bid: &openrtb2.Bid{
+ AdM: ``,
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
- req: &openrtb2.BidRequest{App: &openrtb2.App{Bundle: "abc"}},
},
want: want{
- eventURLs: map[string][]string{},
+ wantVastXml: ``,
+ wantErr: errEventURLNotConfigured,
+ metrics: nil,
},
},
{
name: "wrapper_vast_xml_from_partner", // expect we are injecting trackers inside wrapper
args: args{
externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `iabtechlabhttp://somevasturl`,
bid: &openrtb2.Bid{ // Adm contains to TrackingEvents tag
- AdM: `
-
-
- iabtechlab
- http://somevasturl
-
-
-
-
-
- `,
- },
- req: &openrtb2.BidRequest{App: &openrtb2.App{Bundle: "abc"}},
+ AdM: `iabtechlabhttp://somevasturl`,
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
+ },
},
want: want{
- eventURLs: map[string][]string{
- // "firstQuartile": {"http://company.tracker.com?eventId=firstQuartile&appbundle=abc"},
- // "midpoint": {"http://company.tracker.com?eventId=midpoint&appbundle=abc"},
- // "thirdQuartile": {"http://company.tracker.com?eventId=thirdQuartile&appbundle=abc"},
- // "complete": {"http://company.tracker.com?eventId=complete&appbundle=abc"},
- "firstQuartile": {"http://company.tracker.com?eventId=4&appbundle=abc"},
- "midpoint": {"http://company.tracker.com?eventId=3&appbundle=abc"},
- "thirdQuartile": {"http://company.tracker.com?eventId=5&appbundle=abc"},
- "complete": {"http://company.tracker.com?eventId=6&appbundle=abc"},
- "start": {"http://company.tracker.com?eventId=2&appbundle=abc"},
- },
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
- // {
- // name: "vast_tag_uri_response_from_partner",
- // args: args{
- // externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
- // bid: &openrtb2.Bid{ // Adm contains to TrackingEvents tag
- // AdM: ``,
- // },
- // req: &openrtb2.BidRequest{App: &openrtb2.App{Bundle: "abc"}},
- // },
- // want: want{
- // eventURLs: map[string][]string{
- // "firstQuartile": {"http://company.tracker.com?eventId=firstQuartile&appbundle=abc"},
- // "midpoint": {"http://company.tracker.com?eventId=midpoint&appbundle=abc"},
- // "thirdQuartile": {"http://company.tracker.com?eventId=thirdQuartile&appbundle=abc"},
- // "complete": {"http://company.tracker.com?eventId=complete&appbundle=abc"},
- // },
- // },
- // },
- // {
- // name: "adm_empty",
- // args: args{
- // externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
- // bid: &openrtb2.Bid{ // Adm contains to TrackingEvents tag
- // AdM: "",
- // NURL: "nurl_contents",
- // },
- // req: &openrtb2.BidRequest{App: &openrtb2.App{Bundle: "abc"}},
- // },
- // want: want{
- // eventURLs: map[string][]string{
- // "firstQuartile": {"http://company.tracker.com?eventId=firstQuartile&appbundle=abc"},
- // "midpoint": {"http://company.tracker.com?eventId=midpoint&appbundle=abc"},
- // "thirdQuartile": {"http://company.tracker.com?eventId=thirdQuartile&appbundle=abc"},
- // "complete": {"http://company.tracker.com?eventId=complete&appbundle=abc"},
- // },
- // },
- // },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- vast := ""
- if nil != tc.args.bid {
- vast = tc.args.bid.AdM // original vast
- }
- // bind this bid id with imp object
- tc.args.req.Imp = []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}}
- tc.args.bid.ImpID = tc.args.req.Imp[0].ID
- accountID := ""
- timestamp := int64(0)
- requestingBidder := "test_bidder"
- bidderCoreName := "test_core_bidder"
- injectedVast, injected, ierr := InjectVideoEventTrackers(tc.args.externalURL, vast, tc.args.bid, tc.args.genbidID, requestingBidder, bidderCoreName, accountID, timestamp, tc.args.req)
-
- if !injected {
- // expect no change in input vast if tracking events are not injected
- assert.Equal(t, vast, string(injectedVast))
- assert.NotNil(t, ierr)
- } else {
- assert.Nil(t, ierr)
- }
- actualVastDoc := etree.NewDocument()
-
- err := actualVastDoc.ReadFromBytes(injectedVast)
- if nil != err {
- assert.Fail(t, err.Error())
- }
-
- // fmt.Println(string(injectedVast))
- actualTrackingEvents := actualVastDoc.FindElements("VAST/Ad/InLine/Creatives/Creative/Linear/TrackingEvents/Tracking")
- actualTrackingEvents = append(actualTrackingEvents, actualVastDoc.FindElements("VAST/Ad/InLine/Creatives/Creative/NonLinearAds/TrackingEvents/Tracking")...)
- actualTrackingEvents = append(actualTrackingEvents, actualVastDoc.FindElements("VAST/Ad/Wrapper/Creatives/Creative/Linear/TrackingEvents/Tracking")...)
- actualTrackingEvents = append(actualTrackingEvents, actualVastDoc.FindElements("VAST/Ad/Wrapper/Creatives/Creative/NonLinearAds/TrackingEvents/Tracking")...)
-
- totalURLCount := 0
- for event, URLs := range tc.want.eventURLs {
-
- for _, expectedURL := range URLs {
- present := false
- for _, te := range actualTrackingEvents {
- if te.SelectAttr("event").Value == event && te.Text() == expectedURL {
- present = true
- totalURLCount++
- break // expected URL present. check for next expected URL
- }
- }
- if !present {
- assert.Fail(t, "Expected tracker URL '"+expectedURL+"' is not present")
- }
- }
- }
- // ensure all total of events are injected
- assert.Equal(t, totalURLCount, len(actualTrackingEvents), fmt.Sprintf("Expected '%v' event trackers. But found '%v'", len(tc.want.eventURLs), len(actualTrackingEvents)))
-
- })
- }
-}
-
-func TestGetVideoEventTracking(t *testing.T) {
- type args struct {
- trackerURL string
- bid *openrtb2.Bid
- requestingBidder string
- gen_bidid string
- bidderCoreName string
- accountId string
- timestamp int64
- req *openrtb2.BidRequest
- doc *etree.Document
- }
- type want struct {
- trackerURLMap map[string]string
- }
- tests := []struct {
- name string
- args args
- want want
- }{
{
- name: "valid_scenario",
+ name: "vast_tag_uri_response_from_partner",
args: args{
- trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
- bid: &openrtb2.Bid{
- // AdM: vastXMLWith2Creatives,
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: ``,
+ bid: &openrtb2.Bid{
+ AdM: ``,
},
req: &openrtb2.BidRequest{
- App: &openrtb2.App{
- Bundle: "someappbundle",
- },
- Imp: []openrtb2.Imp{},
+ Imp: []openrtb2.Imp{{Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
want: want{
- trackerURLMap: map[string]string{
- // "firstQuartile": "http://company.tracker.com?eventId=firstQuartile&appbundle=someappbundle",
- // "midpoint": "http://company.tracker.com?eventId=midpoint&appbundle=someappbundle",
- // "thirdQuartile": "http://company.tracker.com?eventId=thirdQuartile&appbundle=someappbundle",
- // "complete": "http://company.tracker.com?eventId=complete&appbundle=someappbundle"},
- "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=someappbundle",
- "midpoint": "http://company.tracker.com?eventId=3&appbundle=someappbundle",
- "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=someappbundle",
- "start": "http://company.tracker.com?eventId=2&appbundle=someappbundle",
- "complete": "http://company.tracker.com?eventId=6&appbundle=someappbundle"},
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
- name: "no_macro_value", // expect no replacement
+ name: "adm_empty_with_vast_build_from_modifyBidVAST",
args: args{
- trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
- bid: &openrtb2.Bid{},
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: "",
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- App: &openrtb2.App{}, // no app bundle value
- Imp: []openrtb2.Imp{},
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
want: want{
- trackerURLMap: map[string]string{
- // "firstQuartile": "http://company.tracker.com?eventId=firstQuartile&appbundle=[DOMAIN]",
- // "midpoint": "http://company.tracker.com?eventId=midpoint&appbundle=[DOMAIN]",
- // "thirdQuartile": "http://company.tracker.com?eventId=thirdQuartile&appbundle=[DOMAIN]",
- // "complete": "http://company.tracker.com?eventId=complete&appbundle=[DOMAIN]"},
- "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=",
- "midpoint": "http://company.tracker.com?eventId=3&appbundle=",
- "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=",
- "start": "http://company.tracker.com?eventId=2&appbundle=",
- "complete": "http://company.tracker.com?eventId=6&appbundle="},
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
- name: "prefer_company_value_for_standard_macro",
+ name: "adm_empty_with_vast_build_from_modifyBidVAST_non_video",
args: args{
- trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: "",
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- App: &openrtb2.App{
- Bundle: "myapp", // do not expect this value
- },
- Imp: []openrtb2.Imp{},
- Ext: []byte(`{"prebid":{
- "macros": {
- "[DOMAIN]": "my_custom_value"
- }
- }}`),
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
want: want{
- trackerURLMap: map[string]string{
- // "firstQuartile": "http://company.tracker.com?eventId=firstQuartile&appbundle=my_custom_value",
- // "midpoint": "http://company.tracker.com?eventId=midpoint&appbundle=my_custom_value",
- // "thirdQuartile": "http://company.tracker.com?eventId=thirdQuartile&appbundle=my_custom_value",
- // "complete": "http://company.tracker.com?eventId=complete&appbundle=my_custom_value"},
- "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=my_custom_value",
- "midpoint": "http://company.tracker.com?eventId=3&appbundle=my_custom_value",
- "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=my_custom_value",
- "start": "http://company.tracker.com?eventId=2&appbundle=my_custom_value",
- "complete": "http://company.tracker.com?eventId=6&appbundle=my_custom_value"},
- },
- }, {
- name: "multireplace_macro",
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ },
+ },
+ {
+ name: "vast_without_creative_tracking_node.Only_till_xpath_VAST/Ad/Wrapper/Creatives",
args: args{
- trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]¶meter2=[DOMAIN]",
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- App: &openrtb2.App{
- Bundle: "myapp123",
- },
- Imp: []openrtb2.Imp{},
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
want: want{
- trackerURLMap: map[string]string{
- // "firstQuartile": "http://company.tracker.com?eventId=firstQuartile&appbundle=myapp123¶meter2=myapp123",
- // "midpoint": "http://company.tracker.com?eventId=midpoint&appbundle=myapp123¶meter2=myapp123",
- // "thirdQuartile": "http://company.tracker.com?eventId=thirdQuartile&appbundle=myapp123¶meter2=myapp123",
- // "complete": "http://company.tracker.com?eventId=complete&appbundle=myapp123¶meter2=myapp123"},
- "firstQuartile": "http://company.tracker.com?eventId=4&appbundle=myapp123¶meter2=myapp123",
- "midpoint": "http://company.tracker.com?eventId=3&appbundle=myapp123¶meter2=myapp123",
- "thirdQuartile": "http://company.tracker.com?eventId=5&appbundle=myapp123¶meter2=myapp123",
- "start": "http://company.tracker.com?eventId=2&appbundle=myapp123¶meter2=myapp123",
- "complete": "http://company.tracker.com?eventId=6&appbundle=myapp123¶meter2=myapp123"},
+ wantVastXml: `prebid.org wrapper`,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
- name: "custom_macro_without_prefix_and_suffix",
+ name: "vast_without_linear_node.Only_till_xpath_VAST/Ad/Wrapper/Creatives/Creative",
args: args{
- trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]¶m1=[CUSTOM_MACRO]",
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- Ext: []byte(`{"prebid":{
- "macros": {
- "CUSTOM_MACRO": "my_custom_value"
- }
- }}`),
- Imp: []openrtb2.Imp{},
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
want: want{
- trackerURLMap: map[string]string{
- // "firstQuartile": "http://company.tracker.com?eventId=firstQuartile¶m1=[CUSTOM_MACRO]",
- // "midpoint": "http://company.tracker.com?eventId=midpoint¶m1=[CUSTOM_MACRO]",
- // "thirdQuartile": "http://company.tracker.com?eventId=thirdQuartile¶m1=[CUSTOM_MACRO]",
- // "complete": "http://company.tracker.com?eventId=complete¶m1=[CUSTOM_MACRO]"},
- "firstQuartile": "http://company.tracker.com?eventId=4¶m1=[CUSTOM_MACRO]",
- "midpoint": "http://company.tracker.com?eventId=3¶m1=[CUSTOM_MACRO]",
- "thirdQuartile": "http://company.tracker.com?eventId=5¶m1=[CUSTOM_MACRO]",
- "start": "http://company.tracker.com?eventId=2¶m1=[CUSTOM_MACRO]",
- "complete": "http://company.tracker.com?eventId=6¶m1=[CUSTOM_MACRO]"},
+ wantVastXml: `prebid.org wrapper`,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
- name: "empty_macro",
+ name: "vast_without_tracking_node.Only_till_xpath_VAST/Ad/Wrapper/Creatives/Creative/Linear",
args: args{
- trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]¶m1=[CUSTOM_MACRO]",
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- Ext: []byte(`{"prebid":{
- "macros": {
- "": "my_custom_value"
- }
- }}`),
- Imp: []openrtb2.Imp{},
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
want: want{
- trackerURLMap: map[string]string{
- // "firstQuartile": "http://company.tracker.com?eventId=firstQuartile¶m1=[CUSTOM_MACRO]",
- // "midpoint": "http://company.tracker.com?eventId=midpoint¶m1=[CUSTOM_MACRO]",
- // "thirdQuartile": "http://company.tracker.com?eventId=thirdQuartile¶m1=[CUSTOM_MACRO]",
- // "complete": "http://company.tracker.com?eventId=complete¶m1=[CUSTOM_MACRO]"},
- "firstQuartile": "http://company.tracker.com?eventId=4¶m1=[CUSTOM_MACRO]",
- "midpoint": "http://company.tracker.com?eventId=3¶m1=[CUSTOM_MACRO]",
- "thirdQuartile": "http://company.tracker.com?eventId=5¶m1=[CUSTOM_MACRO]",
- "start": "http://company.tracker.com?eventId=2¶m1=[CUSTOM_MACRO]",
- "complete": "http://company.tracker.com?eventId=6¶m1=[CUSTOM_MACRO]"},
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
- name: "macro_is_case_sensitive",
+ name: "vast_without_tracking_node.Only_till_xpath_VAST/Ad/Wrapper/Creatives/Creative/NonLinear",
args: args{
- trackerURL: "http://company.tracker.com?eventId=[EVENT_ID]¶m1=[CUSTOM_MACRO]",
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- Ext: []byte(`{"prebid":{
- "macros": {
- "": "my_custom_value"
- }
- }}`),
- Imp: []openrtb2.Imp{},
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
want: want{
- trackerURLMap: map[string]string{
- // "firstQuartile": "http://company.tracker.com?eventId=firstQuartile¶m1=[CUSTOM_MACRO]",
- // "midpoint": "http://company.tracker.com?eventId=midpoint¶m1=[CUSTOM_MACRO]",
- // "thirdQuartile": "http://company.tracker.com?eventId=thirdQuartile¶m1=[CUSTOM_MACRO]",
- // "complete": "http://company.tracker.com?eventId=complete¶m1=[CUSTOM_MACRO]"},
- "firstQuartile": "http://company.tracker.com?eventId=4¶m1=[CUSTOM_MACRO]",
- "midpoint": "http://company.tracker.com?eventId=3¶m1=[CUSTOM_MACRO]",
- "thirdQuartile": "http://company.tracker.com?eventId=5¶m1=[CUSTOM_MACRO]",
- "start": "http://company.tracker.com?eventId=2¶m1=[CUSTOM_MACRO]",
- "complete": "http://company.tracker.com?eventId=6¶m1=[CUSTOM_MACRO]"},
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
- name: "empty_tracker_url",
- args: args{trackerURL: " ", req: &openrtb2.BidRequest{Imp: []openrtb2.Imp{}}},
- want: want{trackerURLMap: make(map[string]string)},
+ name: "vast_without_creative_tracking_node.Only_till_xpath_VAST/Ad/InLine/Creatives",
+ args: args{
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
+ },
+ },
+ want: want{
+ wantVastXml: `prebid.org wrapper`,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ },
},
{
- name: "site_domain_tracker_url",
- args: args{trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]",
- req: &openrtb2.BidRequest{Site: &openrtb2.Site{Name: "test", Domain: "www.test.com", Publisher: &openrtb2.Publisher{ID: "5890"}}, Imp: []openrtb2.Imp{}}},
- want: want{
- map[string]string{
- "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ name: "vast_without_linear_node.Only_till_xpath_VAST/Ad/InLine/Creatives/Creative",
+ args: args{
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
+ want: want{
+ wantVastXml: `prebid.org wrapper`,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ },
},
{
- name: "site_page_tracker_url",
- args: args{trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]",
- req: &openrtb2.BidRequest{Site: &openrtb2.Site{Name: "test", Page: "https://www.test.com/", Publisher: &openrtb2.Publisher{ID: "5890"}}, Imp: []openrtb2.Imp{}}},
+ name: "vast_without_tracking_node.Only_till_xpath_VAST/Ad/InLine/Creatives/Creative/Linear",
+ args: args{
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
+ },
+ },
want: want{
- map[string]string{
- "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
- "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=&advertiser_id=&sURL=www.test.com&pfi=[PLATFORM]&af=video&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=&bidid=",
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ },
+ },
+ {
+ name: "vast_without_tracking_node.Only_till_xpath_VAST/Ad/InLine/Creatives/Creative/NonLinear",
+ args: args{
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
+ req: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
},
},
+ want: want{
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ },
},
{
- name: "all_macros with generated_bidId", // expect encoding for WRAPPER_IMPRESSION_ID macro
+ name: "vast_without_tracking_node_and_multiple_creative.All_4_xpath_Wrapper_InLine_Linear_NonLinear",
args: args{
- trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]&origbidid=[PBS-ORIG_BIDID]&bc=[BIDDER_CODE]",
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapperprebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapperprebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- App: &openrtb2.App{Bundle: "com.someapp.com", Publisher: &openrtb2.Publisher{ID: "5890"}},
- Ext: []byte(`{
- "prebid": {
- "macros": {
- "[PROFILE_ID]": "100",
- "[PROFILE_VERSION]": "2",
- "[UNIX_TIMESTAMP]": "1234567890",
- "[PLATFORM]": "7",
- "[WRAPPER_IMPRESSION_ID]": "abc~!@#$%^&&*()_+{}|:\"<>?[]\\;',./"
- }
- }
- }`),
- Imp: []openrtb2.Imp{
- {TagID: "/testadunit/1", ID: "imp_1"},
- },
- },
- bid: &openrtb2.Bid{ADomain: []string{"http://a.com/32?k=v", "b.com"}, ImpID: "imp_1", ID: "test_bid_id"},
- gen_bidid: "random_bid_id",
- requestingBidder: "test_bidder:234",
- bidderCoreName: "test_core_bidder:234",
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
+ },
},
want: want{
- trackerURLMap: map[string]string{
- "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=random_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234"},
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
{
- name: "all_macros with empty generated_bidId", // expect encoding for WRAPPER_IMPRESSION_ID macro
+ name: "vast_with_tracking_node_and_multiple_creative.All_4_xpath_Wrapper_InLine_Linear_NonLinear",
args: args{
- trackerURL: "https://company.tracker.com?operId=8&e=[EVENT_ID]&p=[PBS-ACCOUNT]&pid=[PROFILE_ID]&v=[PROFILE_VERSION]&ts=[UNIX_TIMESTAMP]&pn=[PBS-BIDDER]&advertiser_id=[ADVERTISER_NAME]&sURL=[DOMAIN]&pfi=[PLATFORM]&af=[ADTYPE]&iid=[WRAPPER_IMPRESSION_ID]&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=[AD_UNIT]&bidid=[PBS-BIDID]&origbidid=[PBS-ORIG_BIDID]&bc=[BIDDER_CODE]",
+ externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ vastXML: `prebid.org wrapperprebid.org wrapper`,
+ bid: &openrtb2.Bid{
+ ImpID: "123",
+ AdM: `prebid.org wrapperprebid.org wrapper`,
+ NURL: "nurl_contents",
+ },
req: &openrtb2.BidRequest{
- App: &openrtb2.App{Bundle: "com.someapp.com", Publisher: &openrtb2.Publisher{ID: "5890"}},
- Ext: []byte(`{
- "prebid": {
- "macros": {
- "[PROFILE_ID]": "100",
- "[PROFILE_VERSION]": "2",
- "[UNIX_TIMESTAMP]": "1234567890",
- "[PLATFORM]": "7",
- "[WRAPPER_IMPRESSION_ID]": "abc~!@#$%^&&*()_+{}|:\"<>?[]\\;',./"
- }
- }
- }`),
- Imp: []openrtb2.Imp{
- {TagID: "/testadunit/1", ID: "imp_1"},
- },
- },
- bid: &openrtb2.Bid{ADomain: []string{"http://a.com/32?k=v", "b.com"}, ImpID: "imp_1", ID: "test_bid_id"},
- gen_bidid: "",
- requestingBidder: "test_bidder:234",
- bidderCoreName: "test_core_bidder:234",
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ App: &openrtb2.App{Bundle: "abc"},
+ },
},
want: want{
- trackerURLMap: map[string]string{
- "firstQuartile": "https://company.tracker.com?operId=8&e=4&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "midpoint": "https://company.tracker.com?operId=8&e=3&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "thirdQuartile": "https://company.tracker.com?operId=8&e=5&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "complete": "https://company.tracker.com?operId=8&e=6&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234",
- "start": "https://company.tracker.com?operId=8&e=2&p=5890&pid=100&v=2&ts=1234567890&pn=test_core_bidder%3A234&advertiser_id=a.com&sURL=com.someapp.com&pfi=7&af=video&iid=abc~%21%40%23%24%25%5E%26%26%2A%28%29_%2B%7B%7D%7C%3A%22%3C%3E%3F%5B%5D%5C%3B%27%2C.%2F&pseq=[PODSEQUENCE]&adcnt=[ADCOUNT]&cb=[CACHEBUSTING]&au=%2Ftestadunit%2F1&bidid=test_bid_id&origbidid=test_bid_id&bc=test_bidder%3A234"},
+ wantVastXml: ``,
+ wantErr: nil,
+ metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
},
},
+ // {
+ // name: "vast_and_adm_empty - This should never be the case as modifyBidVAST always updates AdM with tempate vast",
+ // args: args{
+ // externalURL: "http://company.tracker.com?eventId=[EVENT_ID]&appbundle=[DOMAIN]",
+ // vastXML: "",
+ // bid: &openrtb2.Bid{ // Adm contains to TrackingEvents tag
+ // AdM: "",
+ // NURL: "nurl_contents",
+ // },
+ // req: &openrtb2.BidRequest{App: &openrtb2.App{Bundle: "abc"}},
+ // },
+ // want : want{
+ // wantVastXml: "",
+ // wantErr: errors.New("error parsing VAST XML. 'EOF'"),
+ // metrics: &openrtb_ext.FastXMLMetrics{IsRespMismatch: false},
+ // },
+ // },
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
+ injectedVast, metrics, err := InjectVideoEventTrackers(tc.args.req, tc.args.bid, tc.args.vastXML, tc.args.externalURL, tc.args.genbidID, "test_bidder", "test_core_bidder", int64(0), true)
+ assert.Equal(t, tc.want.wantErr, err)
+ assert.Equal(t, tc.want.wantVastXml, string(injectedVast))
+ if tc.want.metrics != nil {
+ assert.NotNil(t, metrics)
+ assert.Equal(t, tc.want.metrics.IsRespMismatch, metrics.IsRespMismatch)
+ }
+ })
+ }
+}
- if nil == tc.args.bid {
- tc.args.bid = &openrtb2.Bid{}
+func quoteUnescape[T []byte | string](s T) string {
+ buf := bytes.Buffer{}
+ for i := 0; i < len(s); i++ {
+ ch := s[i]
+ if ch == '\\' {
+ if i+1 < len(s) {
+ nextCh := s[i+1]
+ if nextCh == '\\' || nextCh == '"' || nextCh == '\'' {
+ i++
+ ch = nextCh
+ }
}
+ }
+ buf.WriteByte(ch)
+ }
+ return buf.String()
+}
- impMap := map[string]*openrtb2.Imp{}
+func TestCompareXMLParsers(t *testing.T) {
+ fileName := `./test/raw_vast.txt`
+ //fileName = `../../base64_vast.txt`
- for _, imp := range tc.args.req.Imp {
- impMap[imp.ID] = &imp
- }
+ base64Decode := strings.Contains(fileName, "base64")
+
+ file, err := os.Open(fileName)
+ if !assert.Nil(t, err) {
+ return
+ }
- eventURLMap := GetVideoEventTracking(tc.args.trackerURL, tc.args.bid, tc.args.gen_bidid, tc.args.requestingBidder, tc.args.bidderCoreName, tc.args.accountId, tc.args.timestamp, tc.args.req, tc.args.doc, impMap)
+ defer file.Close()
+ var mismatched, debugLines []int
+ line := 0
+ scanner := bufio.NewScanner(file)
+ scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
- for event, eurl := range tc.want.trackerURLMap {
+ //debugLines = []int{19, 24, 25, 29, 58, 80, 83, 84, 86, 93, 128, 147, 151, 155, 159, 168, 184, 190, 199, 200, 225, 226, 243, 249, 254, 261, 272, 281, 291, 298, 310, 312, 320, 323, 328, 340, 350, 358, 362, 373, 376, 384}
+ sort.Ints(debugLines)
- u, _ := url.Parse(eurl)
- expectedValues, _ := url.ParseQuery(u.RawQuery)
- u, _ = url.Parse(eventURLMap[event])
- actualValues, _ := url.ParseQuery(u.RawQuery)
- for k, ev := range expectedValues {
- av := actualValues[k]
- for i := 0; i < len(ev); i++ {
- assert.Equal(t, ev[i], av[i], fmt.Sprintf("Expected '%v' for '%v'. but found %v", ev[i], k, av[i]))
- }
- }
+ for scanner.Scan() {
+ line++
+ vast := scanner.Text()
+ if len(debugLines) > 0 && sort.SearchInts(debugLines, line) == len(debugLines) {
+ continue
+ }
- // error out if extra query params
- if len(expectedValues) != len(actualValues) {
- assert.Equal(t, expectedValues, actualValues, fmt.Sprintf("Expected '%v' query params but found '%v'", len(expectedValues), len(actualValues)))
- break
- }
+ if base64Decode {
+ data, err := base64.StdEncoding.DecodeString(vast)
+ if !assert.Nil(t, err) {
+ continue
+ }
+ vast = quoteUnescape(data)
+ }
+ t.Run(fmt.Sprintf("vast_%d", line), func(t *testing.T) {
+ etreeXML, _ := injectVideoEventsETree(vast, eventURLMap, false, adcom1.LinearityLinear)
+ fastXML, _ := injectVideoEventsFastXML(vast, eventURLMap, false, adcom1.LinearityLinear)
+ if vast != fastXML {
+ fastXML = tmpFastXMLProcessing(fastXML)
}
- // check if new quartile pixels are covered inside test
- assert.Equal(t, tc.want.trackerURLMap, eventURLMap)
+ if !assert.Equal(t, etreeXML, fastXML) {
+ mismatched = append(mismatched, line)
+ }
})
}
+ t.Logf("\ntotal:[%v] mismatched:[%v] lines:[%v]", line, len(mismatched), mismatched)
+ assert.Equal(t, 0, len(mismatched))
+ assert.Nil(t, scanner.Err())
}
-func TestReplaceMacro(t *testing.T) {
- type args struct {
- trackerURL string
- macro string
- value string
- }
- type want struct {
- trackerURL string
- }
- tests := []struct {
- name string
- args args
- want want
- }{
- {name: "empty_tracker_url", args: args{trackerURL: "", macro: "[TEST]", value: "testme"}, want: want{trackerURL: ""}},
- {name: "tracker_url_with_macro", args: args{trackerURL: "http://something.com?test=[TEST]", macro: "[TEST]", value: "testme"}, want: want{trackerURL: "http://something.com?test=testme"}},
- {name: "tracker_url_with_invalid_macro", args: args{trackerURL: "http://something.com?test=TEST]", macro: "[TEST]", value: "testme"}, want: want{trackerURL: "http://something.com?test=TEST]"}},
- {name: "tracker_url_with_repeating_macro", args: args{trackerURL: "http://something.com?test=[TEST]&test1=[TEST]", macro: "[TEST]", value: "testme"}, want: want{trackerURL: "http://something.com?test=testme&test1=testme"}},
- {name: "empty_macro", args: args{trackerURL: "http://something.com?test=[TEST]", macro: "", value: "testme"}, want: want{trackerURL: "http://something.com?test=[TEST]"}},
- {name: "macro_without_[", args: args{trackerURL: "http://something.com?test=[TEST]", macro: "TEST]", value: "testme"}, want: want{trackerURL: "http://something.com?test=[TEST]"}},
- {name: "macro_without_]", args: args{trackerURL: "http://something.com?test=[TEST]", macro: "[TEST", value: "testme"}, want: want{trackerURL: "http://something.com?test=[TEST]"}},
- {name: "empty_value", args: args{trackerURL: "http://something.com?test=[TEST]", macro: "[TEST]", value: ""}, want: want{trackerURL: "http://something.com?test="}},
- {name: "nested_macro_value", args: args{trackerURL: "http://something.com?test=[TEST]", macro: "[TEST]", value: "[TEST][TEST]"}, want: want{trackerURL: "http://something.com?test=%5BTEST%5D%5BTEST%5D"}},
- {name: "url_as_macro_value", args: args{trackerURL: "http://something.com?test=[TEST]", macro: "[TEST]", value: "http://iamurl.com"}, want: want{trackerURL: "http://something.com?test=http%3A%2F%2Fiamurl.com"}},
- {name: "macro_with_spaces", args: args{trackerURL: "http://something.com?test=[TEST]", macro: " [TEST] ", value: "http://iamurl.com"}, want: want{trackerURL: "http://something.com?test=http%3A%2F%2Fiamurl.com"}},
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- trackerURL := replaceMacro(tc.args.trackerURL, tc.args.macro, tc.args.value)
- assert.Equal(t, tc.want.trackerURL, trackerURL)
- })
- }
+func TestBase64(t *testing.T) {
+ fileName := `./test/ow_failed.txt`
-}
-func TestExtractDomain(t *testing.T) {
- testCases := []struct {
- description string
- url string
- expectedDomain string
- expectedErr error
- }{
- {description: "a.com", url: "a.com", expectedDomain: "a.com", expectedErr: nil},
- {description: "a.com/123", url: "a.com/123", expectedDomain: "a.com", expectedErr: nil},
- {description: "http://a.com/123", url: "http://a.com/123", expectedDomain: "a.com", expectedErr: nil},
- {description: "https://a.com/123", url: "https://a.com/123", expectedDomain: "a.com", expectedErr: nil},
- {description: "c.b.a.com", url: "c.b.a.com", expectedDomain: "c.b.a.com", expectedErr: nil},
- {description: "url_encoded_http://c.b.a.com", url: "http%3A%2F%2Fc.b.a.com", expectedDomain: "c.b.a.com", expectedErr: nil},
- {description: "url_encoded_with_www_http://c.b.a.com", url: "http%3A%2F%2Fwww.c.b.a.com", expectedDomain: "c.b.a.com", expectedErr: nil},
+ file, err := os.Open(fileName)
+ if !assert.Nil(t, err) {
+ return
}
- for _, test := range testCases {
- t.Run(test.description, func(t *testing.T) {
- domain, err := extractDomain(test.url)
- assert.Equal(t, test.expectedDomain, domain)
- assert.Equal(t, test.expectedErr, err)
- })
+
+ defer file.Close()
+ var mismatched, errored, debugLines []int
+ var line, singleQuotePresent, maxLength int
+
+ maxLength = 14884
+ scanner := bufio.NewScanner(file)
+ scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
+
+ //debugLines = []int{19, 24, 25, 29, 58, 80, 83, 84, 86, 93, 128, 147, 151, 155, 159, 168, 184, 190, 199, 200, 225, 226, 243, 249, 254, 261, 272, 281, 291, 298, 310, 312, 320, 323, 328, 340, 350, 358, 362, 373, 376, 384}
+ sort.Ints(debugLines)
+
+ for scanner.Scan() {
+ line++
+ value := scanner.Text()
+
+ if len(debugLines) > 0 && sort.SearchInts(debugLines, line) == len(debugLines) {
+ continue
+ }
+
+ vast, err := base64.RawStdEncoding.DecodeString(value[0:maxLength])
+
+ if err != nil {
+ errored = append(errored, line)
+ continue
+ }
+
+ if bytes.Contains(vast, []byte("'")) {
+ singleQuotePresent++
+ } else {
+ mismatched = append(mismatched, line)
+ }
}
+ assert.Empty(t, mismatched)
+ assert.Empty(t, errored)
}
diff --git a/exchange/adapter_util.go b/exchange/adapter_util.go
index 2412fb314fe..dc6b1a8753f 100644
--- a/exchange/adapter_util.go
+++ b/exchange/adapter_util.go
@@ -11,7 +11,7 @@ import (
)
func BuildAdapters(client *http.Client, cfg *config.Configuration, infos config.BidderInfos, me metrics.MetricsEngine) (map[openrtb_ext.BidderName]AdaptedBidder, []error) {
- server := config.Server{ExternalUrl: cfg.ExternalURL, GvlID: cfg.GDPR.HostVendorID, DataCenter: cfg.DataCenter, EnableFastXML: cfg.EnableFastXML}
+ server := config.Server{ExternalUrl: cfg.ExternalURL, GvlID: cfg.GDPR.HostVendorID, DataCenter: cfg.DataCenter, FastXMLEnabledPercentage: cfg.FastXMLEnabledPercentage}
bidders, errs := buildBidders(infos, newAdapterBuilders(), server)
if len(errs) > 0 {
diff --git a/exchange/events.go b/exchange/events.go
index 2ec63ccfefb..4d9f2bf4a8c 100644
--- a/exchange/events.go
+++ b/exchange/events.go
@@ -16,10 +16,10 @@ import (
// eventTracking has configuration fields needed for adding event tracking to an auction response
type eventTracking struct {
+ OpenWrapEventTracking
accountID string
enabledForAccount bool
enabledForRequest bool
- enabledVideoEvents bool //TODO: OPENWRAP Video Events Flag
auctionTimestampMs int64
integrationType string
bidderInfos config.BidderInfos
@@ -27,16 +27,16 @@ type eventTracking struct {
}
// getEventTracking creates an eventTracking object from the different configuration sources
-func getEventTracking(requestExtPrebid *openrtb_ext.ExtRequestPrebid, ts time.Time, account *config.Account, bidderInfos config.BidderInfos, externalURL string) *eventTracking {
+func getEventTracking(requestExtPrebid *openrtb_ext.ExtRequestPrebid, ts time.Time, account *config.Account, bidderInfos config.BidderInfos, externalURL string, owEventTracking OpenWrapEventTracking) *eventTracking {
return &eventTracking{
- accountID: account.ID,
- enabledForAccount: account.Events.Enabled,
- enabledForRequest: requestExtPrebid != nil && requestExtPrebid.Events != nil,
- enabledVideoEvents: requestExtPrebid == nil || !requestExtPrebid.ExtOWRequestPrebid.TrackerDisabled,
- auctionTimestampMs: ts.UnixNano() / 1e+6,
- integrationType: getIntegrationType(requestExtPrebid),
- bidderInfos: bidderInfos,
- externalURL: externalURL,
+ accountID: account.ID,
+ enabledForAccount: account.Events.Enabled,
+ enabledForRequest: requestExtPrebid != nil && requestExtPrebid.Events != nil,
+ auctionTimestampMs: ts.UnixNano() / 1e+6,
+ integrationType: getIntegrationType(requestExtPrebid),
+ bidderInfos: bidderInfos,
+ externalURL: externalURL,
+ OpenWrapEventTracking: owEventTracking,
}
}
@@ -81,12 +81,7 @@ func (ev *eventTracking) modifyBidVAST(pbsBid *entities.PbsOrtbBid, bidderName o
}
}
- if ev.enabledVideoEvents {
- // always inject event trackers without checkign isModifyingVASTXMLAllowed
- if newVastXML, injected, _ := events.InjectVideoEventTrackers(trackerURL, vastXML, bid, bidID, bidderName.String(), bidderCoreName.String(), ev.accountID, ev.auctionTimestampMs, req); injected {
- bid.AdM = string(newVastXML)
- }
- }
+ ev.injectVideoEvents(req, bid, vastXML, trackerURL, bidID, bidderName.String(), bidderCoreName.String())
}
// modifyBidJSON injects "wurl" (win) event url if needed, otherwise returns original json
diff --git a/exchange/events_ow.go b/exchange/events_ow.go
new file mode 100644
index 00000000000..61e45e9e336
--- /dev/null
+++ b/exchange/events_ow.go
@@ -0,0 +1,34 @@
+package exchange
+
+import (
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/endpoints/events"
+ "github.com/prebid/prebid-server/v2/metrics"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
+)
+
+type OpenWrapEventTracking struct {
+ enabledVideoEvents bool
+ fastXMLEnabledPercentage int
+ me metrics.MetricsEngine
+}
+
+func (ev *eventTracking) injectVideoEvents(
+ bidRequest *openrtb2.BidRequest,
+ bid *openrtb2.Bid,
+ vastXML, trackerURL, bidID, requestingBidder, bidderCoreName string) {
+
+ if !ev.enabledVideoEvents {
+ return
+ }
+
+ // always inject event trackers without checkign isModifyingVASTXMLAllowed
+ newVastXML, metrics, err := events.InjectVideoEventTrackers(bidRequest, bid, vastXML, trackerURL, bidID, requestingBidder, bidderCoreName, ev.auctionTimestampMs, openrtb_ext.IsFastXMLEnabled(ev.fastXMLEnabledPercentage))
+ if err == nil {
+ bid.AdM = newVastXML
+ }
+
+ if metrics != nil && ev.me != nil {
+ recordFastXMLMetrics(ev.me, "vcr", metrics)
+ }
+}
diff --git a/exchange/events_ow_test.go b/exchange/events_ow_test.go
new file mode 100644
index 00000000000..f7bfcd4e2f3
--- /dev/null
+++ b/exchange/events_ow_test.go
@@ -0,0 +1,74 @@
+package exchange
+
+import (
+ "testing"
+
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/config"
+ "github.com/prebid/prebid-server/v2/exchange/entities"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestModifyBidVAST(t *testing.T) {
+ type args struct {
+ enabledVideoEvents bool
+ bidReq *openrtb2.BidRequest
+ bid *openrtb2.Bid
+ }
+ tests := []struct {
+ name string
+ args args
+ wantAdM string
+ }{
+ {
+ name: "empty_adm", // expect adm contain vast tag with tracking events and VASTAdTagURI nurl contents
+ args: args{
+ enabledVideoEvents: true,
+ bidReq: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ },
+ bid: &openrtb2.Bid{
+ AdM: "",
+ NURL: "nurl_contents",
+ ImpID: "123",
+ },
+ },
+ wantAdM: ``,
+ },
+ {
+ name: "adm_containing_url", // expect adm contain vast tag with tracking events and VASTAdTagURI adm url (previous value) contents
+ args: args{
+ enabledVideoEvents: true,
+ bidReq: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
+ },
+ bid: &openrtb2.Bid{
+ AdM: "http://vast_tag_inline.xml",
+ NURL: "nurl_contents",
+ ImpID: "123",
+ },
+ },
+ wantAdM: ``,
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ ev := eventTracking{
+ bidderInfos: config.BidderInfos{
+ "somebidder": config.BidderInfo{
+ ModifyingVastXmlAllowed: false,
+ },
+ },
+ OpenWrapEventTracking: OpenWrapEventTracking{
+ enabledVideoEvents: tc.args.enabledVideoEvents,
+ },
+ }
+ ev.modifyBidVAST(&entities.PbsOrtbBid{
+ Bid: tc.args.bid,
+ BidType: openrtb_ext.BidTypeVideo,
+ }, "somebidder", "coreBidder", tc.args.bidReq, "http://company.tracker.com?e=[EVENT_ID]")
+ assert.Equal(t, tc.wantAdM, tc.args.bid.AdM)
+ })
+ }
+}
diff --git a/exchange/events_test.go b/exchange/events_test.go
index 0dd3c8a9920..a4ed587cd67 100644
--- a/exchange/events_test.go
+++ b/exchange/events_test.go
@@ -1,11 +1,9 @@
package exchange
import (
- "strings"
"testing"
"github.com/prebid/openrtb/v20/openrtb2"
- "github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/exchange/entities"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/stretchr/testify/assert"
@@ -194,112 +192,3 @@ func Test_isEventAllowed(t *testing.T) {
})
}
}
-
-func TestModifyBidVAST(t *testing.T) {
- type args struct {
- enabledVideoEvents bool
- bidReq *openrtb2.BidRequest
- bid *openrtb2.Bid
- }
- type want struct {
- tags []string
- }
- tests := []struct {
- name string
- args args
- want want
- }{
- {
- name: "empty_adm", // expect adm contain vast tag with tracking events and VASTAdTagURI nurl contents
- args: args{
- enabledVideoEvents: true,
- bidReq: &openrtb2.BidRequest{
- Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
- },
- bid: &openrtb2.Bid{
- AdM: "",
- NURL: "nurl_contents",
- ImpID: "123",
- },
- },
- want: want{
- tags: []string{
- // ``,
- // ``,
- // ``,
- // ``,
- // "",
- // "",
- // "",
- ``,
- ``,
- ``,
- ``,
- "",
- "",
- "",
- },
- },
- },
- {
- name: "adm_containing_url", // expect adm contain vast tag with tracking events and VASTAdTagURI adm url (previous value) contents
- args: args{
- enabledVideoEvents: true,
- bidReq: &openrtb2.BidRequest{
- Imp: []openrtb2.Imp{{ID: "123", Video: &openrtb2.Video{}}},
- },
- bid: &openrtb2.Bid{
- AdM: "http://vast_tag_inline.xml",
- NURL: "nurl_contents",
- ImpID: "123",
- },
- },
- want: want{
- tags: []string{
- // ``,
- // ``,
- // ``,
- // ``,
- // "",
- // "",
- // "",
- ``,
- ``,
- ``,
- ``,
- "",
- "",
- "",
- },
- },
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- ev := eventTracking{
- bidderInfos: config.BidderInfos{
- "somebidder": config.BidderInfo{
- ModifyingVastXmlAllowed: false,
- },
- },
- enabledVideoEvents: tc.args.enabledVideoEvents,
- }
- ev.modifyBidVAST(&entities.PbsOrtbBid{
- Bid: tc.args.bid,
- BidType: openrtb_ext.BidTypeVideo,
- }, "somebidder", "coreBidder", tc.args.bidReq, "http://company.tracker.com?e=[EVENT_ID]")
- validator(t, tc.args.bid, tc.want.tags)
- })
- }
-}
-
-func validator(t *testing.T, b *openrtb2.Bid, expectedTags []string) {
- adm := b.AdM
- assert.NotNil(t, adm)
- assert.NotEmpty(t, adm)
- // check tags are present
-
- for _, tag := range expectedTags {
- assert.True(t, strings.Contains(adm, tag), "expected '"+tag+"' tag in Adm")
- }
-}
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 166a5675547..29ed299a87d 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -176,7 +176,7 @@ func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid
bidIDGenerator: &bidIDGenerator{cfg.GenerateBidID},
hostSChainNode: cfg.HostSChainNode,
adsCertSigner: adsCertSigner,
- server: config.Server{ExternalUrl: cfg.ExternalURL, GvlID: cfg.GDPR.HostVendorID, DataCenter: cfg.DataCenter},
+ server: config.Server{ExternalUrl: cfg.ExternalURL, GvlID: cfg.GDPR.HostVendorID, DataCenter: cfg.DataCenter, FastXMLEnabledPercentage: cfg.FastXMLEnabledPercentage},
bidValidationEnforcement: cfg.Validations,
requestSplitter: requestSplitter,
macroReplacer: macroReplacer,
@@ -493,7 +493,12 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
}
}
- evTracking := getEventTracking(requestExtPrebid, r.StartTime, &r.Account, e.bidderInfo, e.externalURL)
+ evTracking := getEventTracking(requestExtPrebid, r.StartTime, &r.Account, e.bidderInfo, e.externalURL,
+ OpenWrapEventTracking{
+ enabledVideoEvents: requestExtPrebid == nil || !requestExtPrebid.ExtOWRequestPrebid.TrackerDisabled,
+ fastXMLEnabledPercentage: e.server.FastXMLEnabledPercentage,
+ me: e.me,
+ })
adapterBids = evTracking.modifyBidsForEvents(adapterBids, r.BidRequestWrapper.BidRequest, e.trakerURL)
r.HookExecutor.ExecuteAllProcessedBidResponsesStage(adapterBids)
diff --git a/exchange/exchange_ow.go b/exchange/exchange_ow.go
index b02899742da..fc9c52e9d72 100644
--- a/exchange/exchange_ow.go
+++ b/exchange/exchange_ow.go
@@ -202,20 +202,20 @@ func recordOpenWrapBidResponseMetrics(bidder *bidderAdapter, bidResponse *adapte
}
if bidResponse.FastXMLMetrics != nil {
- recordFastXMLMetrics(bidder.me, "vastbidder", string(bidder.BidderName), bidResponse.FastXMLMetrics)
+ recordFastXMLMetrics(bidder.me, "vastbidder", bidResponse.FastXMLMetrics)
if bidResponse.FastXMLMetrics.IsRespMismatch {
resp, _ := jsonutil.Marshal(bidResponse)
- glog.V(2).Infof("\n[VAST_BIDDER] Response Mismatch for Creative : %s", string(resp))
+ openrtb_ext.FastXMLLogf("\n[XML_PARSER_TEST] method:[vast_bidder] response:[%s]", resp)
}
}
recordVASTTagType(bidder.me, bidResponse, bidder.BidderName)
}
-func recordFastXMLMetrics(metricsEngine metrics.MetricsEngine, method string, bidder string, vastBidderInfo *openrtb_ext.FastXMLMetrics) {
- metricsEngine.RecordXMLParserResponseTime(metrics.XMLParserLabelFastXML, method, bidder, vastBidderInfo.XMLParserTime)
- metricsEngine.RecordXMLParserResponseTime(metrics.XMLParserLabelETree, method, bidder, vastBidderInfo.EtreeParserTime)
- metricsEngine.RecordXMLParserResponseMismatch(method, bidder, vastBidderInfo.IsRespMismatch)
+func recordFastXMLMetrics(metricsEngine metrics.MetricsEngine, method string, vastBidderInfo *openrtb_ext.FastXMLMetrics) {
+ metricsEngine.RecordXMLParserResponseTime(metrics.XMLParserLabelFastXML, method, vastBidderInfo.XMLParserTime)
+ metricsEngine.RecordXMLParserResponseTime(metrics.XMLParserLabelETree, method, vastBidderInfo.EtreeParserTime)
+ metricsEngine.RecordXMLParserResponseMismatch(method, vastBidderInfo.IsRespMismatch)
}
func recordVASTTagType(metricsEngine metrics.MetricsEngine, adapterBids *adapters.BidderResponse, bidder openrtb_ext.BidderName) {
diff --git a/exchange/exchange_ow_test.go b/exchange/exchange_ow_test.go
index 661cf4b6b2e..6a4337aad3c 100644
--- a/exchange/exchange_ow_test.go
+++ b/exchange/exchange_ow_test.go
@@ -680,7 +680,7 @@ func TestNormalizeDomain(t *testing.T) {
func newTestTagAdapter(name string) *bidderAdapter {
return &bidderAdapter{
- Bidder: vastbidder.NewTagBidder(openrtb_ext.BidderName(name), config.Adapter{}, false),
+ Bidder: vastbidder.NewTagBidder(openrtb_ext.BidderName(name), config.Adapter{}, 0),
BidderName: openrtb_ext.BidderName(name),
}
}
@@ -1823,7 +1823,6 @@ func TestRecordFastXMLMetrics(t *testing.T) {
testMethodName := "test"
type args struct {
- bidder string
vastBidderInfo *openrtb_ext.FastXMLMetrics
getMetricsEngine func() *metrics.MetricsEngineMock
}
@@ -1835,7 +1834,6 @@ func TestRecordFastXMLMetrics(t *testing.T) {
{
name: "Record_Fast_XML_Metrics_Respnse_matched",
args: args{
- bidder: "pubmatic",
vastBidderInfo: &openrtb_ext.FastXMLMetrics{
XMLParserTime: time.Millisecond * 10,
EtreeParserTime: time.Millisecond * 20,
@@ -1843,9 +1841,9 @@ func TestRecordFastXMLMetrics(t *testing.T) {
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
- metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelFastXML, testMethodName, "pubmatic", time.Millisecond*10).Return()
- metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelETree, testMethodName, "pubmatic", time.Millisecond*20).Return()
- metricEngine.Mock.On("RecordXMLParserResponseMismatch", testMethodName, "pubmatic", false).Return()
+ metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelFastXML, testMethodName, time.Millisecond*10).Return()
+ metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelETree, testMethodName, time.Millisecond*20).Return()
+ metricEngine.Mock.On("RecordXMLParserResponseMismatch", testMethodName, false).Return()
return metricEngine
},
},
@@ -1853,7 +1851,6 @@ func TestRecordFastXMLMetrics(t *testing.T) {
{
name: "Record_Fast_XML_Metrics_Respnse_mismatched",
args: args{
- bidder: "pubmatic",
vastBidderInfo: &openrtb_ext.FastXMLMetrics{
XMLParserTime: time.Millisecond * 15,
EtreeParserTime: time.Millisecond * 25,
@@ -1861,9 +1858,9 @@ func TestRecordFastXMLMetrics(t *testing.T) {
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
- metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelFastXML, testMethodName, "pubmatic", time.Millisecond*15).Return()
- metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelETree, testMethodName, "pubmatic", time.Millisecond*25).Return()
- metricEngine.Mock.On("RecordXMLParserResponseMismatch", testMethodName, "pubmatic", true).Return()
+ metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelFastXML, testMethodName, time.Millisecond*15).Return()
+ metricEngine.Mock.On("RecordXMLParserResponseTime", metrics.XMLParserLabelETree, testMethodName, time.Millisecond*25).Return()
+ metricEngine.Mock.On("RecordXMLParserResponseMismatch", testMethodName, true).Return()
return metricEngine
},
},
@@ -1873,7 +1870,7 @@ func TestRecordFastXMLMetrics(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockMetricEngine := tt.args.getMetricsEngine()
- recordFastXMLMetrics(mockMetricEngine, testMethodName, tt.args.bidder, tt.args.vastBidderInfo)
+ recordFastXMLMetrics(mockMetricEngine, testMethodName, tt.args.vastBidderInfo)
mockMetricEngine.AssertExpectations(t)
})
}
diff --git a/go.mod b/go.mod
index b9f7f938308..fdf70090dc8 100644
--- a/go.mod
+++ b/go.mod
@@ -2,7 +2,7 @@ module github.com/PubMatic-OpenWrap/prebid-server/v2
go 1.20
-replace git.pubmatic.com/vastunwrap => git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240319050712-0b288cbb5a5d
+replace git.pubmatic.com/vastunwrap => git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240827084017-0e392d3beb8b
require (
github.com/DATA-DOG/go-sqlmock v1.5.0
@@ -51,7 +51,7 @@ require (
git.pubmatic.com/PubMatic/go-common v0.0.0-20240313090142-97ff3d63b7c3
git.pubmatic.com/PubMatic/go-netacuity-client v0.0.0-20240104092757-5d6f15e25fe3
git.pubmatic.com/vastunwrap v0.0.0-00010101000000-000000000000
- github.com/PubMatic-OpenWrap/fastxml v0.0.0-20240621094509-2f843d282179
+ github.com/PubMatic-OpenWrap/fastxml v0.0.0-20240826060652-d9d5d05fdad2
github.com/diegoholiveira/jsonlogic/v3 v3.5.3
github.com/go-sql-driver/mysql v1.7.1
github.com/golang/mock v1.6.0
@@ -88,9 +88,9 @@ require (
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
+ github.com/yudai/pp v2.0.1+incompatible // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/sys v0.18.0 // indirect
- github.com/yudai/pp v2.0.1+incompatible // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
@@ -100,6 +100,6 @@ replace github.com/prebid/prebid-server/v2 => ./
replace github.com/prebid/openrtb/v20 => github.com/PubMatic-OpenWrap/prebid-openrtb/v20 v20.0.0-20240222072752-2d647d1707ef
-replace github.com/beevik/etree v1.0.2 => github.com/PubMatic-OpenWrap/etree v1.0.2-0.20210129100623-8f30cfecf9f4
+replace github.com/beevik/etree v1.0.2 => github.com/PubMatic-OpenWrap/etree v1.0.2-0.20240914050009-a916f68552f5
replace github.com/beevik/etree/110 => github.com/beevik/etree v1.1.0
diff --git a/go.sum b/go.sum
index 13321359a53..51dad9957bb 100644
--- a/go.sum
+++ b/go.sum
@@ -29,321 +29,63 @@ cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
-cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
-cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
-cloud.google.com/go/accessapproval v1.6.0 h1:x0cEHro/JFPd7eS4BlEWNTMecIj2HdXjOVB5BtvwER0=
-cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
-cloud.google.com/go/accesscontextmanager v1.7.0 h1:MG60JgnEoawHJrbWw0jGdv6HLNSf6gQvYRiXpuzqgEA=
-cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ=
-cloud.google.com/go/aiplatform v1.37.0 h1:zTw+suCVchgZyO+k847wjzdVjWmrAuehxdvcZvJwfGg=
-cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw=
-cloud.google.com/go/analytics v0.19.0 h1:LqAo3tAh2FU9+w/r7vc3hBjU23Kv7GhO/PDIW7kIYgM=
-cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE=
-cloud.google.com/go/apigateway v1.5.0 h1:ZI9mVO7x3E9RK/BURm2p1aw9YTBSCQe3klmyP1WxWEg=
-cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8=
-cloud.google.com/go/apigeeconnect v1.5.0 h1:sWOmgDyAsi1AZ48XRHcATC0tsi9SkPT7DA/+VCfkaeA=
-cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8=
-cloud.google.com/go/apigeeregistry v0.6.0 h1:E43RdhhCxdlV+I161gUY2rI4eOaMzHTA5kNkvRsFXvc=
-cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc=
-cloud.google.com/go/apikeys v0.6.0 h1:B9CdHFZTFjVti89tmyXXrO+7vSNo2jvZuHG8zD5trdQ=
-cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8=
-cloud.google.com/go/appengine v1.7.1 h1:aBGDKmRIaRRoWJ2tAoN0oVSHoWLhtO9aj/NvUyP4aYs=
-cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E=
-cloud.google.com/go/area120 v0.7.1 h1:ugckkFh4XkHJMPhTIx0CyvdoBxmOpMe8rNs4Ok8GAag=
-cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k=
-cloud.google.com/go/artifactregistry v1.13.0 h1:o1Q80vqEB6Qp8WLEH3b8FBLNUCrGQ4k5RFj0sn/sgO8=
-cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08=
-cloud.google.com/go/asset v1.13.0 h1:YAsssO08BqZ6mncbb6FPlj9h6ACS7bJQUOlzciSfbNk=
-cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw=
-cloud.google.com/go/assuredworkloads v1.10.0 h1:VLGnVFta+N4WM+ASHbhc14ZOItOabDLH1MSoDv+Xuag=
-cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E=
-cloud.google.com/go/automl v1.12.0 h1:50VugllC+U4IGl3tDNcZaWvApHBTrn/TvyHDJ0wM+Uw=
-cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU=
-cloud.google.com/go/baremetalsolution v0.5.0 h1:2AipdYXL0VxMboelTTw8c1UJ7gYu35LZYUbuRv9Q28s=
-cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss=
-cloud.google.com/go/batch v0.7.0 h1:YbMt0E6BtqeD5FvSv1d56jbVsWEzlGm55lYte+M6Mzs=
-cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g=
-cloud.google.com/go/beyondcorp v0.5.0 h1:UkY2BTZkEUAVrgqnSdOJ4p3y9ZRBPEe1LkjgC8Bj/Pc=
-cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/bigquery v1.50.0 h1:RscMV6LbnAmhAzD893Lv9nXXy2WCaJmbxYPWDLbGqNQ=
-cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU=
-cloud.google.com/go/billing v1.13.0 h1:JYj28UYF5w6VBAh0gQYlgHJ/OD1oA+JgW29YZQU+UHM=
-cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc=
-cloud.google.com/go/binaryauthorization v1.5.0 h1:d3pMDBCCNivxt5a4eaV7FwL7cSH0H7RrEnFrTb1QKWs=
-cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q=
-cloud.google.com/go/certificatemanager v1.6.0 h1:5C5UWeSt8Jkgp7OWn2rCkLmYurar/vIWIoSQ2+LaTOc=
-cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8=
-cloud.google.com/go/channel v1.12.0 h1:GpcQY5UJKeOekYgsX3QXbzzAc/kRGtBq43fTmyKe6Uw=
-cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU=
-cloud.google.com/go/cloudbuild v1.9.0 h1:GHQCjV4WlPPVU/j3Rlpc8vNIDwThhd1U9qSY/NPZdko=
-cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s=
-cloud.google.com/go/clouddms v1.5.0 h1:E7v4TpDGUyEm1C/4KIrpVSOCTm0P6vWdHT0I4mostRA=
-cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA=
-cloud.google.com/go/cloudtasks v1.10.0 h1:uK5k6abf4yligFgYFnG0ni8msai/dSv6mDmiBulU0hU=
-cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs=
-cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
-cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
-cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
-cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
-cloud.google.com/go/contactcenterinsights v1.6.0 h1:jXIpfcH/VYSE1SYcPzO0n1VVb+sAamiLOgCw45JbOQk=
-cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
-cloud.google.com/go/container v1.15.0 h1:NKlY/wCDapfVZlbVVaeuu2UZZED5Dy1z4Zx1KhEzm8c=
-cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA=
-cloud.google.com/go/containeranalysis v0.9.0 h1:EQ4FFxNaEAg8PqQCO7bVQfWz9NVwZCUKaM1b3ycfx3U=
-cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s=
-cloud.google.com/go/datacatalog v1.13.0 h1:4H5IJiyUE0X6ShQBqgFFZvGGcrwGVndTwUSLP4c52gw=
-cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8=
-cloud.google.com/go/dataflow v0.8.0 h1:eYyD9o/8Nm6EttsKZaEGD84xC17bNgSKCu0ZxwqUbpg=
-cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE=
-cloud.google.com/go/dataform v0.7.0 h1:Dyk+fufup1FR6cbHjFpMuP4SfPiF3LI3JtoIIALoq48=
-cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE=
-cloud.google.com/go/datafusion v1.6.0 h1:sZjRnS3TWkGsu1LjYPFD/fHeMLZNXDK6PDHi2s2s/bk=
-cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8=
-cloud.google.com/go/datalabeling v0.7.0 h1:ch4qA2yvddGRUrlfwrNJCr79qLqhS9QBwofPHfFlDIk=
-cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM=
-cloud.google.com/go/dataplex v1.6.0 h1:RvoZ5T7gySwm1CHzAw7yY1QwwqaGswunmqEssPxU/AM=
-cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs=
-cloud.google.com/go/dataproc v1.12.0 h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU=
-cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4=
-cloud.google.com/go/dataqna v0.7.0 h1:yFzi/YU4YAdjyo7pXkBE2FeHbgz5OQQBVDdbErEHmVQ=
-cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/datastore v1.11.0 h1:iF6I/HaLs3Ado8uRKMvZRvF/ZLkWaWE9i8AiHzbC774=
-cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c=
-cloud.google.com/go/datastream v1.7.0 h1:BBCBTnWMDwwEzQQmipUXxATa7Cm7CA/gKjKcR2w35T0=
-cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww=
-cloud.google.com/go/deploy v1.8.0 h1:otshdKEbmsi1ELYeCKNYppwV0UH5xD05drSdBm7ouTk=
-cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ=
-cloud.google.com/go/dialogflow v1.32.0 h1:uVlKKzp6G/VtSW0E7IH1Y5o0H48/UOCmqksG2riYCwQ=
-cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE=
-cloud.google.com/go/dlp v1.9.0 h1:1JoJqezlgu6NWCroBxr4rOZnwNFILXr4cB9dMaSKO4A=
-cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4=
-cloud.google.com/go/documentai v1.18.0 h1:KM3Xh0QQyyEdC8Gs2vhZfU+rt6OCPF0dwVwxKgLmWfI=
-cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs=
-cloud.google.com/go/domains v0.8.0 h1:2ti/o9tlWL4N+wIuWUNH+LbfgpwxPr8J1sv9RHA4bYQ=
-cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE=
-cloud.google.com/go/edgecontainer v1.0.0 h1:O0YVE5v+O0Q/ODXYsQHmHb+sYM8KNjGZw2pjX2Ws41c=
-cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY=
-cloud.google.com/go/errorreporting v0.3.0 h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0=
-cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU=
-cloud.google.com/go/essentialcontacts v1.5.0 h1:gIzEhCoOT7bi+6QZqZIzX1Erj4SswMPIteNvYVlu+pM=
-cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M=
-cloud.google.com/go/eventarc v1.11.0 h1:fsJmNeqvqtk74FsaVDU6cH79lyZNCYP8Rrv7EhaB/PU=
-cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY=
-cloud.google.com/go/filestore v1.6.0 h1:ckTEXN5towyTMu4q0uQ1Mde/JwTHur0gXs8oaIZnKfw=
-cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg=
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
-cloud.google.com/go/firestore v1.9.0 h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA=
-cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE=
-cloud.google.com/go/functions v1.13.0 h1:pPDqtsXG2g9HeOQLoquLbmvmb82Y4Ezdo1GXuotFoWg=
-cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c=
-cloud.google.com/go/gaming v1.9.0 h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc=
-cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0=
-cloud.google.com/go/gkebackup v0.4.0 h1:za3QZvw6ujR0uyqkhomKKKNoXDyqYGPJies3voUK8DA=
-cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg=
-cloud.google.com/go/gkeconnect v0.7.0 h1:gXYKciHS/Lgq0GJ5Kc9SzPA35NGc3yqu6SkjonpEr2Q=
-cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw=
-cloud.google.com/go/gkehub v0.12.0 h1:TqCSPsEBQ6oZSJgEYZ3XT8x2gUadbvfwI32YB0kuHCs=
-cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw=
-cloud.google.com/go/gkemulticloud v0.5.0 h1:8I84Q4vl02rJRsFiinBxl7WCozfdLlUVBQuSrqr9Wtk=
-cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y=
-cloud.google.com/go/gsuiteaddons v1.5.0 h1:1mvhXqJzV0Vg5Fa95QwckljODJJfDFXV4pn+iL50zzA=
-cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo=
-cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=
-cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
-cloud.google.com/go/iap v1.7.1 h1:PxVHFuMxmSZyfntKXHXhd8bo82WJ+LcATenq7HLdVnU=
-cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74=
-cloud.google.com/go/ids v1.3.0 h1:fodnCDtOXuMmS8LTC2y3h8t24U8F3eKWfhi+3LY6Qf0=
-cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4=
-cloud.google.com/go/iot v1.6.0 h1:39W5BFSarRNZfVG0eXI5LYux+OVQT8GkgpHCnrZL2vM=
-cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE=
-cloud.google.com/go/kms v1.10.1 h1:7hm1bRqGCA1GBRQUrp831TwJ9TWhP+tvLuP497CQS2g=
-cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI=
-cloud.google.com/go/language v1.9.0 h1:7Ulo2mDk9huBoBi8zCE3ONOoBrL6UXfAI71CLQ9GEIM=
-cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY=
-cloud.google.com/go/lifesciences v0.8.0 h1:uWrMjWTsGjLZpCTWEAzYvyXj+7fhiZST45u9AgasasI=
-cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo=
-cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I=
-cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M=
-cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=
-cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo=
-cloud.google.com/go/managedidentities v1.5.0 h1:ZRQ4k21/jAhrHBVKl/AY7SjgzeJwG1iZa+mJ82P+VNg=
-cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA=
-cloud.google.com/go/maps v0.7.0 h1:mv9YaczD4oZBZkM5XJl6fXQ984IkJNHPwkc8MUsdkBo=
-cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY=
-cloud.google.com/go/mediatranslation v0.7.0 h1:anPxH+/WWt8Yc3EdoEJhPMBRF7EhIdz426A+tuoA0OU=
-cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I=
-cloud.google.com/go/memcache v1.9.0 h1:8/VEmWCpnETCrBwS3z4MhT+tIdKgR1Z4Tr2tvYH32rg=
-cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM=
-cloud.google.com/go/metastore v1.10.0 h1:QCFhZVe2289KDBQ7WxaHV2rAmPrmRAdLC6gbjUd3HPo=
-cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo=
-cloud.google.com/go/monitoring v1.13.0 h1:2qsrgXGVoRXpP7otZ14eE1I568zAa92sJSDPyOJvwjM=
-cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw=
-cloud.google.com/go/networkconnectivity v1.11.0 h1:ZD6b4Pk1jEtp/cx9nx0ZYcL3BKqDa+KixNDZ6Bjs1B8=
-cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM=
-cloud.google.com/go/networkmanagement v1.6.0 h1:8KWEUNGcpSX9WwZXq7FtciuNGPdPdPN/ruDm769yAEM=
-cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY=
-cloud.google.com/go/networksecurity v0.8.0 h1:sOc42Ig1K2LiKlzG71GUVloeSJ0J3mffEBYmvu+P0eo=
-cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU=
-cloud.google.com/go/notebooks v1.8.0 h1:Kg2K3K7CbSXYJHZ1aGQpf1xi5x2GUvQWf2sFVuiZh8M=
-cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ=
-cloud.google.com/go/optimization v1.3.1 h1:dj8O4VOJRB4CUwZXdmwNViH1OtI0WtWL867/lnYH248=
-cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI=
-cloud.google.com/go/orchestration v1.6.0 h1:Vw+CEXo8M/FZ1rb4EjcLv0gJqqw89b7+g+C/EmniTb8=
-cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ=
-cloud.google.com/go/orgpolicy v1.10.0 h1:XDriMWug7sd0kYT1QKofRpRHzjad0bK8Q8uA9q+XrU4=
-cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc=
-cloud.google.com/go/osconfig v1.11.0 h1:PkSQx4OHit5xz2bNyr11KGcaFccL5oqglFPdTboyqwQ=
-cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw=
-cloud.google.com/go/oslogin v1.9.0 h1:whP7vhpmc+ufZa90eVpkfbgzJRK/Xomjz+XCD4aGwWw=
-cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs=
-cloud.google.com/go/phishingprotection v0.7.0 h1:l6tDkT7qAEV49MNEJkEJTB6vOO/onbSOcNtAT09HPuA=
-cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk=
-cloud.google.com/go/policytroubleshooter v1.6.0 h1:yKAGC4p9O61ttZUswaq9GAn1SZnEzTd0vUYXD7ZBT7Y=
-cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc=
-cloud.google.com/go/privatecatalog v0.8.0 h1:EPEJ1DpEGXLDnmc7mnCAqFmkwUJbIsaLAiLHVOkkwtc=
-cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/pubsub v1.30.0 h1:vCge8m7aUKBJYOgrZp7EsNDf6QMd2CAlXZqWTn3yq6s=
-cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4=
-cloud.google.com/go/pubsublite v1.7.0 h1:cb9fsrtpINtETHiJ3ECeaVzrfIVhcGjhhJEjybHXHao=
-cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM=
-cloud.google.com/go/recaptchaenterprise/v2 v2.7.0 h1:6iOCujSNJ0YS7oNymI64hXsjGq60T4FK1zdLugxbzvU=
-cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c=
-cloud.google.com/go/recommendationengine v0.7.0 h1:VibRFCwWXrFebEWKHfZAt2kta6pS7Tlimsnms0fjv7k=
-cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac=
-cloud.google.com/go/recommender v1.9.0 h1:ZnFRY5R6zOVk2IDS1Jbv5Bw+DExCI5rFumsTnMXiu/A=
-cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ=
-cloud.google.com/go/redis v1.11.0 h1:JoAd3SkeDt3rLFAAxEvw6wV4t+8y4ZzfZcZmddqphQ8=
-cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ=
-cloud.google.com/go/resourcemanager v1.7.0 h1:NRM0p+RJkaQF9Ee9JMnUV9BQ2QBIOq/v8M+Pbv/wmCs=
-cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI=
-cloud.google.com/go/resourcesettings v1.5.0 h1:8Dua37kQt27CCWHm4h/Q1XqCF6ByD7Ouu49xg95qJzI=
-cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA=
-cloud.google.com/go/retail v1.12.0 h1:1Dda2OpFNzIb4qWgFZjYlpP7sxX3aLeypKG6A3H4Yys=
-cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14=
-cloud.google.com/go/run v0.9.0 h1:ydJQo+k+MShYnBfhaRHSZYeD/SQKZzZLAROyfpeD9zw=
-cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg=
-cloud.google.com/go/scheduler v1.9.0 h1:NpQAHtx3sulByTLe2dMwWmah8PWgeoieFPpJpArwFV0=
-cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc=
-cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60=
-cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU=
-cloud.google.com/go/security v1.13.0 h1:PYvDxopRQBfYAXKAuDpFCKBvDOWPWzp9k/H5nB3ud3o=
-cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0=
-cloud.google.com/go/securitycenter v1.19.0 h1:AF3c2s3awNTMoBtMX3oCUoOMmGlYxGOeuXSYHNBkf14=
-cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag=
-cloud.google.com/go/servicecontrol v1.11.1 h1:d0uV7Qegtfaa7Z2ClDzr9HJmnbJW7jn0WhZ7wOX6hLE=
-cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk=
-cloud.google.com/go/servicedirectory v1.9.0 h1:SJwk0XX2e26o25ObYUORXx6torSFiYgsGkWSkZgkoSU=
-cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s=
-cloud.google.com/go/servicemanagement v1.8.0 h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkvi+gzu+NjywY=
-cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4=
-cloud.google.com/go/serviceusage v1.6.0 h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4=
-cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA=
-cloud.google.com/go/shell v1.6.0 h1:wT0Uw7ib7+AgZST9eCDygwTJn4+bHMDtZo5fh7kGWDU=
-cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A=
-cloud.google.com/go/spanner v1.45.0 h1:7VdjZ8zj4sHbDw55atp5dfY6kn1j9sam9DRNpPQhqR4=
-cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M=
-cloud.google.com/go/speech v1.15.0 h1:JEVoWGNnTF128kNty7T4aG4eqv2z86yiMJPT9Zjp+iw=
-cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-cloud.google.com/go/storage v1.14.0 h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
-cloud.google.com/go/storagetransfer v1.8.0 h1:5T+PM+3ECU3EY2y9Brv0Sf3oka8pKmsCfpQ07+91G9o=
-cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw=
-cloud.google.com/go/talent v1.5.0 h1:nI9sVZPjMKiO2q3Uu0KhTDVov3Xrlpt63fghP9XjyEM=
-cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c=
-cloud.google.com/go/texttospeech v1.6.0 h1:H4g1ULStsbVtalbZGktyzXzw6jP26RjVGYx9RaYjBzc=
-cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc=
-cloud.google.com/go/tpu v1.5.0 h1:/34T6CbSi+kTv5E19Q9zbU/ix8IviInZpzwz3rsFE+A=
-cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM=
-cloud.google.com/go/trace v1.9.0 h1:olxC0QHC59zgJVALtgqfD9tGk0lfeCP5/AGXL3Px/no=
-cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk=
-cloud.google.com/go/translate v1.7.0 h1:GvLP4oQ4uPdChBmBaUSa/SaZxCdyWELtlAaKzpHsXdA=
-cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos=
-cloud.google.com/go/video v1.15.0 h1:upIbnGI0ZgACm58HPjAeBMleW3sl5cT84AbYQ8PWOgM=
-cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ=
-cloud.google.com/go/videointelligence v1.10.0 h1:Uh5BdoET8XXqXX2uXIahGb+wTKbLkGH7s4GXR58RrG8=
-cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU=
-cloud.google.com/go/vision/v2 v2.7.0 h1:8C8RXUJoflCI4yVdqhTy9tRyygSHmp60aP363z23HKg=
-cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0=
-cloud.google.com/go/vmmigration v1.6.0 h1:Azs5WKtfOC8pxvkyrDvt7J0/4DYBch0cVbuFfCCFt5k=
-cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY=
-cloud.google.com/go/vmwareengine v0.3.0 h1:b0NBu7S294l0gmtrT0nOJneMYgZapr5x9tVWvgDoVEM=
-cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY=
-cloud.google.com/go/vpcaccess v1.6.0 h1:FOe6CuiQD3BhHJWt7E8QlbBcaIzVRddupwJlp7eqmn4=
-cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes=
-cloud.google.com/go/webrisk v1.8.0 h1:IY+L2+UwxcVm2zayMAtBhZleecdIFLiC+QJMzgb0kT0=
-cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg=
-cloud.google.com/go/websecurityscanner v1.5.0 h1:AHC1xmaNMOZtNqxI9Rmm87IJEyPaRkOxeI0gpAacXGk=
-cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng=
-cloud.google.com/go/workflows v1.10.0 h1:FfGp9w0cYnaKZJhUOMqCOJCYT/WlvYBfTQhFWV3sRKI=
-cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.pubmatic.com/PubMatic/go-common v0.0.0-20240313090142-97ff3d63b7c3 h1:Ea8zwi1eeX4kqvi9RyyXrizIIRcstM0XBwf8U7NHrno=
git.pubmatic.com/PubMatic/go-common v0.0.0-20240313090142-97ff3d63b7c3/go.mod h1:c/I6IcDn4Mtq4mmw8wGJN3v0o10nIMX7VTuQnsalUw0=
git.pubmatic.com/PubMatic/go-netacuity-client v0.0.0-20240104092757-5d6f15e25fe3 h1:zQUpPJOjTBGu2fIydrfRWphH7EWLlBE/Qgn64BSoccI=
git.pubmatic.com/PubMatic/go-netacuity-client v0.0.0-20240104092757-5d6f15e25fe3/go.mod h1:w733mqJnHt0hLR9mIFMzyDR0D94qzc7mFHsuE0tFQho=
-git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240319050712-0b288cbb5a5d h1:BgLUpJQ9Z89eDGz//voK74G/8FgjgVg2PWVbjgCJ4+A=
-git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240319050712-0b288cbb5a5d/go.mod h1:kcoJf7k+xug8X8fLWmsiKhPnYP+k7RZkfUoUo5QF+KA=
-github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240827084017-0e392d3beb8b h1:7AsXylZJDwq514L8KE0Id079VNfUsDEMUIYMlRYH+0Y=
+git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240827084017-0e392d3beb8b/go.mod h1:kcoJf7k+xug8X8fLWmsiKhPnYP+k7RZkfUoUo5QF+KA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
-github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/IABTechLab/adscert v0.34.0 h1:UNM2gMfRPGUbv3KDiLJmy2ajaVCfF3jWqgVKkz8wBu8=
github.com/IABTechLab/adscert v0.34.0/go.mod h1:pCLd3Up1kfTrH6kYFUGGeavxIc1f6Tvvj8yJeFRb7mA=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
-github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/PubMatic-OpenWrap/etree v1.0.2-0.20210129100623-8f30cfecf9f4 h1:EhiijwjoKTx7FVP8p2wwC/z4n5l4c8l2CGmsrFv2uhI=
-github.com/PubMatic-OpenWrap/etree v1.0.2-0.20210129100623-8f30cfecf9f4/go.mod h1:5Y8qgcuDoy3XXG907UXkGnVTwihF16rXyJa4zRT7hOE=
-github.com/PubMatic-OpenWrap/fastxml v0.0.0-20240621094509-2f843d282179 h1:XhtshM/kxpjzShEebApfcvPv1ue3LynvvKNCW2SMONA=
-github.com/PubMatic-OpenWrap/fastxml v0.0.0-20240621094509-2f843d282179/go.mod h1:TGGzSA5ziWpfLsKvqOzgdPGEZ7SJIQjHbcJw6lWoyHU=
+github.com/PubMatic-OpenWrap/etree v1.0.2-0.20240914050009-a916f68552f5 h1:qNRDZVW/TJI0O4hPVdk5YCl+WxD6alYdaCG0im73lNo=
+github.com/PubMatic-OpenWrap/etree v1.0.2-0.20240914050009-a916f68552f5/go.mod h1:5Y8qgcuDoy3XXG907UXkGnVTwihF16rXyJa4zRT7hOE=
+github.com/PubMatic-OpenWrap/fastxml v0.0.0-20240826060652-d9d5d05fdad2 h1:4zaGImZVnKCJudxKfsVNJAqGhCPxbjApAo0QvEThwpw=
+github.com/PubMatic-OpenWrap/fastxml v0.0.0-20240826060652-d9d5d05fdad2/go.mod h1:TGGzSA5ziWpfLsKvqOzgdPGEZ7SJIQjHbcJw6lWoyHU=
github.com/PubMatic-OpenWrap/prebid-openrtb/v20 v20.0.0-20240222072752-2d647d1707ef h1:CXsyYtEgZz/0++fiug6QZXrRYG6BBrl9IGveCxsnhiE=
github.com/PubMatic-OpenWrap/prebid-openrtb/v20 v20.0.0-20240222072752-2d647d1707ef/go.mod h1:hLBrA/APkSrxs5MaW639l+y/EAHivDfRagO2TX/wbSc=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alitto/pond v1.8.3 h1:ydIqygCLVPqIX/USe5EaV/aSRXTRXDEI9JwuDdu+/xs=
github.com/alitto/pond v1.8.3/go.mod h1:CmvIIGd5jKLasGI3D87qDkQxjzChdKMmnXMg3fG6M6Q=
-github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
-github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q=
-github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/aws/aws-sdk-go v1.36.29 h1:lM1G3AF1+7vzFm0n7hfH8r2+750BTo+6Lo6FtPB7kzk=
github.com/aws/aws-sdk-go v1.36.29/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0=
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM=
@@ -355,15 +97,11 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
-github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -371,39 +109,26 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chasex/glog v0.0.0-20160217080310-c62392af379c h1:eXqCBUHfmjbeDqcuvzjsd+bM6A+bnwo5N9FVbV6m5/s=
github.com/chasex/glog v0.0.0-20160217080310-c62392af379c/go.mod h1:omJZNg0Qu76bxJd+ExohVo8uXzNcGOk2bv7vel460xk=
-github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
-github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
-github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
-github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
-github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
-github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
-github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coocood/freecache v1.2.1 h1:/v1CqMq45NFH9mp/Pt142reundeBM0dVUD3osQBeu/U=
github.com/coocood/freecache v1.2.1/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk=
-github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -421,58 +146,38 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
-github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=
-github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
-github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
-github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
-github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
-github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
-github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/log v0.1.0 h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-ldap/ldap v3.0.2+incompatible h1:kD5HQcAzlQ7yrhfn+h+MSABeAy/jAJhvIJ/QDllP44g=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
-github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
-github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
-github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
@@ -480,7 +185,6 @@ github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -512,10 +216,8 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -532,13 +234,10 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@@ -554,111 +253,67 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg=
-github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
-github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
-github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
-github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
-github.com/hashicorp/consul/api v1.18.0 h1:R7PPNzTCeN6VuQNDwwhZWJvzCtGSrNpJqfb22h3yH9g=
-github.com/hashicorp/consul/api v1.18.0/go.mod h1:owRRGJ9M5xReDC5nfT8FTJrNAPbT4NM6p/k+d03q2v4=
-github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
-github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
-github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
-github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
-github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
-github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE=
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
-github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
-github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
-github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
-github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
-github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
-github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
-github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
-github.com/hashicorp/vault/api v1.0.4 h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU=
github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
-github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0sMLy8=
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
-github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
-github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
-github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
-github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
-github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -667,34 +322,24 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
-github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
-github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
-github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
-github.com/lyft/protoc-gen-star v0.5.3 h1:zSGLzsUew8RT+ZKPHc3jnf8XLaVyHzTcAFBzHtCNR20=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
@@ -716,20 +361,15 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
-github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
-github.com/mitchellh/cli v1.1.0 h1:tEElEatulEHDeedTxwckzyYMA5c86fbmNIUL1hBIiTg=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
-github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@@ -747,12 +387,10 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
-github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
@@ -763,27 +401,22 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug=
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
-github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
-github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
-github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/prebid/go-gdpr v1.12.0 h1:OrjQ7Uc+lCRYaOirQ48jjG/PBMvZsKNAaRTgzxN6iZ0=
github.com/prebid/go-gdpr v1.12.0/go.mod h1:mPZAdkRxn+iuSjaUuJAi9+0SppBOdM1PCzv/55UH3pY=
@@ -817,37 +450,26 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
-github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
-github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/rs/vast v0.0.0-20180618195556-06597a11a4c3 h1:PSgAIBGyQP7KW2+EElPsa3qmaya7kCxLSI/GBR176MQ=
github.com/rs/vast v0.0.0-20180618195556-06597a11a4c3/go.mod h1:gq4gkWd7KdigGXkRdN5GEgBQYAWDTmD4/U65MdCgLxQ=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
-github.com/sagikazarmark/crypt v0.9.0 h1:fipzMFW34hFUEc4D7fsLQFtE7yElkpgyS2zruedRdZk=
-github.com/sagikazarmark/crypt v0.9.0/go.mod h1:RnH7sEhxfdnPm1z+XMgSLjWTEIjyK4z2dw6+4vHTMuo=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
-github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
-github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
-github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
@@ -856,7 +478,6 @@ github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcD
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
-github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0=
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@@ -884,7 +505,6 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
-github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/vrischmann/go-metrics-influxdb v0.1.1 h1:xneKFRjsS4BiVYvAKaM/rOlXYd1pGHksnES0ECCJLgo=
github.com/vrischmann/go-metrics-influxdb v0.1.1/go.mod h1:q7YC8bFETCYopXRMtUvQQdLaoVhpsEwvQS2zZEYCqg8=
@@ -904,19 +524,10 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/api/v3 v3.5.6 h1:Cy2qx3npLcYqTKqGJzMypnMv2tiRyifZJ17BlWIWA7A=
-go.etcd.io/etcd/api/v3 v3.5.6/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
-go.etcd.io/etcd/client/pkg/v3 v3.5.6 h1:TXQWYceBKqLp4sa87rcPs11SXxUA/mHwH975v+BDvLU=
-go.etcd.io/etcd/client/pkg/v3 v3.5.6/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
-go.etcd.io/etcd/client/v2 v2.305.6 h1:fIDR0p4KMjw01MJMfUIDWdQbjo06PD6CeYM5z4EHLi0=
-go.etcd.io/etcd/client/v2 v2.305.6/go.mod h1:BHha8XJGe8vCIBfWBpbBLVZ4QjOIlfoouvOwydu63E0=
-go.etcd.io/etcd/client/v3 v3.5.6 h1:coLs69PWCXE9G4FKquzNaSHrRyMCAXwF+IX1tAPVO8E=
-go.etcd.io/etcd/client/v3 v3.5.6/go.mod h1:f6GRinRMCsFVv9Ht42EyY7nfsVGwrNO0WEoS2pRKzQk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -924,19 +535,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
-go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
-go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
-go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
-go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
-go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
-go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -966,7 +568,6 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w=
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -979,10 +580,8 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
@@ -994,8 +593,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1063,8 +660,6 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
-golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1076,8 +671,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1164,8 +757,6 @@ golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
-golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1181,8 +772,6 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
-golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -1239,14 +828,10 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
-golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
-golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -1280,15 +865,12 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
-google.golang.org/api v0.107.0 h1:I2SlFjD8ZWabaIFOfeEDg3pf0BHJDh6iYQ1ic3Yu/UU=
-google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1391,7 +973,6 @@ google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
-google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -1408,31 +989,22 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
-gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
-gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=
-gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
-gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
-gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1452,11 +1024,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/hooks/hookexecution/executor.go b/hooks/hookexecution/executor.go
index 0ba466acc8d..2249fd29d42 100644
--- a/hooks/hookexecution/executor.go
+++ b/hooks/hookexecution/executor.go
@@ -260,10 +260,10 @@ func (e *hookExecutor) ExecuteRawBidderResponseStage(response *adapters.BidderRe
stageName := hooks.StageRawBidderResponse.String()
executionCtx := e.newContext(stageName)
- payload := hookstage.RawBidderResponsePayload{Bids: response.Bids, Bidder: bidder}
+ payload := hookstage.RawBidderResponsePayload{BidderResponse: response, Bidder: bidder}
outcome, payload, contexts, reject := executeStage(executionCtx, plan, payload, handler, e.metricEngine)
- response.Bids = payload.Bids
+ response = payload.BidderResponse
outcome.Entity = entity(bidder)
outcome.Stage = stageName
diff --git a/hooks/hookexecution/mocks_test.go b/hooks/hookexecution/mocks_test.go
index a52fdbe12a7..968b1a7540b 100644
--- a/hooks/hookexecution/mocks_test.go
+++ b/hooks/hookexecution/mocks_test.go
@@ -154,7 +154,7 @@ func (e mockTimeoutHook) HandleRawBidderResponseHook(_ context.Context, _ hookst
time.Sleep(20 * time.Millisecond)
c := hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
c.AddMutation(func(payload hookstage.RawBidderResponsePayload) (hookstage.RawBidderResponsePayload, error) {
- payload.Bids[0].BidMeta = &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "new-code"}
+ payload.BidderResponse.Bids[0].BidMeta = &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "new-code"}
return payload, nil
}, hookstage.MutationUpdate, "bidderResponse", "bidMeta.AdapterCode")
@@ -371,7 +371,7 @@ func (e mockUpdateBidderResponseHook) HandleRawBidderResponseHook(_ context.Cont
c := hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
c.AddMutation(
func(payload hookstage.RawBidderResponsePayload) (hookstage.RawBidderResponsePayload, error) {
- payload.Bids[0].DealPriority = 10
+ payload.BidderResponse.Bids[0].DealPriority = 10
return payload, nil
}, hookstage.MutationUpdate, "bidderResponse", "bid.deal-priority",
)
diff --git a/hooks/hookstage/rawbidderresponse.go b/hooks/hookstage/rawbidderresponse.go
index 7d08a7d2e02..1f6aaaa64ef 100644
--- a/hooks/hookstage/rawbidderresponse.go
+++ b/hooks/hookstage/rawbidderresponse.go
@@ -25,6 +25,6 @@ type RawBidderResponse interface {
// objects representing bids returned by a particular bidder.
// Hooks are allowed to modify bids using mutations.
type RawBidderResponsePayload struct {
- Bids []*adapters.TypedBid
- Bidder string
+ BidderResponse *adapters.BidderResponse
+ Bidder string
}
diff --git a/hooks/hookstage/rawbidderresponse_mutations.go b/hooks/hookstage/rawbidderresponse_mutations.go
index efab874fa15..c5022c31218 100644
--- a/hooks/hookstage/rawbidderresponse_mutations.go
+++ b/hooks/hookstage/rawbidderresponse_mutations.go
@@ -33,7 +33,7 @@ func (c ChangeSetBids[T]) Update(bids []*adapters.TypedBid) {
c.changeSetRawBidderResponse.changeSet.AddMutation(func(p T) (T, error) {
bidderPayload, err := c.changeSetRawBidderResponse.castPayload(p)
if err == nil {
- bidderPayload.Bids = bids
+ bidderPayload.BidderResponse.Bids = bids
}
if payload, ok := any(bidderPayload).(T); ok {
return payload, nil
diff --git a/metrics/config/metrics_ow.go b/metrics/config/metrics_ow.go
index 9e793527d2c..149e920f5a7 100644
--- a/metrics/config/metrics_ow.go
+++ b/metrics/config/metrics_ow.go
@@ -26,15 +26,15 @@ func NewMetricsRegistry() MetricsRegistry {
}
// RecordXMLParserResponseTime records execution time for multiple parsers
-func (me *MultiMetricsEngine) RecordXMLParserResponseTime(parser string, method string, bidder string, respTime time.Duration) {
+func (me *MultiMetricsEngine) RecordXMLParserResponseTime(parser string, method string, respTime time.Duration) {
for _, thisME := range *me {
- thisME.RecordXMLParserResponseTime(parser, method, bidder, respTime)
+ thisME.RecordXMLParserResponseTime(parser, method, respTime)
}
}
-func (me *MultiMetricsEngine) RecordXMLParserResponseMismatch(method string, bidder string, isMismatch bool) {
+func (me *MultiMetricsEngine) RecordXMLParserResponseMismatch(method string, isMismatch bool) {
for _, thisME := range *me {
- thisME.RecordXMLParserResponseMismatch(method, bidder, isMismatch)
+ thisME.RecordXMLParserResponseMismatch(method, isMismatch)
}
}
@@ -90,14 +90,6 @@ func (me *MultiMetricsEngine) RecordBadRequest(endpoint string, pubId string, nb
}
}
-// RecordXMLParserResponseTime records execution time for multiple parsers
-func (me *NilMetricsEngine) RecordXMLParserResponseTime(parser string, method string, bidder string, respTime time.Duration) {
-}
-
-// RecordXMLParserResponseMismatch as a noop
-func (me *NilMetricsEngine) RecordXMLParserResponseMismatch(method string, bidder string, isMismatch bool) {
-}
-
// RecordVASTTagType as a noop
func (me *NilMetricsEngine) RecordVASTTagType(biddder, vastTag string) {
}
@@ -129,3 +121,11 @@ func (me *NilMetricsEngine) RecordPanic(hostname, method string) {
// RecordBadRequest as a noop
func (me *NilMetricsEngine) RecordBadRequest(endpoint string, pubId string, nbr *openrtb3.NoBidReason) {
}
+
+// RecordXMLParserResponseTime records execution time for multiple parsers
+func (me *NilMetricsEngine) RecordXMLParserResponseTime(parser string, method string, respTime time.Duration) {
+}
+
+// RecordXMLParserResponseMismatch as a noop
+func (me *NilMetricsEngine) RecordXMLParserResponseMismatch(method string, isMismatch bool) {
+}
diff --git a/metrics/go_metrics_ow.go b/metrics/go_metrics_ow.go
index 8cf915139f1..06eca3819ad 100644
--- a/metrics/go_metrics_ow.go
+++ b/metrics/go_metrics_ow.go
@@ -55,9 +55,9 @@ func (me *Metrics) RecordBadRequest(endpoint string, pubId string, nbr *openrtb3
}
// RecordXMLParserResponseTime records execution time for multiple parsers
-func (me *Metrics) RecordXMLParserResponseTime(parser string, method string, bidder string, respTime time.Duration) {
+func (me *Metrics) RecordXMLParserResponseTime(parser string, method string, respTime time.Duration) {
}
// RecordXMLParserResponseMismatch as a noop
-func (me *Metrics) RecordXMLParserResponseMismatch(method string, bidder string, isMismatch bool) {
+func (me *Metrics) RecordXMLParserResponseMismatch(method string, isMismatch bool) {
}
diff --git a/metrics/metrics_mock_ow.go b/metrics/metrics_mock_ow.go
index dfe5bb97bda..9bbb0d93cb6 100644
--- a/metrics/metrics_mock_ow.go
+++ b/metrics/metrics_mock_ow.go
@@ -61,11 +61,11 @@ func (me *MetricsEngineMock) RecordBadRequest(endpoint string, pubId string, nbr
}
// RecordXMLParserResponseTime records execution time for multiple parsers
-func (me *MetricsEngineMock) RecordXMLParserResponseTime(parser string, method string, bidder string, respTime time.Duration) {
- me.Called(parser, method, bidder, respTime)
+func (me *MetricsEngineMock) RecordXMLParserResponseTime(parser string, method string, respTime time.Duration) {
+ me.Called(parser, method, respTime)
}
// RecordXMLParserResponseMismatch mock
-func (me *MetricsEngineMock) RecordXMLParserResponseMismatch(method string, bidder string, isMismatch bool) {
- me.Called(method, bidder, isMismatch)
+func (me *MetricsEngineMock) RecordXMLParserResponseMismatch(method string, isMismatch bool) {
+ me.Called(method, isMismatch)
}
diff --git a/metrics/metrics_ow.go b/metrics/metrics_ow.go
index 6c36854ac9c..33d910a0cff 100644
--- a/metrics/metrics_ow.go
+++ b/metrics/metrics_ow.go
@@ -22,7 +22,7 @@ type OWMetricsEngine interface {
RecordPanic(hostname, method string)
RecordBadRequest(endpoint string, pubId string, nbr *openrtb3.NoBidReason)
//RecordXMLParserResponseTime records execution time for multiple parsers
- RecordXMLParserResponseTime(parser string, method string, bidder string, respTime time.Duration)
+ RecordXMLParserResponseTime(parser string, method string, respTime time.Duration)
//RecordXMLParserResponseMismatch records number of response mismatch
- RecordXMLParserResponseMismatch(method string, bidder string, isMismatch bool)
+ RecordXMLParserResponseMismatch(method string, isMismatch bool)
}
diff --git a/metrics/prometheus/prometheus_ow.go b/metrics/prometheus/prometheus_ow.go
index a74dbe198cb..66ae5669ee4 100644
--- a/metrics/prometheus/prometheus_ow.go
+++ b/metrics/prometheus/prometheus_ow.go
@@ -220,24 +220,22 @@ func (m *Metrics) RecordHttpCounter() {
}
// RecordXMLParserResponseTime records xml parser response time
-func (m *OWMetrics) RecordXMLParserResponseTime(parser string, method string, bidder string, respTime time.Duration) {
+func (m *OWMetrics) RecordXMLParserResponseTime(parser string, method string, respTime time.Duration) {
m.xmlParserResponseTime.With(prometheus.Labels{
xmlParserLabel: parser,
methodLabel: method,
- adapterLabel: bidder,
- }).Observe(respTime.Seconds())
+ }).Observe(float64(respTime.Microseconds()))
}
// RecordVastVersion record the count of vast version labelled by bidder and vast version
-func (m *OWMetrics) RecordXMLParserResponseMismatch(method, bidder string, isMismatch bool) {
+func (m *OWMetrics) RecordXMLParserResponseMismatch(method string, isMismatch bool) {
status := requestSuccessful
if isMismatch {
status = requestFailed
}
m.xmlParserMismatch.With(prometheus.Labels{
- methodLabel: method,
- adapterLabel: bidder,
- statusLabel: status,
+ methodLabel: method,
+ statusLabel: status,
}).Inc()
}
@@ -327,12 +325,12 @@ func (m *OWMetrics) init(cfg config.PrometheusMetrics, reg *prometheus.Registry)
//XML Parser Response Time
m.xmlParserResponseTime = newHistogramVec(cfg, reg,
"xml_parser_response_time",
- "Time taken by xml parser", []string{xmlParserLabel, methodLabel, adapterLabel},
- //0.01ms, 0.5ms, 1ms, 5ms, 10ms
- []float64{0.0001, 0.0005, 0.001, 0.005, 0.01})
+ "Time taken by xml parser", []string{xmlParserLabel, methodLabel},
+ //50µs, 100µs, 250µs, 500µs, 1ms, 5ms, 10ms
+ []float64{50, 100, 250, 500, 1000, 5000, 10000})
m.xmlParserMismatch = newCounter(cfg, reg,
"etree_fastxml_resp_mismatch",
"Count of no of bids for which fast xml and etree response mismatch",
- []string{methodLabel, adapterLabel, statusLabel})
+ []string{methodLabel, statusLabel})
}
diff --git a/metrics/prometheus/prometheus_ow_test.go b/metrics/prometheus/prometheus_ow_test.go
index 795dde9770a..f9a218f431a 100644
--- a/metrics/prometheus/prometheus_ow_test.go
+++ b/metrics/prometheus/prometheus_ow_test.go
@@ -215,8 +215,8 @@ func TestRecordFloorStatus(t *testing.T) {
func TestRecordXMLParserResponseMismatch(t *testing.T) {
type args struct {
- method, bidder string
- isMismatch bool
+ method string
+ isMismatch bool
}
type want struct {
expCount int
@@ -231,7 +231,6 @@ func TestRecordXMLParserResponseMismatch(t *testing.T) {
name: "mismatch found",
args: args{
method: "xml",
- bidder: "bidder",
isMismatch: true,
},
want: want{
@@ -243,7 +242,6 @@ func TestRecordXMLParserResponseMismatch(t *testing.T) {
name: "mismatch not found",
args: args{
method: "xml",
- bidder: "bidder",
isMismatch: false,
},
want: want{
@@ -256,16 +254,15 @@ func TestRecordXMLParserResponseMismatch(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
pm := createMetricsForTesting()
- pm.RecordXMLParserResponseMismatch(tt.args.method, tt.args.bidder, tt.args.isMismatch)
+ pm.RecordXMLParserResponseMismatch(tt.args.method, tt.args.isMismatch)
assertCounterVecValue(t,
"",
"record dynamic fetch failure",
pm.xmlParserMismatch,
float64(tt.want.expCount),
prometheus.Labels{
- methodLabel: tt.args.method,
- adapterLabel: tt.args.bidder,
- statusLabel: tt.want.status,
+ methodLabel: tt.args.method,
+ statusLabel: tt.want.status,
})
})
}
diff --git a/modules/prebid/ortb2blocking/hook_raw_bidder_response.go b/modules/prebid/ortb2blocking/hook_raw_bidder_response.go
index 215de260b09..e1a4d9c60dd 100644
--- a/modules/prebid/ortb2blocking/hook_raw_bidder_response.go
+++ b/modules/prebid/ortb2blocking/hook_raw_bidder_response.go
@@ -34,7 +34,7 @@ func handleRawBidderResponseHook(
// allowedBids will store all bids that have passed the attribute check
allowedBids := make([]*adapters.TypedBid, 0)
- for _, bid := range payload.Bids {
+ for _, bid := range payload.BidderResponse.Bids {
failedChecksData := make(map[string]interface{})
bidMediaTypes := mediaTypesFromBid(bid)
@@ -77,7 +77,7 @@ func handleRawBidderResponseHook(
}
changeSet := hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
- if len(payload.Bids) != len(allowedBids) {
+ if len(payload.BidderResponse.Bids) != len(allowedBids) {
changeSet.RawBidderResponse().Bids().Update(allowedBids)
result.ChangeSet = changeSet
}
diff --git a/modules/prebid/ortb2blocking/module_test.go b/modules/prebid/ortb2blocking/module_test.go
index 8178cba15fe..053fc9bfc75 100644
--- a/modules/prebid/ortb2blocking/module_test.go
+++ b/modules/prebid/ortb2blocking/module_test.go
@@ -614,9 +614,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}{
{
description: "Payload not changed when empty account config and empty module contexts are provided. Analytic tags have successful records",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ADomain: []string{"foo"}, ImpID: impID1},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ADomain: []string{"foo"}, ImpID: impID1},
+ },
},
}},
expectedBids: []*adapters.TypedBid{
@@ -643,9 +645,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Catch error if wrong data has been passed from previous hook. Payload not changed",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ADomain: []string{"foo"}, ImpID: impID1},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ADomain: []string{"foo"}, ImpID: impID1},
+ },
},
}},
expectedBids: []*adapters.TypedBid{
@@ -658,12 +662,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by badv attribute check. Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"badv":{"enforce_blocks": true}}}`),
@@ -701,12 +707,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid not blocked because blocking conditions for current bidder do not exist. Payload not updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"badv":{"enforce_blocks": true}}}`),
@@ -742,12 +750,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid not blocked because enforce blocking is disabled by account config. Payload not updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"badv":{"enforce_blocks": false}}}`),
@@ -783,12 +793,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid not blocked because enforce blocking overridden for given bidder. Payload not updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"badv":{"enforce_blocks": true, "action_overrides": {"enforce_blocks": [{"conditions": {"bidders": ["appnexus"]}, "override": false}]}}}}`),
@@ -824,12 +836,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by badv attribute check (block unknown attributes). Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"badv":{"enforce_blocks": true, "block_unknown_adomain": true}}}`),
@@ -867,12 +881,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid not blocked because block unknown overridden for given bidder. Payload not updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"badv":{"enforce_blocks": true, "block_unknown_adomain": true, "action_overrides": {"block_unknown_adomain": [{"conditions": {"bidders": ["appnexus"]}, "override": false}]}}}}`),
@@ -908,12 +924,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid not blocked due to deal exception. Payload not updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1, DealID: "acceptDealID"},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, ImpID: impID1, DealID: "acceptDealID"},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", ADomain: []string{"good_domain"}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"badv":{"enforce_blocks": true, "action_overrides": {"allowed_adomain_for_deals": [{"conditions": {"deal_ids": ["acceptDealID"]}, "override": ["forbidden_domain"]}]}}}}`),
@@ -949,9 +967,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if there is an issue processing enforce blocks overrides for badv attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"badv": {"enforce_blocks": true, "action_overrides": {"enforce_blocks": [{"conditions": {}}]}}}}`),
@@ -974,9 +994,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if there is an issue processing block unknown domains overrides for badv attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"badv": {"enforce_blocks": true, "action_overrides": {"block_unknown_adomain": [{"conditions": {}}]}}}}`),
@@ -999,9 +1021,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if deal_ids not defined in config override conditions for badv attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, DealID: "acceptDealID"},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", ADomain: []string{"forbidden_domain"}, DealID: "acceptDealID"},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"badv": {"enforce_blocks": true, "action_overrides": {"allowed_adomain_for_deals": [{"conditions": {}}]}}}}`),
@@ -1024,12 +1048,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by bcat attribute check. Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", Cat: []string{"moto"}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", Cat: []string{"moto"}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"bcat":{"enforce_blocks": true}}}`),
@@ -1067,9 +1093,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if there is an issue processing enforce blocks overrides for bcat attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"bcat": {"enforce_blocks": true, "action_overrides": {"enforce_blocks": [{"conditions": {}}]}}}}`),
@@ -1092,9 +1120,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if there is an issue processing block unknown domains overrides for bcat attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"bcat": {"enforce_blocks": true, "action_overrides": {"block_unknown_adv_cat": [{"conditions": {}}]}}}}`),
@@ -1117,9 +1147,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if deal_ids not defined in config override conditions for bcat attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1, DealID: "acceptDealID"},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Cat: []string{"fishing"}, ImpID: impID1, DealID: "acceptDealID"},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"bcat": {"enforce_blocks": true, "action_overrides": {"allowed_adv_cat_for_deals": [{"conditions": {}}]}}}}`),
@@ -1142,12 +1174,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by cattax attribute check. Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", CatTax: 1, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", CatTax: 2, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", CatTax: 1, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", CatTax: 2, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"bcat":{"enforce_blocks": true}}}`),
@@ -1185,12 +1219,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by cattax attribute check (the default value used if no blocking attribute passed). Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", CatTax: 1, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", CatTax: 2, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", CatTax: 1, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", CatTax: 2, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"bcat":{"enforce_blocks": true}}}`),
@@ -1227,12 +1263,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by bapp attribute check. Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Bundle: "forbidden_bundle", ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", Bundle: "allowed_bundle", ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Bundle: "forbidden_bundle", ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", Bundle: "allowed_bundle", ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"bapp":{"enforce_blocks": true}}}`),
@@ -1270,9 +1308,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if there is an issue processing enforce blocks overrides for bapp attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Bundle: "forbidden_bundle", ImpID: impID1},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Bundle: "forbidden_bundle", ImpID: impID1},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"bapp": {"enforce_blocks": true, "action_overrides": {"enforce_blocks": [{"conditions": {}}]}}}}`),
@@ -1295,9 +1335,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if deal_ids not defined in config override conditions for bapp attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Bundle: "forbidden_bundle", ImpID: impID1, DealID: "acceptDealID"},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Bundle: "forbidden_bundle", ImpID: impID1, DealID: "acceptDealID"},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"bapp": {"enforce_blocks": true, "action_overrides": {"allowed_app_for_deals": [{"conditions": {}}]}}}}`),
@@ -1320,12 +1362,14 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by battr attribute check. Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Attr: []adcom1.CreativeAttribute{1}, ImpID: impID1},
- },
- {
- Bid: &openrtb2.Bid{ID: "2", Attr: []adcom1.CreativeAttribute{2}, ImpID: impID2},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Attr: []adcom1.CreativeAttribute{1}, ImpID: impID1},
+ },
+ {
+ Bid: &openrtb2.Bid{ID: "2", Attr: []adcom1.CreativeAttribute{2}, ImpID: impID2},
+ },
},
}},
config: json.RawMessage(`{"attributes":{"battr":{"enforce_blocks": true}}}`),
@@ -1363,9 +1407,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if there is an issue processing enforce blocks overrides for battr attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Attr: []adcom1.CreativeAttribute{1}, ImpID: impID1},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Attr: []adcom1.CreativeAttribute{1}, ImpID: impID1},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"battr": {"enforce_blocks": true, "action_overrides": {"enforce_blocks": [{"conditions": {}}]}}}}`),
@@ -1388,9 +1434,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Expect error if deal_ids not defined in config override conditions for battr attribute. Analytics should have error status tag",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{ID: "1", Attr: []adcom1.CreativeAttribute{1}, ImpID: impID1, DealID: "acceptDealID"},
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{ID: "1", Attr: []adcom1.CreativeAttribute{1}, ImpID: impID1, DealID: "acceptDealID"},
+ },
},
}},
config: json.RawMessage(`{"attributes": {"battr": {"enforce_blocks": true, "action_overrides": {"allowed_banner_attr_for_deals": [{"conditions": {}}]}}}}`),
@@ -1413,27 +1461,29 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
{
description: "Bid blocked by multiple attribute check. Payload updated. Analytic tags successfully collected",
- payload: hookstage.RawBidderResponsePayload{Bidder: bidder, Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{
- ID: "1",
- ADomain: []string{"forbidden_domain"},
- Cat: []string{"fishing"},
- CatTax: 1,
- Bundle: "forbidden_bundle",
- Attr: []adcom1.CreativeAttribute{1},
- ImpID: impID1,
+ payload: hookstage.RawBidderResponsePayload{Bidder: bidder, BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{
+ ID: "1",
+ ADomain: []string{"forbidden_domain"},
+ Cat: []string{"fishing"},
+ CatTax: 1,
+ Bundle: "forbidden_bundle",
+ Attr: []adcom1.CreativeAttribute{1},
+ ImpID: impID1,
+ },
},
- },
- {
- Bid: &openrtb2.Bid{
- ID: "2",
- ADomain: []string{"allowed_domain"},
- Cat: []string{"moto"},
- CatTax: 2,
- Bundle: "allowed_bundle",
- Attr: []adcom1.CreativeAttribute{2},
- ImpID: impID2,
+ {
+ Bid: &openrtb2.Bid{
+ ID: "2",
+ ADomain: []string{"allowed_domain"},
+ Cat: []string{"moto"},
+ CatTax: 2,
+ Bundle: "allowed_bundle",
+ Attr: []adcom1.CreativeAttribute{2},
+ ImpID: impID2,
+ },
},
},
}},
@@ -1514,7 +1564,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
assert.NoError(t, err)
test.payload = newPayload
}
- assert.Equal(t, test.expectedBids, test.payload.Bids, "Invalid Bids returned after executing RawBidderResponse hook.")
+ assert.Equal(t, test.expectedBids, test.payload.BidderResponse.Bids, "Invalid Bids returned after executing RawBidderResponse hook.")
// reset ChangeSet not to break hookResult assertion, we validated ChangeSet separately
hookResult.ChangeSet = hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
diff --git a/modules/pubmatic/openwrap/adpod/adpod.go b/modules/pubmatic/openwrap/adpod/adpod.go
index 91e1ff290eb..f6f6cdeec6d 100644
--- a/modules/pubmatic/openwrap/adpod/adpod.go
+++ b/modules/pubmatic/openwrap/adpod/adpod.go
@@ -3,13 +3,16 @@ package adpod
import (
"encoding/json"
"errors"
+ "fmt"
"github.com/buger/jsonparser"
"github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/cache"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adpodconfig"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
- "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/utils"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/ortb"
"github.com/prebid/prebid-server/v2/util/ptrutil"
)
@@ -32,30 +35,19 @@ func setDefaultValues(adpodConfig *models.AdPod) {
}
-func GetAdpodConfigs(impVideo *openrtb2.Video, requestExtConfigs *models.ExtRequestAdPod, adUnitConfig *adunitconfig.AdConfig, partnerConfigMap map[int]map[string]string, pubId string, me metrics.MetricsEngine) (*models.AdPod, error) {
- adpodConfigs, ok, err := resolveAdpodConfigs(impVideo, requestExtConfigs, adUnitConfig, pubId, me)
+func GetV25AdpodConfigs(impVideo *openrtb2.Video, requestExtConfigs *models.ExtRequestAdPod, adUnitConfig *adunitconfig.AdConfig, partnerConfigMap map[int]map[string]string, pubId string, me metrics.MetricsEngine) (*models.AdPod, error) {
+ adpodConfigs, ok, err := resolveV25AdpodConfigs(impVideo, requestExtConfigs, adUnitConfig, pubId, me)
if !ok || err != nil {
return nil, err
}
- videoAdDuration := models.GetVersionLevelPropertyFromPartnerConfig(partnerConfigMap, models.VideoAdDurationKey)
- if len(videoAdDuration) > 0 {
- adpodConfigs.VideoAdDuration = utils.GetIntArrayFromString(videoAdDuration, models.ArraySeparator)
- }
-
- videoAdDurationMatchingPolicy := models.GetVersionLevelPropertyFromPartnerConfig(partnerConfigMap, models.VideoAdDurationMatchingKey)
- if len(videoAdDurationMatchingPolicy) > 0 {
- adpodConfigs.VideoAdDurationMatching = videoAdDurationMatchingPolicy
- }
-
// Set default value if adpod object does not exists
setDefaultValues(adpodConfigs)
return adpodConfigs, nil
-
}
-func resolveAdpodConfigs(impVideo *openrtb2.Video, requestExtConfigs *models.ExtRequestAdPod, adUnitConfig *adunitconfig.AdConfig, pubId string, me metrics.MetricsEngine) (*models.AdPod, bool, error) {
+func resolveV25AdpodConfigs(impVideo *openrtb2.Video, requestExtConfigs *models.ExtRequestAdPod, adUnitConfig *adunitconfig.AdConfig, pubId string, me metrics.MetricsEngine) (*models.AdPod, bool, error) {
var adpodConfig *models.AdPod
// Check in impression extension
@@ -79,10 +71,9 @@ func resolveAdpodConfigs(impVideo *openrtb2.Video, requestExtConfigs *models.Ext
}
return nil, false, nil
-
}
-func Validate(config *models.AdPod) error {
+func ValidateV25Configs(rCtx models.RequestCtx, config *models.AdPod) error {
if config == nil {
return nil
}
@@ -119,9 +110,9 @@ func Validate(config *models.AdPod) error {
return errors.New("adpod.adminduration must be less than adpod.admaxduration")
}
- if len(config.VideoAdDuration) > 0 {
+ if rCtx.AdpodProfileConfig != nil && len(rCtx.AdpodProfileConfig.AdserverCreativeDurations) > 0 {
validDurations := false
- for _, videoDuration := range config.VideoAdDuration {
+ for _, videoDuration := range rCtx.AdpodProfileConfig.AdserverCreativeDurations {
if videoDuration >= config.MinDuration && videoDuration <= config.MaxDuration {
validDurations = true
break
@@ -135,3 +126,170 @@ func Validate(config *models.AdPod) error {
return nil
}
+
+func GetAdpodConfigs(rctx models.RequestCtx, cache cache.Cache, adunit *adunitconfig.AdConfig) ([]models.PodConfig, error) {
+ // Fetch Adpod Configs from UI
+ pods, err := cache.GetAdpodConfig(rctx.PubID, rctx.ProfileID, rctx.DisplayVersionID)
+ if err != nil {
+ return nil, err
+ }
+
+ var uiAdpodConfigs []models.PodConfig
+ if pods != nil {
+ uiAdpodConfigs = append(uiAdpodConfigs, decouplePodConfigs(pods)...)
+ }
+
+ // Vmap adpod configs
+ var adrules []models.PodConfig
+ if adunit != nil && adunit.Adrule != nil {
+ for _, rule := range adunit.Adrule {
+ if rule != nil {
+ adrules = append(adrules, models.PodConfig{
+ PodID: rule.PodID,
+ PodDur: rule.PodDur,
+ MaxSeq: rule.MaxSeq,
+ MinDuration: rule.MinDuration,
+ MaxDuration: rule.MaxDuration,
+ RqdDurs: rule.RqdDurs,
+ })
+ }
+ }
+ }
+
+ var podConfigs []models.PodConfig
+ if len(uiAdpodConfigs) > 0 && adunit.Video != nil && adunit.Video.UsePodConfig != nil && *adunit.Video.UsePodConfig {
+ podConfigs = append(podConfigs, uiAdpodConfigs...)
+ } else if len(adrules) > 0 && rctx.AdruleFlag {
+ podConfigs = append(podConfigs, adrules...)
+ }
+
+ return podConfigs, nil
+}
+
+func decouplePodConfigs(pods *adpodconfig.AdpodConfig) []models.PodConfig {
+ if pods == nil {
+ return nil
+ }
+
+ var podConfigs []models.PodConfig
+ // Add all dynamic adpods
+ for i, dynamic := range pods.Dynamic {
+ podConfigs = append(podConfigs, models.PodConfig{
+ PodID: fmt.Sprintf("dynamic-%d", i+1),
+ PodDur: dynamic.PodDur,
+ MaxSeq: dynamic.MaxSeq,
+ MinDuration: dynamic.MinDuration,
+ MaxDuration: dynamic.MaxDuration,
+ RqdDurs: dynamic.RqdDurs,
+ })
+ }
+
+ // Add all structured adpods
+ for i, structured := range pods.Structured {
+ podConfigs = append(podConfigs, models.PodConfig{
+ PodID: fmt.Sprintf("structured-%d", i+1),
+ MinDuration: structured.MinDuration,
+ MaxDuration: structured.MaxDuration,
+ RqdDurs: structured.RqdDurs,
+ })
+ }
+
+ // Add all hybrid adpods
+ for i, hybrid := range pods.Hybrid {
+ pod := models.PodConfig{
+ PodID: fmt.Sprintf("hybrid-%d", i+1),
+ MinDuration: hybrid.MinDuration,
+ MaxDuration: hybrid.MaxDuration,
+ RqdDurs: hybrid.RqdDurs,
+ }
+
+ if hybrid.PodDur != nil {
+ pod.PodDur = *hybrid.PodDur
+ }
+
+ if hybrid.MaxSeq != nil {
+ pod.MaxSeq = *hybrid.MaxSeq
+ }
+
+ podConfigs = append(podConfigs, pod)
+ }
+
+ return podConfigs
+}
+
+func ValidateAdpodConfigs(configs []models.PodConfig) error {
+ for _, config := range configs {
+ if config.RqdDurs == nil && config.MinDuration == 0 && config.MaxDuration == 0 {
+ return errors.New("slot duration is missing in adpod config")
+ }
+
+ if config.MinDuration > config.MaxDuration {
+ return errors.New("min duration should be less than max duration")
+ }
+
+ if config.RqdDurs == nil && config.MaxDuration <= 0 {
+ return errors.New("max duration should be greater than 0")
+ }
+
+ if config.PodDur < 0 {
+ return errors.New("pod duration should be positive number")
+ }
+
+ if config.MaxSeq < 0 {
+ return errors.New("max sequence should be positive number")
+ }
+ }
+
+ return nil
+}
+
+func ApplyAdpodConfigs(rctx models.RequestCtx, bidRequest *openrtb2.BidRequest) *openrtb2.BidRequest {
+ if len(rctx.ImpAdPodConfig) == 0 {
+ return bidRequest
+ }
+
+ imps := make([]openrtb2.Imp, 0)
+ for _, imp := range bidRequest.Imp {
+ if imp.Video == nil {
+ imps = append(imps, imp)
+ continue
+ }
+
+ // Give priority to adpod config in request
+ if len(imp.Video.PodID) > 0 {
+ imps = append(imps, imp)
+ continue
+ }
+
+ impPodConfig, ok := rctx.ImpAdPodConfig[imp.ID]
+ if !ok || len(impPodConfig) == 0 {
+ imps = append(imps, imp)
+ continue
+ }
+
+ // Apply adpod config
+ for i, podConfig := range impPodConfig {
+ impCopy := ortb.DeepCloneImpression(&imp)
+ impCopy.ID = fmt.Sprintf("%s-%s-%d", impCopy.ID, podConfig.PodID, i)
+ impCopy.Video.PodID = podConfig.PodID
+ impCopy.Video.MaxSeq = podConfig.MaxSeq
+ impCopy.Video.PodDur = podConfig.PodDur
+ impCopy.Video.MinDuration = podConfig.MinDuration
+ impCopy.Video.MaxDuration = podConfig.MaxDuration
+ impCopy.Video.RqdDurs = podConfig.RqdDurs
+
+ impCtx := rctx.ImpBidCtx[imp.ID]
+ impCtxCopy := impCtx.DeepCopy()
+ impCtxCopy.Video = impCopy.Video
+
+ rctx.ImpBidCtx[impCopy.ID] = impCtxCopy
+ imps = append(imps, *impCopy)
+ }
+
+ // Delete original imp from context
+ delete(rctx.ImpBidCtx, imp.ID)
+ }
+
+ bidRequest.Imp = imps
+ return bidRequest
+}
diff --git a/modules/pubmatic/openwrap/adpod/auction/auction.go b/modules/pubmatic/openwrap/adpod/auction/auction.go
index 4ededc7e7fc..be0b81d5d15 100644
--- a/modules/pubmatic/openwrap/adpod/auction/auction.go
+++ b/modules/pubmatic/openwrap/adpod/auction/auction.go
@@ -39,7 +39,7 @@ func FormAdpodBidsAndPerformExclusion(response *openrtb2.BidResponse, rctx model
return nil, errs
}
- impAdpodBidsMap, _ := generateAdpodBids(response.SeatBid, rctx.ImpBidCtx)
+ impAdpodBidsMap, _ := generateAdpodBids(response.SeatBid, rctx.ImpBidCtx, rctx.AdpodProfileConfig)
adpodBids, errs := doAdPodExclusions(impAdpodBidsMap, rctx.ImpBidCtx)
if len(errs) > 0 {
return nil, errs
@@ -77,7 +77,7 @@ func addTargetingKey(bid *openrtb2.Bid, key openrtb_ext.TargetingKey, value stri
return err
}
-func generateAdpodBids(seatBids []openrtb2.SeatBid, impCtx map[string]models.ImpCtx) (map[string]*AdPodBid, []openrtb2.SeatBid) {
+func generateAdpodBids(seatBids []openrtb2.SeatBid, impCtx map[string]models.ImpCtx, adpodProfileCfg *models.AdpodProfileConfig) (map[string]*AdPodBid, []openrtb2.SeatBid) {
impAdpodBidsMap := make(map[string]*AdPodBid)
videoSeatBids := make([]openrtb2.SeatBid, 0)
@@ -133,12 +133,13 @@ func generateAdpodBids(seatBids []openrtb2.SeatBid, impCtx map[string]models.Imp
// }
//get duration of creative
- duration, status := getBidDuration(bid, *eachImpCtx.AdpodConfig, eachImpCtx.ImpAdPodCfg, sequence)
+ duration, status := getBidDuration(bid, *eachImpCtx.AdpodConfig, adpodProfileCfg, eachImpCtx.ImpAdPodCfg, sequence)
if eachImpCtx.BidIDToDur == nil {
eachImpCtx.BidIDToDur = map[string]int64{}
}
eachImpCtx.BidIDToDur[bid.ID] = duration
impCtx[impId] = eachImpCtx
+
eachImpBid := Bid{
Bid: bid,
ExtBid: ext,
@@ -185,7 +186,7 @@ it will try to get the actual ad duration returned by the bidder using prebid.vi
if prebid.video.duration not present then uses defaultDuration passed as an argument
if video lengths matching policy is present for request then it will validate and update duration based on policy
*/
-func getBidDuration(bid *openrtb2.Bid, adpodConfig models.AdPod, config []*models.ImpAdPodConfig, sequence int) (int64, int64) {
+func getBidDuration(bid *openrtb2.Bid, adpodConfig models.AdPod, adpodProfileCfg *models.AdpodProfileConfig, config []*models.ImpAdPodConfig, sequence int) (int64, int64) {
// C1: Read it from bid.ext.prebid.video.duration field
duration, err := jsonparser.GetInt(bid.Ext, "prebid", "video", "duration")
@@ -201,8 +202,8 @@ func getBidDuration(bid *openrtb2.Bid, adpodConfig models.AdPod, config []*model
}
// C2: Based on video lengths matching policy validate and return duration
- if len(adpodConfig.VideoAdDurationMatching) > 0 {
- return getDurationBasedOnDurationMatchingPolicy(duration, adpodConfig.VideoAdDurationMatching, config)
+ if adpodProfileCfg != nil && len(adpodProfileCfg.AdserverCreativeDurationMatchingPolicy) > 0 {
+ return getDurationBasedOnDurationMatchingPolicy(duration, adpodProfileCfg.AdserverCreativeDurationMatchingPolicy, config)
}
//default return duration which is present in bid.ext.prebid.vide.duration field
diff --git a/modules/pubmatic/openwrap/adpod/impressions/duration_ranges.go b/modules/pubmatic/openwrap/adpod/impressions/duration_ranges.go
index d086cb2d83e..1ff280064f5 100644
--- a/modules/pubmatic/openwrap/adpod/impressions/duration_ranges.go
+++ b/modules/pubmatic/openwrap/adpod/impressions/duration_ranges.go
@@ -12,14 +12,19 @@ type DurRangeConfig struct { //IImpressions interface
}
// newByDurationRanges will create new object ob byDurRangeConfig for creating impressions for adpod request
-func newByDurationRanges(policy string, durations []int, maxAds, adMinDuration, adMaxDuration int) DurRangeConfig {
- return DurRangeConfig{
- policy: policy,
- durations: durations,
+func newByDurationRanges(adpodProfileCfg *models.AdpodProfileConfig, maxAds, adMinDuration, adMaxDuration int) DurRangeConfig {
+ cfg := DurRangeConfig{
maxAds: maxAds,
adMinDuration: adMinDuration,
adMaxDuration: adMaxDuration,
}
+
+ if adpodProfileCfg != nil {
+ cfg.durations = adpodProfileCfg.AdserverCreativeDurations
+ cfg.policy = adpodProfileCfg.AdserverCreativeDurationMatchingPolicy
+ }
+
+ return cfg
}
// Get function returns lists of min,max duration ranges ganerated based on durations
diff --git a/modules/pubmatic/openwrap/adpod/impressions/impression.go b/modules/pubmatic/openwrap/adpod/impressions/impression.go
index 4535b49a845..f1fd6e7be4c 100644
--- a/modules/pubmatic/openwrap/adpod/impressions/impression.go
+++ b/modules/pubmatic/openwrap/adpod/impressions/impression.go
@@ -27,14 +27,14 @@ type ImpGenerator interface {
// Algorithm() int // returns algorithm used for computing number of impressions
}
-func GenerateImpressions(request *openrtb_ext.RequestWrapper, impCtx map[string]models.ImpCtx, pubId string, me metrics.MetricsEngine) ([]*openrtb_ext.ImpWrapper, []error) {
+func GenerateImpressions(request *openrtb_ext.RequestWrapper, impCtx map[string]models.ImpCtx, adpodProfileCfg *models.AdpodProfileConfig, pubId string, me metrics.MetricsEngine) ([]*openrtb_ext.ImpWrapper, []error) {
var imps []*openrtb_ext.ImpWrapper
var errs []error
for _, impWrapper := range request.GetImp() {
eachImpCtx := impCtx[impWrapper.ID]
- impAdpodConfig, err := getAdPodImpConfig(impWrapper.Imp, eachImpCtx.AdpodConfig)
+ impAdpodConfig, err := getAdPodImpConfig(impWrapper.Imp, eachImpCtx.AdpodConfig, adpodProfileCfg)
if impAdpodConfig == nil {
imps = append(imps, impWrapper)
if err != nil {
@@ -95,13 +95,13 @@ func generateImpressionID(impID string, seqNo int) string {
}
// getAdPodImpsConfigs will return number of impressions configurations within adpod
-func getAdPodImpConfig(imp *openrtb2.Imp, adpod *models.AdPod) ([]*models.ImpAdPodConfig, error) {
+func getAdPodImpConfig(imp *openrtb2.Imp, adpod *models.AdPod, adpodProfileCfg *models.AdpodProfileConfig) ([]*models.ImpAdPodConfig, error) {
// This case for non adpod video impression
if adpod == nil {
return nil, nil
}
- selectedAlgorithm := SelectAlgorithm(adpod)
- impGen := NewImpressions(imp.Video.MinDuration, imp.Video.MaxDuration, adpod, selectedAlgorithm)
+ selectedAlgorithm := SelectAlgorithm(adpod, adpodProfileCfg)
+ impGen := NewImpressions(imp.Video.MinDuration, imp.Video.MaxDuration, adpod, adpodProfileCfg, selectedAlgorithm)
impRanges := impGen.Get()
// labels := metrics.PodLabels{AlgorithmName: impressions.MonitorKey[selectedAlgorithm], NoOfImpressions: new(int)}
@@ -132,10 +132,10 @@ func getAdPodImpConfig(imp *openrtb2.Imp, adpod *models.AdPod) ([]*models.ImpAdP
// Return Value:
// - MinMaxAlgorithm (default)
// - ByDurationRanges: if reqAdPod extension has VideoAdDuration and VideoAdDurationMatchingPolicy is "exact" algorithm
-func SelectAlgorithm(reqAdPod *models.AdPod) int {
+func SelectAlgorithm(reqAdPod *models.AdPod, adpodProfileCfg *models.AdpodProfileConfig) int {
if reqAdPod != nil {
- if len(reqAdPod.VideoAdDuration) > 0 &&
- (models.OWExactVideoAdDurationMatching == reqAdPod.VideoAdDurationMatching || models.OWRoundupVideoAdDurationMatching == reqAdPod.VideoAdDurationMatching) {
+ if adpodProfileCfg != nil && len(adpodProfileCfg.AdserverCreativeDurations) > 0 &&
+ (models.OWExactVideoAdDurationMatching == adpodProfileCfg.AdserverCreativeDurationMatchingPolicy || models.OWRoundupVideoAdDurationMatching == adpodProfileCfg.AdserverCreativeDurationMatchingPolicy) {
return models.ByDurationRanges
}
}
@@ -146,7 +146,7 @@ func SelectAlgorithm(reqAdPod *models.AdPod) int {
// based on input algorithm type
// if invalid algorithm type is passed, it returns default algorithm which will compute
// impressions based on minimum ad slot duration
-func NewImpressions(podMinDuration, podMaxDuration int64, adpod *models.AdPod, algorithm int) ImpGenerator {
+func NewImpressions(podMinDuration, podMaxDuration int64, adpod *models.AdPod, adpodProfileCfg *models.AdpodProfileConfig, algorithm int) ImpGenerator {
switch algorithm {
case models.MaximizeForDuration:
g := newMaximizeForDuration(podMinDuration, podMaxDuration, adpod)
@@ -157,10 +157,7 @@ func NewImpressions(podMinDuration, podMaxDuration int64, adpod *models.AdPod, a
return &g
case models.ByDurationRanges:
- g := newByDurationRanges(adpod.VideoAdDurationMatching, adpod.VideoAdDuration,
- int(adpod.MaxAds),
- adpod.MinDuration, adpod.MaxDuration)
-
+ g := newByDurationRanges(adpodProfileCfg, int(adpod.MaxAds), adpod.MinDuration, adpod.MaxDuration)
return &g
}
diff --git a/modules/pubmatic/openwrap/applovinmax.go b/modules/pubmatic/openwrap/applovinmax.go
index c8630f32ac8..185d45e1693 100644
--- a/modules/pubmatic/openwrap/applovinmax.go
+++ b/modules/pubmatic/openwrap/applovinmax.go
@@ -144,7 +144,7 @@ func updateRegs(signalRegs *openrtb2.Regs, maxRequest *openrtb2.BidRequest) {
if signalRegs.COPPA != 0 {
maxRequest.Regs.COPPA = signalRegs.COPPA
}
- maxRequest.Regs.Ext = setIfKeysExists(signalRegs.Ext, maxRequest.Regs.Ext, "gdpr", "gpp", "gpp_sid", "us_privacy")
+ maxRequest.Regs.Ext = setIfKeysExists(signalRegs.Ext, maxRequest.Regs.Ext, "gdpr", "gpp", "gpp_sid", "us_privacy", "dsa")
}
func updateSource(signalSource *openrtb2.Source, maxRequest *openrtb2.BidRequest) {
diff --git a/modules/pubmatic/openwrap/applovinmax_test.go b/modules/pubmatic/openwrap/applovinmax_test.go
index 229ddcfcbdf..c3e77bc204f 100644
--- a/modules/pubmatic/openwrap/applovinmax_test.go
+++ b/modules/pubmatic/openwrap/applovinmax_test.go
@@ -289,6 +289,22 @@ func TestUpdateRegs(t *testing.T) {
},
want: &openrtb2.Regs{Ext: json.RawMessage(`{"gpp":"sdfewe3cer","gdpr":1,"gpp_sid":[6],"us_privacy":"uspConsentString"}`)},
},
+ {
+ name: "signalRegsExt has dsa",
+ args: args{
+ signalRegs: &openrtb2.Regs{Ext: json.RawMessage(`{"dsa":{"dsarequired":3,"pubrender":2,"datatopub":1,"transparency":[{"domain":"params.com","params":[1,2]},{"domain":"dsaicon2.com","params":[2,3]}]}}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Regs{Ext: json.RawMessage(`{"dsa":{"dsarequired":3,"pubrender":2,"datatopub":1,"transparency":[{"domain":"params.com","params":[1,2]},{"domain":"dsaicon2.com","params":[2,3]}]}}`)},
+ },
+ {
+ name: "signalRegsExt has gdpr, gpp, gp_sid, us_privacy, dsa and maxRegsExt has gpp",
+ args: args{
+ signalRegs: &openrtb2.Regs{Ext: json.RawMessage(`{"gdpr":1,"gpp":"sdfewe3cer","gpp_sid":[6],"us_privacy":"uspConsentString","dsa":{"dsarequired":3,"pubrender":2,"datatopub":1,"transparency":[{"domain":"params.com","params":[1,2]},{"domain":"dsaicon2.com","params":[2,3]}]}`)},
+ maxRequest: &openrtb2.BidRequest{Regs: &openrtb2.Regs{Ext: json.RawMessage(`{"gpp":"gpp_string"}`)}},
+ },
+ want: &openrtb2.Regs{Ext: json.RawMessage(`{"gpp":"sdfewe3cer","gdpr":1,"gpp_sid":[6],"us_privacy":"uspConsentString","dsa":{"dsarequired":3,"pubrender":2,"datatopub":1,"transparency":[{"domain":"params.com","params":[1,2]},{"domain":"dsaicon2.com","params":[2,3]}]}}`)},
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/modules/pubmatic/openwrap/auctionresponsehook.go b/modules/pubmatic/openwrap/auctionresponsehook.go
index 6b4011d0100..cacda092cfa 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook.go
@@ -67,6 +67,11 @@ func (m OpenWrap) handleAuctionResponseHook(
return result, nil
}
+ //Impression counting method enabled bidders
+ if rctx.Endpoint == models.EndpointV25 || rctx.Endpoint == models.EndpointAppLovinMax {
+ rctx.ImpCountingMethodEnabledBidders = m.pubFeatures.GetImpCountingMethodEnabledBidders()
+ }
+
var winningAdpodBidIds map[string][]string
var errs []error
if rctx.IsCTVRequest {
diff --git a/modules/pubmatic/openwrap/auctionresponsehook_test.go b/modules/pubmatic/openwrap/auctionresponsehook_test.go
index db94524cb85..55d11e8c552 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook_test.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook_test.go
@@ -1906,8 +1906,8 @@ func TestAuctionResponseHookForApplovinMax(t *testing.T) {
ID: "456",
ImpID: "789",
Price: 1.0,
- BURL: `https:?adv=&af=video&aps=0&au=&bc=pubmatic&bidid=456&di=-1&eg=1&en=1&ft=0&iid=&kgpv=&orig=&origbidid=456&pdvid=0&pid=0&plt=0&pn=pubmatic&psz=0x0&pubid=0&purl=&sl=1&slot=&ss=1&tgid=0&tst=0&owsspburl=http://example.com`,
- Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"456\",\"impid\":\"789\",\"price\":1,\"burl\":\"https:?adv=\\u0026af=video\\u0026aps=0\\u0026au=\\u0026bc=pubmatic\\u0026bidid=456\\u0026di=-1\\u0026eg=1\\u0026en=1\\u0026ft=0\\u0026iid=\\u0026kgpv=\\u0026orig=\\u0026origbidid=456\\u0026pdvid=0\\u0026pid=0\\u0026plt=0\\u0026pn=pubmatic\\u0026psz=0x0\\u0026pubid=0\\u0026purl=\\u0026sl=1\\u0026slot=\\u0026ss=1\\u0026tgid=0\\u0026tst=0\\u0026owsspburl=http://example.com\",\"adm\":\"\\u003cVAST version=\\\"3.0\\\"\\u003e\\u003cAd id=\\\"601364\\\"\\u003e\\u003cInLine\\u003e\\u003cAdSystem\\u003e\\u003c![CDATA[Acudeo Compatible]]\\u003e\\u003c/AdSystem\\u003e\\u003cAdTitle\\u003e\\u003c![CDATA[VAST 2.0 Instream Test 1]]\\u003e\\u003c/AdTitle\\u003e\\u003cDescription\\u003e\\u003c![CDATA[VAST 2.0 Instream Test 1]]\\u003e\\u003c/Description\\u003e\\u003cImpression\\u003e\\u003c![CDATA[http://172.16.4.213/AdServer/AdDisplayTrackerServlet?operId=1\\u0026pubId=5890\\u0026siteId=47163\\u0026adId=1405268\\u0026adType=13\\u0026adServerId=243\\u0026kefact=70.000000\\u0026kaxefact=70.000000\\u0026kadNetFrequecy=0\\u0026kadwidth=0\\u0026kadheight=0\\u0026kadsizeid=97\\u0026kltstamp=1529929473\\u0026indirectAdId=0\\u0026adServerOptimizerId=2\\u0026ranreq=0.1\\u0026kpbmtpfact=100.000000\\u0026dcId=1\\u0026tldId=0\\u0026passback=0\\u0026svr=MADS1107\\u0026ekefact=Ad8wW91TCwCmdG0jlfjXn7Tyzh20hnTVx-m5DoNSep-RXGDr\\u0026ekaxefact=Ad8wWwRUCwAGir4Zzl1eF0bKiC-qrCV0D0yp_eE7YizB_BQk\\u0026ekpbmtpfact=Ad8wWxRUCwD7qgzwwPE2LnS5-Ou19uO5amJl1YT6-XVFvQ41\\u0026imprId=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026oid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026crID=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026campaignId=17050\\u0026creativeId=0\\u0026pctr=0.000000\\u0026wDSPByrId=511\\u0026wDspId=6\\u0026wbId=0\\u0026wrId=0\\u0026wAdvID=3170\\u0026isRTB=1\\u0026rtbId=EBCA079F-8D7C-45B8-B733-92951F670AA1\\u0026pmZoneId=zone1\\u0026pageURL=www.yahoo.com\\u0026lpu=ae.com]]\\u003e\\u003c/Impression\\u003e\\u003cImpression\\u003e\\u003c![CDATA[https://dsptracker.com/{PSPM}]]\\u003e\\u003c/Impression\\u003e\\u003cError\\u003e\\u003c![CDATA[http://172.16.4.213/track?operId=7\\u0026p=5890\\u0026s=47163\\u0026a=1405268\\u0026wa=243\\u0026ts=1529929473\\u0026wc=17050\\u0026crId=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026advertiser_id=3170\\u0026ecpm=70.000000\\u0026er=[ERRORCODE]]]\\u003e\\u003c/Error\\u003e\\u003cError\\u003e\\u003c![CDATA[https://Errortrack.com?p=1234\\u0026er=[ERRORCODE]]]\\u003e\\u003c/Error\\u003e\\u003cCreatives\\u003e\\u003cCreative AdID=\\\"601364\\\"\\u003e\\u003cLinear skipoffset=\\\"20%\\\"\\u003e\\u003cDuration\\u003e\\u003c![CDATA[00:00:04]]\\u003e\\u003c/Duration\\u003e\\u003cVideoClicks\\u003e\\u003cClickTracking\\u003e\\u003c![CDATA[http://172.16.4.213/track?operId=7\\u0026p=5890\\u0026s=47163\\u0026a=1405268\\u0026wa=243\\u0026ts=1529929473\\u0026wc=17050\\u0026crId=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026advertiser_id=3170\\u0026ecpm=70.000000\\u0026e=99]]\\u003e\\u003c/ClickTracking\\u003e\\u003cClickThrough\\u003e\\u003c![CDATA[https://www.sample.com]]\\u003e\\u003c/ClickThrough\\u003e\\u003c/VideoClicks\\u003e\\u003cMediaFiles\\u003e\\u003cMediaFile delivery=\\\"progressive\\\" type=\\\"video/mp4\\\" bitrate=\\\"500\\\" width=\\\"400\\\" height=\\\"300\\\" scalable=\\\"true\\\" maintainAspectRatio=\\\"true\\\"\\u003e\\u003c![CDATA[https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-1.mp4]]\\u003e\\u003c/MediaFile\\u003e\\u003cMediaFile delivery=\\\"progressive\\\" type=\\\"video/mp4\\\" bitrate=\\\"500\\\" width=\\\"400\\\" height=\\\"300\\\" scalable=\\\"true\\\" maintainAspectRatio=\\\"true\\\"\\u003e\\u003c![CDATA[https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-2.mp4]]\\u003e\\u003c/MediaFile\\u003e\\u003c/MediaFiles\\u003e\\u003c/Linear\\u003e\\u003c/Creative\\u003e\\u003c/Creatives\\u003e\\u003cPricing model=\\\"CPM\\\" currency=\\\"USD\\\"\\u003e\\u003c![CDATA[1]]\\u003e\\u003c/Pricing\\u003e\\u003c/InLine\\u003e\\u003c/Ad\\u003e\\u003c/VAST\\u003e\",\"ext\":{\"prebid\":{},\"crtype\":\"video\",\"netecpm\":1}}],\"seat\":\"pubmatic\"}],\"bidid\":\"456\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{}}}"}`),
+ BURL: `https:?adv=&af=video&aps=0&au=&bc=pubmatic&bidid=456&di=-1&eg=1&en=1&ft=0&iid=&kgpv=&orig=&origbidid=456&pdvid=0&pid=0&plt=0&pn=pubmatic&psz=0x0&pubid=0&purl=&sl=1&slot=&ss=1&tgid=0&tst=0&owsspburl=http%3A%2F%2Fexample.com`,
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"456\",\"impid\":\"789\",\"price\":1,\"burl\":\"https:?adv=\\u0026af=video\\u0026aps=0\\u0026au=\\u0026bc=pubmatic\\u0026bidid=456\\u0026di=-1\\u0026eg=1\\u0026en=1\\u0026ft=0\\u0026iid=\\u0026kgpv=\\u0026orig=\\u0026origbidid=456\\u0026pdvid=0\\u0026pid=0\\u0026plt=0\\u0026pn=pubmatic\\u0026psz=0x0\\u0026pubid=0\\u0026purl=\\u0026sl=1\\u0026slot=\\u0026ss=1\\u0026tgid=0\\u0026tst=0\\u0026owsspburl=http%3A%2F%2Fexample.com\",\"adm\":\"\\u003cVAST version=\\\"3.0\\\"\\u003e\\u003cAd id=\\\"601364\\\"\\u003e\\u003cInLine\\u003e\\u003cAdSystem\\u003e\\u003c![CDATA[Acudeo Compatible]]\\u003e\\u003c/AdSystem\\u003e\\u003cAdTitle\\u003e\\u003c![CDATA[VAST 2.0 Instream Test 1]]\\u003e\\u003c/AdTitle\\u003e\\u003cDescription\\u003e\\u003c![CDATA[VAST 2.0 Instream Test 1]]\\u003e\\u003c/Description\\u003e\\u003cImpression\\u003e\\u003c![CDATA[http://172.16.4.213/AdServer/AdDisplayTrackerServlet?operId=1\\u0026pubId=5890\\u0026siteId=47163\\u0026adId=1405268\\u0026adType=13\\u0026adServerId=243\\u0026kefact=70.000000\\u0026kaxefact=70.000000\\u0026kadNetFrequecy=0\\u0026kadwidth=0\\u0026kadheight=0\\u0026kadsizeid=97\\u0026kltstamp=1529929473\\u0026indirectAdId=0\\u0026adServerOptimizerId=2\\u0026ranreq=0.1\\u0026kpbmtpfact=100.000000\\u0026dcId=1\\u0026tldId=0\\u0026passback=0\\u0026svr=MADS1107\\u0026ekefact=Ad8wW91TCwCmdG0jlfjXn7Tyzh20hnTVx-m5DoNSep-RXGDr\\u0026ekaxefact=Ad8wWwRUCwAGir4Zzl1eF0bKiC-qrCV0D0yp_eE7YizB_BQk\\u0026ekpbmtpfact=Ad8wWxRUCwD7qgzwwPE2LnS5-Ou19uO5amJl1YT6-XVFvQ41\\u0026imprId=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026oid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026crID=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026campaignId=17050\\u0026creativeId=0\\u0026pctr=0.000000\\u0026wDSPByrId=511\\u0026wDspId=6\\u0026wbId=0\\u0026wrId=0\\u0026wAdvID=3170\\u0026isRTB=1\\u0026rtbId=EBCA079F-8D7C-45B8-B733-92951F670AA1\\u0026pmZoneId=zone1\\u0026pageURL=www.yahoo.com\\u0026lpu=ae.com]]\\u003e\\u003c/Impression\\u003e\\u003cImpression\\u003e\\u003c![CDATA[https://dsptracker.com/{PSPM}]]\\u003e\\u003c/Impression\\u003e\\u003cError\\u003e\\u003c![CDATA[http://172.16.4.213/track?operId=7\\u0026p=5890\\u0026s=47163\\u0026a=1405268\\u0026wa=243\\u0026ts=1529929473\\u0026wc=17050\\u0026crId=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026advertiser_id=3170\\u0026ecpm=70.000000\\u0026er=[ERRORCODE]]]\\u003e\\u003c/Error\\u003e\\u003cError\\u003e\\u003c![CDATA[https://Errortrack.com?p=1234\\u0026er=[ERRORCODE]]]\\u003e\\u003c/Error\\u003e\\u003cCreatives\\u003e\\u003cCreative AdID=\\\"601364\\\"\\u003e\\u003cLinear skipoffset=\\\"20%\\\"\\u003e\\u003cDuration\\u003e\\u003c![CDATA[00:00:04]]\\u003e\\u003c/Duration\\u003e\\u003cVideoClicks\\u003e\\u003cClickTracking\\u003e\\u003c![CDATA[http://172.16.4.213/track?operId=7\\u0026p=5890\\u0026s=47163\\u0026a=1405268\\u0026wa=243\\u0026ts=1529929473\\u0026wc=17050\\u0026crId=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026advertiser_id=3170\\u0026ecpm=70.000000\\u0026e=99]]\\u003e\\u003c/ClickTracking\\u003e\\u003cClickThrough\\u003e\\u003c![CDATA[https://www.sample.com]]\\u003e\\u003c/ClickThrough\\u003e\\u003c/VideoClicks\\u003e\\u003cMediaFiles\\u003e\\u003cMediaFile delivery=\\\"progressive\\\" type=\\\"video/mp4\\\" bitrate=\\\"500\\\" width=\\\"400\\\" height=\\\"300\\\" scalable=\\\"true\\\" maintainAspectRatio=\\\"true\\\"\\u003e\\u003c![CDATA[https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-1.mp4]]\\u003e\\u003c/MediaFile\\u003e\\u003cMediaFile delivery=\\\"progressive\\\" type=\\\"video/mp4\\\" bitrate=\\\"500\\\" width=\\\"400\\\" height=\\\"300\\\" scalable=\\\"true\\\" maintainAspectRatio=\\\"true\\\"\\u003e\\u003c![CDATA[https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-2.mp4]]\\u003e\\u003c/MediaFile\\u003e\\u003c/MediaFiles\\u003e\\u003c/Linear\\u003e\\u003c/Creative\\u003e\\u003c/Creatives\\u003e\\u003cPricing model=\\\"CPM\\\" currency=\\\"USD\\\"\\u003e\\u003c![CDATA[1]]\\u003e\\u003c/Pricing\\u003e\\u003c/InLine\\u003e\\u003c/Ad\\u003e\\u003c/VAST\\u003e\",\"ext\":{\"prebid\":{},\"crtype\":\"video\",\"netecpm\":1}}],\"seat\":\"pubmatic\"}],\"bidid\":\"456\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{}}}"}`),
},
},
},
@@ -1921,6 +1921,7 @@ func TestAuctionResponseHookForApplovinMax(t *testing.T) {
mockEngine.EXPECT().RecordPublisherResponseTimeStats(gomock.Any(), gomock.Any())
mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false)
mockEngine.EXPECT().RecordPartnerResponseTimeStats(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ mockFeature.EXPECT().GetImpCountingMethodEnabledBidders().Return(map[string]struct{}{})
return mockEngine
},
},
diff --git a/modules/pubmatic/openwrap/beforevalidationhook.go b/modules/pubmatic/openwrap/beforevalidationhook.go
index 058b8b4b5bd..aa4a938e87c 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook.go
@@ -27,6 +27,7 @@ import (
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
modelsAdunitConfig "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/nbr"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/utils"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/util/ptrutil"
)
@@ -170,6 +171,15 @@ func (m OpenWrap) handleBeforeValidationHook(
}
}
+ videoAdDuration := models.GetVersionLevelPropertyFromPartnerConfig(partnerConfigMap, models.VideoAdDurationKey)
+ policy := models.GetVersionLevelPropertyFromPartnerConfig(partnerConfigMap, models.VideoAdDurationMatchingKey)
+ if len(videoAdDuration) > 0 {
+ rCtx.AdpodProfileConfig = &models.AdpodProfileConfig{
+ AdserverCreativeDurations: utils.GetIntArrayFromString(videoAdDuration, models.ArraySeparator),
+ AdserverCreativeDurationMatchingPolicy: policy,
+ }
+ }
+
rCtx.PartnerConfigMap = partnerConfigMap // keep a copy at module level as well
if ver, err := strconv.Atoi(models.GetVersionLevelPropertyFromPartnerConfig(partnerConfigMap, models.DisplayVersionID)); err == nil {
rCtx.DisplayVersionID = ver
@@ -336,7 +346,13 @@ func (m OpenWrap) handleBeforeValidationHook(
m.metricEngine.RecordReqImpsWithContentCount(rCtx.PubIDStr, models.ContentTypeSite)
}
}
- videoAdUnitCtx = adunitconfig.UpdateVideoObjectWithAdunitConfig(rCtx, imp, div, payload.BidRequest.Device.ConnectionType)
+
+ var connectionType *adcom1.ConnectionType
+ if payload.BidRequest.Device != nil && payload.BidRequest.Device.ConnectionType != nil {
+ connectionType = payload.BidRequest.Device.ConnectionType
+ }
+
+ videoAdUnitCtx = adunitconfig.UpdateVideoObjectWithAdunitConfig(rCtx, imp, div, connectionType)
if rCtx.Endpoint == models.EndpointAMP && m.pubFeatures.IsAmpMultiformatEnabled(rCtx.PubID) && isVideoEnabledForAMP(videoAdUnitCtx.AppliedSlotAdUnitConfig) {
//Iniitalized local imp.Video object to update macros and get mappings in case of AMP request
rCtx.AmpVideoEnabled = true
@@ -386,7 +402,7 @@ func (m OpenWrap) handleBeforeValidationHook(
var adpodConfig *models.AdPod
if rCtx.IsCTVRequest {
- adpodConfig, err = adpod.GetAdpodConfigs(imp.Video, requestExt.AdPod, videoAdUnitCtx.AppliedSlotAdUnitConfig, partnerConfigMap, rCtx.PubIDStr, m.metricEngine)
+ adpodConfig, err = adpod.GetV25AdpodConfigs(imp.Video, requestExt.AdPod, videoAdUnitCtx.AppliedSlotAdUnitConfig, partnerConfigMap, rCtx.PubIDStr, m.metricEngine)
if err != nil {
result.NbrCode = int(nbr.InvalidAdpodConfig)
result.Errors = append(result.Errors, "failed to get adpod configurations for "+imp.ID+" reason: "+err.Error())
@@ -395,19 +411,39 @@ func (m OpenWrap) handleBeforeValidationHook(
}
//Adding default durations for CTV Test requests
- if rCtx.IsTestRequest > 0 && adpodConfig != nil && adpodConfig.VideoAdDuration == nil {
- adpodConfig.VideoAdDuration = []int{5, 10}
+ if rCtx.IsTestRequest > 0 && adpodConfig != nil && rCtx.AdpodProfileConfig == nil {
+ rCtx.AdpodProfileConfig = &models.AdpodProfileConfig{
+ AdserverCreativeDurations: []int{5, 10},
+ AdserverCreativeDurationMatchingPolicy: openrtb_ext.OWRoundupVideoAdDurationMatching,
+ }
+ }
+
+ if err := adpod.ValidateV25Configs(rCtx, adpodConfig); err != nil {
+ result.NbrCode = int(nbr.InvalidAdpodConfig)
+ result.Errors = append(result.Errors, "invalid adpod configurations for "+imp.ID+" reason: "+err.Error())
+ rCtx.ImpBidCtx = getDefaultImpBidCtx(*payload.BidRequest)
+ return result, nil
}
- if rCtx.IsTestRequest > 0 && adpodConfig != nil && len(adpodConfig.VideoAdDurationMatching) == 0 {
- adpodConfig.VideoAdDurationMatching = openrtb_ext.OWRoundupVideoAdDurationMatching
+
+ podConfigs, err := adpod.GetAdpodConfigs(rCtx, m.cache, videoAdUnitCtx.AppliedSlotAdUnitConfig)
+ if err != nil {
+ result.NbrCode = int(nbr.InvalidAdpodConfig)
+ result.Errors = append(result.Errors, "failed to get adpod configurations for "+imp.ID+" reason: "+err.Error())
+ rCtx.ImpBidCtx = getDefaultImpBidCtx(*payload.BidRequest)
+ return result, nil
}
- if err := adpod.Validate(adpodConfig); err != nil {
+ err = adpod.ValidateAdpodConfigs(podConfigs)
+ if err != nil {
result.NbrCode = int(nbr.InvalidAdpodConfig)
result.Errors = append(result.Errors, "invalid adpod configurations for "+imp.ID+" reason: "+err.Error())
rCtx.ImpBidCtx = getDefaultImpBidCtx(*payload.BidRequest)
return result, nil
}
+
+ if len(podConfigs) > 0 {
+ rCtx.ImpAdPodConfig[imp.ID] = podConfigs
+ }
}
bidderMeta := make(map[string]models.PartnerData)
@@ -632,6 +668,10 @@ func (m OpenWrap) handleBeforeValidationHook(
result.ChangeSet.AddMutation(func(ep hookstage.BeforeValidationRequestPayload) (hookstage.BeforeValidationRequestPayload, error) {
rctx := moduleCtx.ModuleContext["rctx"].(models.RequestCtx)
+ defer func() {
+ moduleCtx.ModuleContext["rctx"] = rctx
+ }()
+
var err error
if rctx.IsCTVRequest && ep.BidRequest.Source != nil && ep.BidRequest.Source.SChain != nil {
err = ctv.IsValidSchain(ep.BidRequest.Source.SChain)
@@ -651,6 +691,8 @@ func (m OpenWrap) handleBeforeValidationHook(
if err != nil {
result.Errors = append(result.Errors, err.Error())
}
+
+ ep.BidRequest = adpod.ApplyAdpodConfigs(rctx, ep.BidRequest)
}
return ep, err
}, hookstage.MutationUpdate, "request-body-with-profile-data")
diff --git a/modules/pubmatic/openwrap/beforevalidationhook_test.go b/modules/pubmatic/openwrap/beforevalidationhook_test.go
index bc14a7bbfb2..13d8cf44fe5 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook_test.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook_test.go
@@ -23,8 +23,8 @@ import (
metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics"
mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adpodconfig"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
- modelsAdunitConfig "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/nbr"
mock_profilemetadata "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/profilemetadata/mock"
mock_feature "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/publisherfeature/mock"
@@ -3967,6 +3967,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
models.BidderCode: "pub2-alias",
models.IsAlias: "1",
models.TIMEOUT: "200",
+ models.PubID: "301",
models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
models.SERVER_SIDE_FLAG: "1",
models.VENDORID: "130",
@@ -4011,10 +4012,10 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
Reject: false,
NbrCode: 0,
ChangeSet: hookstage.ChangeSet[hookstage.BeforeValidationRequestPayload]{},
- DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":4.3,"BidFloorCur":"USD","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":null,"IncomingSlots":["700x900","728x90","300x250","640x480"],"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"},"VASTTagFlags":null},"dm-alias":{"PartnerID":3,"PrebidBidderCode":"districtm","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlags":null},"pub2-alias":{"PartnerID":1,"PrebidBidderCode":"pubmatic2","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}},"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"},"dm-alias":{"placementId":0,"site":"12313","adtag":"45343"},"pub2-alias":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false,"AdpodConfig":null,"ImpAdPodCfg":null,"BidIDToAPRC":null,"AdserverURL":"","BidIDToDur":null}}`, `new request.ext: {"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidadjustmentfactors":{"appnexus":1,"dm-alias":1,"pub2-alias":1},"bidderparams":{"pub2-alias":{"wiid":""},"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
+ DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":4.3,"BidFloorCur":"USD","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":null,"IncomingSlots":["700x900","728x90","300x250","640x480"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"adtag":"45343","site":"12313"},"VASTTagFlags":null},"dm-alias":{"PartnerID":3,"PrebidBidderCode":"districtm","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlags":null},"pub2-alias":{"PartnerID":1,"PrebidBidderCode":"pubmatic2","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"publisherId":"301","adSlot":"adunit@700x900"},"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"adtag":"45343","site":"12313"},"dm-alias":{"placementId":0,"site":"12313","adtag":"45343"},"pub2-alias":{"publisherId":"301","adSlot":"adunit@700x900"}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false,"AdpodConfig":null,"ImpAdPodCfg":null,"BidIDToAPRC":null,"AdserverURL":"","BidIDToDur":null}}`, `new request.ext: {"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidadjustmentfactors":{"appnexus":1,"dm-alias":1,"pub2-alias":1},"bidderparams":{"pub2-alias":{"wiid":""},"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
AnalyticsTags: hookanalytics.Analytics{},
},
- bidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","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","bidfloor":4.3,"bidfloorcur":"USD","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"adtag":"45343","site":"12313"},"dm-alias":{"placementId":0,"site":"12313","adtag":"45343"},"pub2-alias":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}}}}}}],"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","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","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":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidadjustmentfactors":{"appnexus":1,"dm-alias":1,"pub2-alias":1},"bidderparams":{"pubmatic":{"wiid":""},"pub2-alias":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
+ bidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","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","bidfloor":4.3,"bidfloorcur":"USD","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"},"dm-alias":{"placementId":0,"site":"12313","adtag":"45343"},"pub2-alias":{"publisherId":"301","adSlot":"adunit@700x900"}}}}}],"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","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","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":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidadjustmentfactors":{"appnexus":1,"dm-alias":1,"pub2-alias":1},"bidderparams":{"pub2-alias":{"wiid":""},"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
error: false,
doMutate: true,
nilCurrencyConversion: false,
@@ -4290,6 +4291,278 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
nilCurrencyConversion: false,
},
},
+ {
+ name: "Read_adpod_configs_from_UI_and_update_request_impressions_with_configs",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ PubID: 5890,
+ PubIDStr: "5890",
+ ProfileID: 4444,
+ ProfileIDStr: "4444",
+ DisplayID: 1,
+ SSAuction: 1,
+ Platform: "video",
+ Debug: true,
+ UA: "go-test",
+ IP: "127.0.0.1",
+ IsCTVRequest: true,
+ UidCookie: &http.Cookie{
+ Name: "uids",
+ Value: `eyJ0ZW1wVUlEcyI6eyIzM2Fjcm9zcyI6eyJ1aWQiOiIxMTkxNzkxMDk5Nzc2NjEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTo0My4zODg4Nzk5NVoifSwiYWRmIjp7InVpZCI6IjgwNDQ2MDgzMzM3Nzg4MzkwNzgiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMS4wMzMwNTQ3MjdaIn0sImFka2VybmVsIjp7InVpZCI6IkE5MTYzNTAwNzE0OTkyOTMyOTkwIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuMzczMzg1NjYyWiJ9LCJhZGtlcm5lbEFkbiI6eyJ1aWQiOiJBOTE2MzUwMDcxNDk5MjkzMjk5MCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEzLjQzNDkyNTg5NloifSwiYWRtaXhlciI6eyJ1aWQiOiIzNjZhMTdiMTJmMjI0ZDMwOGYzZTNiOGRhOGMzYzhhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjU5MjkxNDgwMVoifSwiYWRueHMiOnsidWlkIjoiNDE5Mjg5ODUzMDE0NTExOTMiLCJleHBpcmVzIjoiMjAyMy0wMS0xOFQwOTo1MzowOC44MjU0NDI2NzZaIn0sImFqYSI6eyJ1aWQiOiJzMnN1aWQ2RGVmMFl0bjJveGQ1aG9zS1AxVmV3IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTMuMjM5MTc2MDU0WiJ9LCJlcGxhbm5pbmciOnsidWlkIjoiQUoxRjBTOE5qdTdTQ0xWOSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjkyOTk2MDQ3M1oifSwiZ2Ftb3NoaSI6eyJ1aWQiOiJndXNyXzM1NmFmOWIxZDhjNjQyYjQ4MmNiYWQyYjdhMjg4MTYxIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuNTI0MTU3MjI1WiJ9LCJncmlkIjp7InVpZCI6IjRmYzM2MjUwLWQ4NTItNDU5Yy04NzcyLTczNTZkZTE3YWI5NyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE0LjY5NjMxNjIyN1oifSwiZ3JvdXBtIjp7InVpZCI6IjdENzVEMjVGLUZBQzktNDQzRC1CMkQxLUIxN0ZFRTExRTAyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjM5LjIyNjIxMjUzMloifSwiaXgiOnsidWlkIjoiWW9ORlNENlc5QkphOEh6eEdtcXlCUUFBXHUwMDI2Mjk3IiwiZXhwaXJlcyI6IjIwMjMtMDUtMzFUMDc6NTM6MzguNTU1ODI3MzU0WiJ9LCJqaXhpZSI6eyJ1aWQiOiI3MzY3MTI1MC1lODgyLTExZWMtYjUzOC0xM2FjYjdhZjBkZTQiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi4xOTEwOTk3MzJaIn0sImxvZ2ljYWQiOnsidWlkIjoiQVZ4OVROQS11c25pa3M4QURzTHpWa3JvaDg4QUFBR0JUREh0UUEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS40NTUxNDk2MTZaIn0sIm1lZGlhbmV0Ijp7InVpZCI6IjI5Nzg0MjM0OTI4OTU0MTAwMDBWMTAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMy42NzIyMTUxMjhaIn0sIm1naWQiOnsidWlkIjoibTU5Z1hyN0xlX1htIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTcuMDk3MDAxNDcxWiJ9LCJuYW5vaW50ZXJhY3RpdmUiOnsidWlkIjoiNmFlYzhjMTAzNzlkY2I3ODQxMmJjODBiNmRkOWM5NzMxNzNhYjdkNzEyZTQzMWE1YTVlYTcwMzRlNTZhNThhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE2LjcxNDgwNzUwNVoifSwib25ldGFnIjp7InVpZCI6IjdPelZoVzFOeC1LOGFVak1HMG52NXVNYm5YNEFHUXZQbnVHcHFrZ3k0ckEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS4xNDE3NDEyNjJaIn0sIm9wZW54Ijp7InVpZCI6IjVkZWNlNjIyLTBhMjMtMGRhYi0zYTI0LTVhNzcwMTBlNDU4MiIsImV4cGlyZXMiOiIyMDIzLTA1LTMxVDA3OjUyOjQ3LjE0MDQxNzM2M1oifSwicHVibWF0aWMiOnsidWlkIjoiN0Q3NUQyNUYtRkFDOS00NDNELUIyRDEtQjE3RkVFMTFFMDI3IiwiZXhwaXJlcyI6IjIwMjItMTAtMzFUMDk6MTQ6MjUuNzM3MjU2ODk5WiJ9LCJyaWNoYXVkaWVuY2UiOnsidWlkIjoiY2I2YzYzMjAtMzNlMi00Nzc0LWIxNjAtMXp6MTY1NDg0MDc0OSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjUyNTA3NDE4WiJ9LCJzbWFydHlhZHMiOnsidWlkIjoiMTJhZjE1ZTQ0ZjAwZDA3NjMwZTc0YzQ5MTU0Y2JmYmE0Zjg0N2U4ZDRhMTU0YzhjM2Q1MWY1OGNmNzJhNDYyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjgyNTAzMTg4NFoifSwic21pbGV3YW50ZWQiOnsidWlkIjoiZGQ5YzNmZTE4N2VmOWIwOWNhYTViNzExNDA0YzI4MzAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNC4yNTU2MDkzNjNaIn0sInN5bmFjb3JtZWRpYSI6eyJ1aWQiOiJHRFBSIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuOTc5NTgzNDM4WiJ9LCJ0cmlwbGVsaWZ0Ijp7InVpZCI6IjcwMjE5NzUwNTQ4MDg4NjUxOTQ2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA4Ljk4OTY3MzU3NFoifSwidmFsdWVpbXByZXNzaW9uIjp7InVpZCI6IjlkMDgxNTVmLWQ5ZmUtNGI1OC04OThlLWUyYzU2MjgyYWIzZSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjA2NzgzOTE2NFoifSwidmlzeCI6eyJ1aWQiOiIyN2UwYWMzYy1iNDZlLTQxYjMtOTkyYy1mOGQyNzE0OTQ5NWUiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi45ODk1MjM1NzNaIn0sInlpZWxkbGFiIjp7InVpZCI6IjY5NzE0ZDlmLWZiMDAtNGE1Zi04MTljLTRiZTE5MTM2YTMyNSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjExLjMwMzAyNjYxNVoifSwieWllbGRtbyI6eyJ1aWQiOiJnOTZjMmY3MTlmMTU1MWIzMWY2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjExMDUyODYwOVoifSwieWllbGRvbmUiOnsidWlkIjoiMmE0MmZiZDMtMmM3MC00ZWI5LWIxYmQtMDQ2OTY2NTBkOTQ4IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuMzE4MzMzOTM5WiJ9LCJ6ZXJvY2xpY2tmcmF1ZCI6eyJ1aWQiOiJiOTk5NThmZS0yYTg3LTJkYTQtOWNjNC05NjFmZDExM2JlY2UiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNS43MTk1OTQ1NjZaIn19LCJiZGF5IjoiMjAyMi0wNS0xN1QwNjo0ODozOC4wMTc5ODgyMDZaIn0=`,
+ },
+ KADUSERCookie: &http.Cookie{
+ Name: "KADUSERCOOKIE",
+ Value: `7D75D25F-FAC9-443D-B2D1-B17FEE11E027`,
+ },
+ OriginCookie: "go-test",
+ Endpoint: models.EndpointJson,
+ Method: "POST",
+ Aliases: make(map[string]string),
+ ImpBidCtx: make(map[string]models.ImpCtx),
+ PrebidBidderCode: make(map[string]string),
+ BidderResponseTimeMillis: make(map[string]int),
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ MetricsEngine: mockEngine,
+ AdruleFlag: false,
+ AdpodProfileConfig: nil,
+ ImpAdPodConfig: make(map[string][]models.PodConfig),
+ },
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"1559039248176","test":0,"at":1,"tmax":500,"source":{"fd":1,"tid":"1559039248176","pchain":"pchaintagid"},"imp":[{"id":"28635736ddc2bb2","ext":{"bidder":{"appnexus":{"keywords":[],"dealtier":{"prefix":"apnx","mindealtier":4}}}},"displaymanager":"PubMaticSDK","displaymanagerver":"PubMaticSDK-1.0","instl":1,"tagid":"adunit","bidfloor":1,"bidfloorcur":"USD","secure":0,"iframebuster":["1"],"exp":1,"video":{"mimes":["video/3gpp","video/mp4"],"minduration":10,"maxduration":40,"protocols":[2,3,5,6],"w":280,"h":360,"startdelay":1,"placement":5,"linearity":1,"skip":1,"skipmin":5,"skipafter":10,"sequence":1,"battr":[5,6,7],"maxextended":10,"minbitrate":1000,"maxbitrate":2000,"playbackmethod":[1],"delivery":[2],"pos":7,"api":[1,2],"companiontype":[1,2,3],"playbackend":1}}],"site":{"id":"123","name":"EbayShopping","domain":"ebay.com","cat":["IAB1-5"],"sectioncat":["IAB1-5"],"pagecat":["IAB1-5"],"page":"http://ebay.com/inte/automation/s2s/pwt_parameter_validation_muti_slot_multi_size.html?appnexus_deal_priority=6&appnexus_video_fixedbid=10&videobid=4&cat=IAB20-3","ref":"http://ebay.com/home","search":"NewCloths","mobile":1,"privacypolicy":1,"keywords":"Cloths","publisher":{"id":"5890","name":"Test Publisher","cat":["IAB1-5"],"domain":"publisher.com"},"content":{"id":"381d2e0b-548d-4f27-bfdd-e6e66f43557e","episode":1,"title":"StarWars","series":"StarWars","season":"Season3","artist":"GeorgeLucas","genre":"Action","album":"Action","isrc":"2","url":"http://www.pubmatic.com/test/","cat":["IAB1-1","IAB1-2"],"prodq":1,"videoquality":1,"context":1,"contentrating":"MPAA","userrating":"9-Stars","qagmediarating":1,"keywords":"ActionMovies","livestream":1,"sourcerelationship":1,"len":12000,"language":"en","embeddable":1,"producer":{"id":"123","name":"GaryKurtz","cat":["IAB1-5","IAB1-6"],"domain":"producer.com"}}},"device":{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36","dnt":0,"lmt":0,"ip":"172.16.8.74","ipv6":"2001:db8::8a2e:370:7334","devicetype":1,"make":"Apple","model":"iPhone X","os":"iOS","osv":"10","hwv":"10x","h":768,"w":1366,"ppi":4096,"pxratio":1.3,"js":1,"flashver":"1.1","language":"en","carrier":"VERIZON","mccmnc":"310-005","connectiontype":2,"ifa":"EA7583CD-A667-48BC-B806-42ECB2B48606","didsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","didmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","macsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","macmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606"},"user":{"id":"45067fec-eab7-4ca0-ad3a-87b01f21846a","buyeruid":"45067fec-eab7-4ca0-ad3a-87b01f21846a","yob":1990,"gender":"M","keywords":"Movies","customdata":"StarWars"},"regs":{"coppa":0,"ext":{"gdpr":1,"us_privacy":"1YNN"}},"ext":{"wrapper":{"profileid":4444,"versionid":1,"ssauction":1,"sumry_disable":0,"clientconfig":1,"supportdeals":true}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "adunit@0x0": {
+ SlotName: "adunit@0x0",
+ 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@0x0"},
+ HashValueMap: map[string]string{
+ "adunit@0x0": "1232433543534543",
+ },
+ })
+ mockCache.EXPECT().GetPartnerConfigMap(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_VIDEO,
+ },
+ }, nil)
+ mockCache.EXPECT().GetAdunitConfigFromCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&adunitconfig.AdUnitConfig{
+ ConfigPattern: "_AU_",
+ Config: map[string]*adunitconfig.AdConfig{
+ "adunit": {
+ Video: &adunitconfig.Video{
+ Enabled: ptrutil.ToPtr(true),
+ Config: &adunitconfig.VideoConfig{
+ Video: openrtb2.Video{
+ MIMEs: []string{"video/mp4", "video/mpeg"},
+ W: ptrutil.ToPtr[int64](640),
+ H: ptrutil.ToPtr[int64](480),
+ },
+ },
+ UsePodConfig: ptrutil.ToPtr(true),
+ },
+ },
+ },
+ })
+ mockCache.EXPECT().GetAdpodConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(&adpodconfig.AdpodConfig{
+ Dynamic: []adpodconfig.Dynamic{
+ {
+ PodDur: 60,
+ MaxSeq: 3,
+ MinDuration: 20,
+ MaxDuration: 30,
+ },
+ },
+ Structured: []adpodconfig.Structured{
+ {
+ MinDuration: 15,
+ MaxDuration: 15,
+ },
+ },
+ }, nil)
+ //prometheus metrics
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "4444")
+ mockEngine.EXPECT().RecordPublisherRequests(models.EndpointJson, "5890", "video")
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats("video", "5890", "appnexus")
+ mockEngine.EXPECT().RecordCTVRequests("json", models.PLATFORM_DISPLAY)
+ mockEngine.EXPECT().RecordCTVHTTPMethodRequests("json", "5890", "POST")
+ mockEngine.EXPECT().RecordVideoInstlImpsStats("5890", "4444")
+ mockEngine.EXPECT().RecordReqImpsWithContentCount("5890", models.ContentTypeSite)
+ mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false)
+ mockFeature.EXPECT().IsAnalyticsTrackingThrottled(gomock.Any(), gomock.Any()).Return(false, false)
+ mockProfileMetaData.EXPECT().GetProfileTypePlatform(gomock.Any()).Return(0, false)
+ },
+ want: want{
+ hookResult: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{
+ Reject: false,
+ NbrCode: 0,
+ ChangeSet: hookstage.ChangeSet[hookstage.BeforeValidationRequestPayload]{},
+ DebugMessages: []string{`new imp: {"28635736ddc2bb2":{"ImpID":"28635736ddc2bb2","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":1,"BidFloorCur":"USD","IsRewardInventory":null,"Banner":false,"Video":{"mimes":["video/3gpp","video/mp4"],"minduration":10,"maxduration":40,"startdelay":1,"protocols":[2,3,5,6],"w":280,"h":360,"placement":5,"linearity":1,"skip":1,"skipmin":5,"skipafter":10,"sequence":1,"battr":[5,6,7],"maxextended":10,"minbitrate":1000,"maxbitrate":2000,"playbackmethod":[1],"playbackend":1,"delivery":[2],"pos":7,"api":[1,2],"companiontype":[1,2,3]},"Native":null,"IncomingSlots":["280x360"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@0x0","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"adunit","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":{"video":{"enabled":true,"config":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"usepodconfig":true}},"AppliedSlotAdUnitConfig":{"video":{"enabled":true,"config":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"usepodconfig":true}},"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"adunit","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":{"video":{"enabled":true,"config":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"usepodconfig":true}},"AppliedSlotAdUnitConfig":{"video":{"enabled":true,"config":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"usepodconfig":true}},"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false,"AdpodConfig":null,"ImpAdPodCfg":null,"BidIDToAPRC":null,"AdserverURL":"","BidIDToDur":null}}`, `new request.ext: {"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true,"includebrandcategory":{"primaryadserver":0,"publisher":"","withcategory":false,"translatecategories":false,"skipdedup":true}},"macros":{"[PLATFORM]":"2","[PROFILE_ID]":"4444","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
+ AnalyticsTags: hookanalytics.Analytics{},
+ },
+ bidRequest: json.RawMessage(`{"id":"1559039248176","imp":[{"id":"28635736ddc2bb2-dynamic-1-0","video":{"mimes":["video/3gpp","video/mp4"],"minduration":20,"maxduration":30,"startdelay":1,"maxseq":3,"poddur":60,"protocols":[2,3,5,6],"w":280,"h":360,"podid":"dynamic-1","placement":5,"linearity":1,"skip":1,"skipmin":5,"skipafter":10,"sequence":1,"battr":[5,6,7],"maxextended":10,"minbitrate":1000,"maxbitrate":2000,"playbackmethod":[1],"playbackend":1,"delivery":[2],"pos":7,"api":[1,2],"companiontype":[1,2,3]},"displaymanager":"PubMaticSDK","displaymanagerver":"PubMaticSDK-1.0","instl":1,"tagid":"adunit","bidfloor":1,"bidfloorcur":"USD","secure":0,"iframebuster":["1"],"exp":1,"ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}}},{"id":"28635736ddc2bb2-structured-1-1","video":{"mimes":["video/3gpp","video/mp4"],"minduration":15,"maxduration":15,"startdelay":1,"protocols":[2,3,5,6],"w":280,"h":360,"podid":"structured-1","placement":5,"linearity":1,"skip":1,"skipmin":5,"skipafter":10,"sequence":1,"battr":[5,6,7],"maxextended":10,"minbitrate":1000,"maxbitrate":2000,"playbackmethod":[1],"playbackend":1,"delivery":[2],"pos":7,"api":[1,2],"companiontype":[1,2,3]},"displaymanager":"PubMaticSDK","displaymanagerver":"PubMaticSDK-1.0","instl":1,"tagid":"adunit","bidfloor":1,"bidfloorcur":"USD","secure":0,"iframebuster":["1"],"exp":1,"ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}}}],"site":{"id":"123","name":"EbayShopping","domain":"ebay.com","cat":["IAB1-5"],"sectioncat":["IAB1-5"],"pagecat":["IAB1-5"],"page":"http://ebay.com/inte/automation/s2s/pwt_parameter_validation_muti_slot_multi_size.html?appnexus_deal_priority=6\u0026appnexus_video_fixedbid=10\u0026videobid=4\u0026cat=IAB20-3","ref":"http://ebay.com/home","search":"NewCloths","mobile":1,"privacypolicy":1,"publisher":{"id":"5890","name":"Test Publisher","cat":["IAB1-5"],"domain":"publisher.com"},"content":{"id":"381d2e0b-548d-4f27-bfdd-e6e66f43557e","episode":1,"title":"StarWars","series":"StarWars","season":"Season3","artist":"GeorgeLucas","genre":"Action","album":"Action","isrc":"2","producer":{"id":"123","name":"GaryKurtz","cat":["IAB1-5","IAB1-6"],"domain":"producer.com"},"url":"http://www.pubmatic.com/test/","cat":["IAB1-1","IAB1-2"],"prodq":1,"videoquality":1,"context":1,"contentrating":"MPAA","userrating":"9-Stars","qagmediarating":1,"keywords":"ActionMovies","livestream":1,"sourcerelationship":1,"len":12000,"language":"en","embeddable":1},"keywords":"Cloths"},"device":{"dnt":0,"lmt":0,"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36","ip":"172.16.8.74","ipv6":"2001:db8::8a2e:370:7334","devicetype":1,"make":"Apple","model":"iPhone X","os":"iOS","osv":"10","hwv":"10x","h":768,"w":1366,"ppi":4096,"pxratio":1.3,"js":1,"flashver":"1.1","language":"en","carrier":"VERIZON","mccmnc":"310-005","connectiontype":2,"ifa":"EA7583CD-A667-48BC-B806-42ECB2B48606","didsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","didmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","macsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","macmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606"},"user":{"id":"45067fec-eab7-4ca0-ad3a-87b01f21846a","buyeruid":"45067fec-eab7-4ca0-ad3a-87b01f21846a","yob":1990,"gender":"M","keywords":"Movies","customdata":"StarWars"},"at":1,"tmax":500,"source":{"fd":1,"tid":"1559039248176","pchain":"pchaintagid"},"regs":{"ext":{"gdpr":1,"us_privacy":"1YNN"}},"ext":{"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true,"includebrandcategory":{"primaryadserver":0,"publisher":"","withcategory":false,"translatecategories":false,"skipdedup":true}},"macros":{"[PLATFORM]":"2","[PROFILE_ID]":"4444","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
+ error: false,
+ nilCurrencyConversion: false,
+ doMutate: true,
+ },
+ },
+ {
+ name: "Read_adpod_configs_from_Adrule_and_update_request_impressions_with_configs",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ PubID: 5890,
+ PubIDStr: "5890",
+ ProfileID: 4444,
+ ProfileIDStr: "4444",
+ DisplayID: 1,
+ SSAuction: 1,
+ Platform: "video",
+ Debug: true,
+ UA: "go-test",
+ IP: "127.0.0.1",
+ IsCTVRequest: true,
+ UidCookie: &http.Cookie{
+ Name: "uids",
+ Value: `eyJ0ZW1wVUlEcyI6eyIzM2Fjcm9zcyI6eyJ1aWQiOiIxMTkxNzkxMDk5Nzc2NjEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTo0My4zODg4Nzk5NVoifSwiYWRmIjp7InVpZCI6IjgwNDQ2MDgzMzM3Nzg4MzkwNzgiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMS4wMzMwNTQ3MjdaIn0sImFka2VybmVsIjp7InVpZCI6IkE5MTYzNTAwNzE0OTkyOTMyOTkwIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuMzczMzg1NjYyWiJ9LCJhZGtlcm5lbEFkbiI6eyJ1aWQiOiJBOTE2MzUwMDcxNDk5MjkzMjk5MCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEzLjQzNDkyNTg5NloifSwiYWRtaXhlciI6eyJ1aWQiOiIzNjZhMTdiMTJmMjI0ZDMwOGYzZTNiOGRhOGMzYzhhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjU5MjkxNDgwMVoifSwiYWRueHMiOnsidWlkIjoiNDE5Mjg5ODUzMDE0NTExOTMiLCJleHBpcmVzIjoiMjAyMy0wMS0xOFQwOTo1MzowOC44MjU0NDI2NzZaIn0sImFqYSI6eyJ1aWQiOiJzMnN1aWQ2RGVmMFl0bjJveGQ1aG9zS1AxVmV3IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTMuMjM5MTc2MDU0WiJ9LCJlcGxhbm5pbmciOnsidWlkIjoiQUoxRjBTOE5qdTdTQ0xWOSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjkyOTk2MDQ3M1oifSwiZ2Ftb3NoaSI6eyJ1aWQiOiJndXNyXzM1NmFmOWIxZDhjNjQyYjQ4MmNiYWQyYjdhMjg4MTYxIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuNTI0MTU3MjI1WiJ9LCJncmlkIjp7InVpZCI6IjRmYzM2MjUwLWQ4NTItNDU5Yy04NzcyLTczNTZkZTE3YWI5NyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE0LjY5NjMxNjIyN1oifSwiZ3JvdXBtIjp7InVpZCI6IjdENzVEMjVGLUZBQzktNDQzRC1CMkQxLUIxN0ZFRTExRTAyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjM5LjIyNjIxMjUzMloifSwiaXgiOnsidWlkIjoiWW9ORlNENlc5QkphOEh6eEdtcXlCUUFBXHUwMDI2Mjk3IiwiZXhwaXJlcyI6IjIwMjMtMDUtMzFUMDc6NTM6MzguNTU1ODI3MzU0WiJ9LCJqaXhpZSI6eyJ1aWQiOiI3MzY3MTI1MC1lODgyLTExZWMtYjUzOC0xM2FjYjdhZjBkZTQiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi4xOTEwOTk3MzJaIn0sImxvZ2ljYWQiOnsidWlkIjoiQVZ4OVROQS11c25pa3M4QURzTHpWa3JvaDg4QUFBR0JUREh0UUEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS40NTUxNDk2MTZaIn0sIm1lZGlhbmV0Ijp7InVpZCI6IjI5Nzg0MjM0OTI4OTU0MTAwMDBWMTAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMy42NzIyMTUxMjhaIn0sIm1naWQiOnsidWlkIjoibTU5Z1hyN0xlX1htIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTcuMDk3MDAxNDcxWiJ9LCJuYW5vaW50ZXJhY3RpdmUiOnsidWlkIjoiNmFlYzhjMTAzNzlkY2I3ODQxMmJjODBiNmRkOWM5NzMxNzNhYjdkNzEyZTQzMWE1YTVlYTcwMzRlNTZhNThhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE2LjcxNDgwNzUwNVoifSwib25ldGFnIjp7InVpZCI6IjdPelZoVzFOeC1LOGFVak1HMG52NXVNYm5YNEFHUXZQbnVHcHFrZ3k0ckEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS4xNDE3NDEyNjJaIn0sIm9wZW54Ijp7InVpZCI6IjVkZWNlNjIyLTBhMjMtMGRhYi0zYTI0LTVhNzcwMTBlNDU4MiIsImV4cGlyZXMiOiIyMDIzLTA1LTMxVDA3OjUyOjQ3LjE0MDQxNzM2M1oifSwicHVibWF0aWMiOnsidWlkIjoiN0Q3NUQyNUYtRkFDOS00NDNELUIyRDEtQjE3RkVFMTFFMDI3IiwiZXhwaXJlcyI6IjIwMjItMTAtMzFUMDk6MTQ6MjUuNzM3MjU2ODk5WiJ9LCJyaWNoYXVkaWVuY2UiOnsidWlkIjoiY2I2YzYzMjAtMzNlMi00Nzc0LWIxNjAtMXp6MTY1NDg0MDc0OSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjUyNTA3NDE4WiJ9LCJzbWFydHlhZHMiOnsidWlkIjoiMTJhZjE1ZTQ0ZjAwZDA3NjMwZTc0YzQ5MTU0Y2JmYmE0Zjg0N2U4ZDRhMTU0YzhjM2Q1MWY1OGNmNzJhNDYyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjgyNTAzMTg4NFoifSwic21pbGV3YW50ZWQiOnsidWlkIjoiZGQ5YzNmZTE4N2VmOWIwOWNhYTViNzExNDA0YzI4MzAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNC4yNTU2MDkzNjNaIn0sInN5bmFjb3JtZWRpYSI6eyJ1aWQiOiJHRFBSIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuOTc5NTgzNDM4WiJ9LCJ0cmlwbGVsaWZ0Ijp7InVpZCI6IjcwMjE5NzUwNTQ4MDg4NjUxOTQ2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA4Ljk4OTY3MzU3NFoifSwidmFsdWVpbXByZXNzaW9uIjp7InVpZCI6IjlkMDgxNTVmLWQ5ZmUtNGI1OC04OThlLWUyYzU2MjgyYWIzZSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjA2NzgzOTE2NFoifSwidmlzeCI6eyJ1aWQiOiIyN2UwYWMzYy1iNDZlLTQxYjMtOTkyYy1mOGQyNzE0OTQ5NWUiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi45ODk1MjM1NzNaIn0sInlpZWxkbGFiIjp7InVpZCI6IjY5NzE0ZDlmLWZiMDAtNGE1Zi04MTljLTRiZTE5MTM2YTMyNSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjExLjMwMzAyNjYxNVoifSwieWllbGRtbyI6eyJ1aWQiOiJnOTZjMmY3MTlmMTU1MWIzMWY2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjExMDUyODYwOVoifSwieWllbGRvbmUiOnsidWlkIjoiMmE0MmZiZDMtMmM3MC00ZWI5LWIxYmQtMDQ2OTY2NTBkOTQ4IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuMzE4MzMzOTM5WiJ9LCJ6ZXJvY2xpY2tmcmF1ZCI6eyJ1aWQiOiJiOTk5NThmZS0yYTg3LTJkYTQtOWNjNC05NjFmZDExM2JlY2UiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNS43MTk1OTQ1NjZaIn19LCJiZGF5IjoiMjAyMi0wNS0xN1QwNjo0ODozOC4wMTc5ODgyMDZaIn0=`,
+ },
+ KADUSERCookie: &http.Cookie{
+ Name: "KADUSERCOOKIE",
+ Value: `7D75D25F-FAC9-443D-B2D1-B17FEE11E027`,
+ },
+ OriginCookie: "go-test",
+ Endpoint: models.EndpointJson,
+ Method: "POST",
+ Aliases: make(map[string]string),
+ ImpBidCtx: make(map[string]models.ImpCtx),
+ PrebidBidderCode: make(map[string]string),
+ BidderResponseTimeMillis: make(map[string]int),
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ MetricsEngine: mockEngine,
+ AdruleFlag: true,
+ AdpodProfileConfig: nil,
+ ImpAdPodConfig: make(map[string][]models.PodConfig),
+ },
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"1559039248176","test":0,"at":1,"tmax":500,"source":{"fd":1,"tid":"1559039248176","pchain":"pchaintagid"},"imp":[{"id":"28635736ddc2bb2","ext":{"bidder":{"appnexus":{"keywords":[],"dealtier":{"prefix":"apnx","mindealtier":4}}}},"displaymanager":"PubMaticSDK","displaymanagerver":"PubMaticSDK-1.0","instl":1,"tagid":"adunit","bidfloor":1,"bidfloorcur":"USD","secure":0,"iframebuster":["1"],"exp":1,"video":{"mimes":["video/3gpp","video/mp4"],"minduration":10,"maxduration":40,"protocols":[2,3,5,6],"w":280,"h":360,"startdelay":1,"placement":5,"linearity":1,"skip":1,"skipmin":5,"skipafter":10,"sequence":1,"battr":[5,6,7],"maxextended":10,"minbitrate":1000,"maxbitrate":2000,"playbackmethod":[1],"delivery":[2],"pos":7,"api":[1,2],"companiontype":[1,2,3],"playbackend":1}}],"site":{"id":"123","name":"EbayShopping","domain":"ebay.com","cat":["IAB1-5"],"sectioncat":["IAB1-5"],"pagecat":["IAB1-5"],"page":"http://ebay.com/inte/automation/s2s/pwt_parameter_validation_muti_slot_multi_size.html?appnexus_deal_priority=6&appnexus_video_fixedbid=10&videobid=4&cat=IAB20-3","ref":"http://ebay.com/home","search":"NewCloths","mobile":1,"privacypolicy":1,"keywords":"Cloths","publisher":{"id":"5890","name":"Test Publisher","cat":["IAB1-5"],"domain":"publisher.com"},"content":{"id":"381d2e0b-548d-4f27-bfdd-e6e66f43557e","episode":1,"title":"StarWars","series":"StarWars","season":"Season3","artist":"GeorgeLucas","genre":"Action","album":"Action","isrc":"2","url":"http://www.pubmatic.com/test/","cat":["IAB1-1","IAB1-2"],"prodq":1,"videoquality":1,"context":1,"contentrating":"MPAA","userrating":"9-Stars","qagmediarating":1,"keywords":"ActionMovies","livestream":1,"sourcerelationship":1,"len":12000,"language":"en","embeddable":1,"producer":{"id":"123","name":"GaryKurtz","cat":["IAB1-5","IAB1-6"],"domain":"producer.com"}}},"device":{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36","dnt":0,"lmt":0,"ip":"172.16.8.74","ipv6":"2001:db8::8a2e:370:7334","devicetype":1,"make":"Apple","model":"iPhone X","os":"iOS","osv":"10","hwv":"10x","h":768,"w":1366,"ppi":4096,"pxratio":1.3,"js":1,"flashver":"1.1","language":"en","carrier":"VERIZON","mccmnc":"310-005","connectiontype":2,"ifa":"EA7583CD-A667-48BC-B806-42ECB2B48606","didsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","didmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","macsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","macmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606"},"user":{"id":"45067fec-eab7-4ca0-ad3a-87b01f21846a","buyeruid":"45067fec-eab7-4ca0-ad3a-87b01f21846a","yob":1990,"gender":"M","keywords":"Movies","customdata":"StarWars"},"regs":{"coppa":0,"ext":{"gdpr":1,"us_privacy":"1YNN"}},"ext":{"wrapper":{"profileid":4444,"versionid":1,"ssauction":1,"sumry_disable":0,"clientconfig":1,"supportdeals":true}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "adunit@0x0": {
+ SlotName: "adunit@0x0",
+ 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@0x0"},
+ HashValueMap: map[string]string{
+ "adunit@0x0": "1232433543534543",
+ },
+ })
+ mockCache.EXPECT().GetPartnerConfigMap(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_VIDEO,
+ },
+ }, nil)
+ mockCache.EXPECT().GetAdunitConfigFromCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&adunitconfig.AdUnitConfig{
+ ConfigPattern: "_AU_",
+ Config: map[string]*adunitconfig.AdConfig{
+ "adunit": {
+ Video: &adunitconfig.Video{
+ Enabled: ptrutil.ToPtr(true),
+ Config: &adunitconfig.VideoConfig{
+ Video: openrtb2.Video{
+ MIMEs: []string{"video/mp4", "video/mpeg"},
+ W: ptrutil.ToPtr[int64](640),
+ H: ptrutil.ToPtr[int64](480),
+ },
+ },
+ },
+ Adrule: []*openrtb2.Video{
+ {
+ PodID: "dynamic-1",
+ PodDur: 60,
+ MaxSeq: 3,
+ MinDuration: 20,
+ MaxDuration: 30,
+ },
+ {
+ PodID: "structured-1",
+ MinDuration: 15,
+ MaxDuration: 15,
+ },
+ },
+ },
+ },
+ })
+ mockCache.EXPECT().GetAdpodConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
+ //prometheus metrics
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "4444")
+ mockEngine.EXPECT().RecordPublisherRequests(models.EndpointJson, "5890", "video")
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats("video", "5890", "appnexus")
+ mockEngine.EXPECT().RecordCTVRequests("json", models.PLATFORM_DISPLAY)
+ mockEngine.EXPECT().RecordCTVHTTPMethodRequests("json", "5890", "POST")
+ mockEngine.EXPECT().RecordVideoInstlImpsStats("5890", "4444")
+ mockEngine.EXPECT().RecordReqImpsWithContentCount("5890", models.ContentTypeSite)
+ mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false)
+ mockFeature.EXPECT().IsAnalyticsTrackingThrottled(gomock.Any(), gomock.Any()).Return(false, false)
+ mockProfileMetaData.EXPECT().GetProfileTypePlatform(gomock.Any()).Return(0, false)
+ },
+ want: want{
+ hookResult: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{
+ Reject: false,
+ NbrCode: 0,
+ ChangeSet: hookstage.ChangeSet[hookstage.BeforeValidationRequestPayload]{},
+ DebugMessages: []string{`new imp: {"28635736ddc2bb2":{"AdpodConfig":null,"AdserverURL":"","AdUnitName":"adunit","Banner":false,"BannerAdUnitCtx":{"AllowedConnectionTypes":null,"AppliedSlotAdUnitConfig":{"adrule":[{"maxduration":30,"maxseq":3,"mimes":null,"minduration":20,"poddur":60,"podid":"dynamic-1"},{"maxduration":15,"mimes":null,"minduration":15,"podid":"structured-1"}],"video":{"config":{"h":480,"mimes":["video/mp4","video/mpeg"],"w":640},"enabled":true}},"IsRegex":false,"MatchedRegex":"","MatchedSlot":"adunit","SelectedSlotAdUnitConfig":{"adrule":[{"maxduration":30,"maxseq":3,"mimes":null,"minduration":20,"poddur":60,"podid":"dynamic-1"},{"maxduration":15,"mimes":null,"minduration":15,"podid":"structured-1"}],"video":{"config":{"h":480,"mimes":["video/mp4","video/mpeg"],"w":640},"enabled":true}},"UsingDefaultConfig":false},"BidCtx":{},"BidderError":"","Bidders":{"appnexus":{"IsRegex":false,"KGP":"_AU_@_W_x_H_","KGPV":"","MatchedSlot":"adunit@0x0","Params":{"adtag":"45343","placementId":0,"site":"12313"},"PartnerID":2,"PrebidBidderCode":"appnexus","VASTTagFlags":null}},"BidFloor":1,"BidFloorCur":"USD","BidIDToAPRC":null,"BidIDToDur":null,"Div":"","ImpAdPodCfg":null,"ImpID":"28635736ddc2bb2","IncomingSlots":["280x360"],"IsAdPodRequest":false,"IsRewardInventory":null,"Native":null,"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"adtag":"45343","placementId":0,"site":"12313"}}}},"NonMapped":{},"Secure":0,"SlotName":"adunit","TagID":"adunit","Type":"video","Video":{"api":[1,2],"battr":[5,6,7],"companiontype":[1,2,3],"delivery":[2],"h":360,"linearity":1,"maxbitrate":2000,"maxduration":40,"maxextended":10,"mimes":["video/3gpp","video/mp4"],"minbitrate":1000,"minduration":10,"placement":5,"playbackend":1,"playbackmethod":[1],"pos":7,"protocols":[2,3,5,6],"sequence":1,"skip":1,"skipafter":10,"skipmin":5,"startdelay":1,"w":280},"VideoAdUnitCtx":{"AllowedConnectionTypes":null,"AppliedSlotAdUnitConfig":{"adrule":[{"maxduration":30,"maxseq":3,"mimes":null,"minduration":20,"poddur":60,"podid":"dynamic-1"},{"maxduration":15,"mimes":null,"minduration":15,"podid":"structured-1"}],"video":{"config":{"h":480,"mimes":["video/mp4","video/mpeg"],"w":640},"enabled":true}},"IsRegex":false,"MatchedRegex":"","MatchedSlot":"adunit","SelectedSlotAdUnitConfig":{"adrule":[{"maxduration":30,"maxseq":3,"mimes":null,"minduration":20,"poddur":60,"podid":"dynamic-1"},{"maxduration":15,"mimes":null,"minduration":15,"podid":"structured-1"}],"video":{"config":{"h":480,"mimes":["video/mp4","video/mpeg"],"w":640},"enabled":true}},"UsingDefaultConfig":false}}}`, `new request.ext: {"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true,"includebrandcategory":{"primaryadserver":0,"publisher":"","withcategory":false,"translatecategories":false,"skipdedup":true}},"macros":{"[PLATFORM]":"2","[PROFILE_ID]":"4444","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
+ AnalyticsTags: hookanalytics.Analytics{},
+ },
+ bidRequest: json.RawMessage(`{"id":"1559039248176","imp":[{"id":"28635736ddc2bb2-dynamic-1-0","video":{"mimes":["video/3gpp","video/mp4"],"minduration":20,"maxduration":30,"startdelay":1,"maxseq":3,"poddur":60,"protocols":[2,3,5,6],"w":280,"h":360,"podid":"dynamic-1","placement":5,"linearity":1,"skip":1,"skipmin":5,"skipafter":10,"sequence":1,"battr":[5,6,7],"maxextended":10,"minbitrate":1000,"maxbitrate":2000,"playbackmethod":[1],"playbackend":1,"delivery":[2],"pos":7,"api":[1,2],"companiontype":[1,2,3]},"displaymanager":"PubMaticSDK","displaymanagerver":"PubMaticSDK-1.0","instl":1,"tagid":"adunit","bidfloor":1,"bidfloorcur":"USD","secure":0,"iframebuster":["1"],"exp":1,"ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}}},{"id":"28635736ddc2bb2-structured-1-1","video":{"mimes":["video/3gpp","video/mp4"],"minduration":15,"maxduration":15,"startdelay":1,"protocols":[2,3,5,6],"w":280,"h":360,"podid":"structured-1","placement":5,"linearity":1,"skip":1,"skipmin":5,"skipafter":10,"sequence":1,"battr":[5,6,7],"maxextended":10,"minbitrate":1000,"maxbitrate":2000,"playbackmethod":[1],"playbackend":1,"delivery":[2],"pos":7,"api":[1,2],"companiontype":[1,2,3]},"displaymanager":"PubMaticSDK","displaymanagerver":"PubMaticSDK-1.0","instl":1,"tagid":"adunit","bidfloor":1,"bidfloorcur":"USD","secure":0,"iframebuster":["1"],"exp":1,"ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}}}],"site":{"id":"123","name":"EbayShopping","domain":"ebay.com","cat":["IAB1-5"],"sectioncat":["IAB1-5"],"pagecat":["IAB1-5"],"page":"http://ebay.com/inte/automation/s2s/pwt_parameter_validation_muti_slot_multi_size.html?appnexus_deal_priority=6\u0026appnexus_video_fixedbid=10\u0026videobid=4\u0026cat=IAB20-3","ref":"http://ebay.com/home","search":"NewCloths","mobile":1,"privacypolicy":1,"publisher":{"id":"5890","name":"Test Publisher","cat":["IAB1-5"],"domain":"publisher.com"},"content":{"id":"381d2e0b-548d-4f27-bfdd-e6e66f43557e","episode":1,"title":"StarWars","series":"StarWars","season":"Season3","artist":"GeorgeLucas","genre":"Action","album":"Action","isrc":"2","producer":{"id":"123","name":"GaryKurtz","cat":["IAB1-5","IAB1-6"],"domain":"producer.com"},"url":"http://www.pubmatic.com/test/","cat":["IAB1-1","IAB1-2"],"prodq":1,"videoquality":1,"context":1,"contentrating":"MPAA","userrating":"9-Stars","qagmediarating":1,"keywords":"ActionMovies","livestream":1,"sourcerelationship":1,"len":12000,"language":"en","embeddable":1},"keywords":"Cloths"},"device":{"dnt":0,"lmt":0,"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36","ip":"172.16.8.74","ipv6":"2001:db8::8a2e:370:7334","devicetype":1,"make":"Apple","model":"iPhone X","os":"iOS","osv":"10","hwv":"10x","h":768,"w":1366,"ppi":4096,"pxratio":1.3,"js":1,"flashver":"1.1","language":"en","carrier":"VERIZON","mccmnc":"310-005","connectiontype":2,"ifa":"EA7583CD-A667-48BC-B806-42ECB2B48606","didsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","didmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","dpidmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606","macsha1":"EA7583CD-A667-48BC-B806-42ECB2B48606","macmd5":"EA7583CD-A667-48BC-B806-42ECB2B48606"},"user":{"id":"45067fec-eab7-4ca0-ad3a-87b01f21846a","buyeruid":"45067fec-eab7-4ca0-ad3a-87b01f21846a","yob":1990,"gender":"M","keywords":"Movies","customdata":"StarWars"},"at":1,"tmax":500,"source":{"fd":1,"tid":"1559039248176","pchain":"pchaintagid"},"regs":{"ext":{"gdpr":1,"us_privacy":"1YNN"}},"ext":{"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true,"includebrandcategory":{"primaryadserver":0,"publisher":"","withcategory":false,"translatecategories":false,"skipdedup":true}},"macros":{"[PLATFORM]":"2","[PROFILE_ID]":"4444","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
+ error: false,
+ nilCurrencyConversion: false,
+ doMutate: true,
+ },
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -5663,7 +5936,7 @@ func TestGetTagID(t *testing.T) {
func TestUpdateImpVideoWithVideoConfig(t *testing.T) {
type args struct {
imp *openrtb2.Imp
- configObjInVideoConfig *modelsAdunitConfig.VideoConfig
+ configObjInVideoConfig *adunitconfig.VideoConfig
}
tests := []struct {
name string
@@ -5677,7 +5950,7 @@ func TestUpdateImpVideoWithVideoConfig(t *testing.T) {
ID: "123",
Video: &openrtb2.Video{},
},
- configObjInVideoConfig: &modelsAdunitConfig.VideoConfig{
+ configObjInVideoConfig: &adunitconfig.VideoConfig{
Video: openrtb2.Video{
W: ptrutil.ToPtr[int64](300),
H: ptrutil.ToPtr[int64](250),
@@ -5746,7 +6019,7 @@ func TestUpdateImpVideoWithVideoConfig(t *testing.T) {
},
},
- configObjInVideoConfig: &modelsAdunitConfig.VideoConfig{
+ configObjInVideoConfig: &adunitconfig.VideoConfig{
Video: openrtb2.Video{
W: ptrutil.ToPtr[int64](400),
H: ptrutil.ToPtr[int64](300),
@@ -6154,7 +6427,7 @@ func TestIsVastUnwrapEnabled(t *testing.T) {
func TestSetImpBidFloorParams(t *testing.T) {
type args struct {
rCtx models.RequestCtx
- adUnitCfg *modelsAdunitConfig.AdConfig
+ adUnitCfg *adunitconfig.AdConfig
imp *openrtb2.Imp
conversions currency.Conversions
}
@@ -6170,7 +6443,7 @@ func TestSetImpBidFloorParams(t *testing.T) {
rCtx: models.RequestCtx{
IsMaxFloorsEnabled: false,
},
- adUnitCfg: &modelsAdunitConfig.AdConfig{
+ adUnitCfg: &adunitconfig.AdConfig{
BidFloor: ptrutil.ToPtr(2.0),
BidFloorCur: ptrutil.ToPtr("USD"),
},
@@ -6188,7 +6461,7 @@ func TestSetImpBidFloorParams(t *testing.T) {
rCtx: models.RequestCtx{
IsMaxFloorsEnabled: true,
},
- adUnitCfg: &modelsAdunitConfig.AdConfig{
+ adUnitCfg: &adunitconfig.AdConfig{
BidFloor: ptrutil.ToPtr(2.0),
BidFloorCur: ptrutil.ToPtr("USD"),
},
@@ -6206,7 +6479,7 @@ func TestSetImpBidFloorParams(t *testing.T) {
rCtx: models.RequestCtx{
IsMaxFloorsEnabled: true,
},
- adUnitCfg: &modelsAdunitConfig.AdConfig{
+ adUnitCfg: &adunitconfig.AdConfig{
BidFloor: ptrutil.ToPtr(2.0),
BidFloorCur: ptrutil.ToPtr("USD"),
},
diff --git a/modules/pubmatic/openwrap/bidderparams/pubmatic.go b/modules/pubmatic/openwrap/bidderparams/pubmatic.go
index e79858bb0d5..e1583092c34 100644
--- a/modules/pubmatic/openwrap/bidderparams/pubmatic.go
+++ b/modules/pubmatic/openwrap/bidderparams/pubmatic.go
@@ -3,7 +3,6 @@ package bidderparams
import (
"encoding/json"
"fmt"
- "strconv"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/cache"
@@ -12,16 +11,9 @@ import (
)
func PreparePubMaticParamsV25(rctx models.RequestCtx, cache cache.Cache, bidRequest openrtb2.BidRequest, imp openrtb2.Imp, impExt models.ImpExtension, partnerID int) (string, string, bool, []byte, error) {
- wrapExt := fmt.Sprintf(`{"%s":%d,"%s":%d}`, models.SS_PM_VERSION_ID, rctx.DisplayID, models.SS_PM_PROFILE_ID, rctx.ProfileID)
-
- // change profile id for pubmatic2
- if secondaryProfileID, ok := rctx.PartnerConfigMap[partnerID][models.KEY_PROFILE_ID]; ok {
- wrapExt = fmt.Sprintf(`{"%s":0,"%s":%s}`, models.SS_PM_VERSION_ID, models.SS_PM_PROFILE_ID, secondaryProfileID)
- }
-
extImpPubMatic := openrtb_ext.ExtImpPubmatic{
- PublisherId: strconv.Itoa(rctx.PubID),
- WrapExt: json.RawMessage(wrapExt),
+ PublisherId: getPubMaticPublisherID(rctx, partnerID),
+ WrapExt: getPubMaticWrapperExt(rctx, partnerID),
Keywords: getImpExtPubMaticKeyWords(impExt, rctx.PartnerConfigMap[partnerID][models.BidderCode]),
Floors: getApplovinBidFloors(rctx, imp),
SendBurl: rctx.SendBurl,
@@ -38,13 +30,7 @@ func PreparePubMaticParamsV25(rctx models.RequestCtx, cache cache.Cache, bidRequ
isRegexKGP = true
}
- if rctx.IsTestRequest == 1 {
- matchedSlot, matchedPattern, isRegexSlot = getMatchingSlotAndPattern(rctx, cache, slots, slotMap, slotMappingInfo, isRegexKGP, isRegexSlot, partnerID, &extImpPubMatic, imp)
- params, err := json.Marshal(extImpPubMatic)
- return matchedSlot, matchedPattern, isRegexSlot, params, err
- }
-
- if rctx.IsTestRequest > 0 {
+ if rctx.IsTestRequest == models.TestValueTwo {
if len(slots) > 0 {
extImpPubMatic.AdSlot = slots[0]
}
@@ -149,3 +135,33 @@ func getMatchingSlotAndPattern(rctx models.RequestCtx, cache cache.Cache, slots
}
return matchedSlot, matchedPattern, isRegexSlot
}
+
+func getPubMaticPublisherID(rctx models.RequestCtx, partnerID int) string {
+ //Pubmatic secondary flow send account level pubID
+ if pubID, ok := rctx.PartnerConfigMap[partnerID][models.KEY_PUBLISHER_ID]; ok {
+ return pubID
+ }
+ //PubMatic alias flow
+ if pubID, ok := rctx.PartnerConfigMap[partnerID][models.PubID]; ok {
+ return pubID
+ }
+ //PubMatic primary flow
+ return rctx.PubIDStr
+}
+
+func getPubMaticWrapperExt(rctx models.RequestCtx, partnerID int) json.RawMessage {
+ wrapExt := fmt.Sprintf(`{"%s":%d,"%s":%d}`, models.SS_PM_VERSION_ID, rctx.DisplayID, models.SS_PM_PROFILE_ID, rctx.ProfileID)
+
+ // change profile id for pubmatic2
+ if secondaryProfileID, ok := rctx.PartnerConfigMap[partnerID][models.KEY_PROFILE_ID]; ok {
+ wrapExt = fmt.Sprintf(`{"%s":%s}`, models.SS_PM_PROFILE_ID, secondaryProfileID)
+ }
+
+ //Pubmatic alias flow do not send wrapExt
+ if isAlias, ok := rctx.PartnerConfigMap[partnerID][models.IsAlias]; ok && isAlias == "1" {
+ if pubID, ok := rctx.PartnerConfigMap[partnerID][models.PubID]; ok && pubID != rctx.PubIDStr {
+ return nil
+ }
+ }
+ return json.RawMessage(wrapExt)
+}
diff --git a/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go b/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go
index 1efdf6150e4..14b004fd4f1 100644
--- a/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go
+++ b/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go
@@ -1,6 +1,7 @@
package bidderparams
import (
+ "encoding/json"
"testing"
"github.com/golang/mock/gomock"
@@ -254,6 +255,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 1,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -291,26 +293,31 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
},
setup: func() {
mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
- "/test_adunit1234@div1@200x300": {
+ "/test_adunit12345@div1@200x300": {
PartnerId: 1,
AdapterId: 1,
SlotName: "/Test_Adunit1234@Div1@200x300",
SlotMappings: map[string]interface{}{
"site": "12313",
"adtag": "45343",
- "slotName": "/Test_Adunit1234@DIV1@200x300",
+ "slotName": "/Test_Adunit1234@Div1@200x300",
},
},
})
mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
- OrderedSlotList: []string{"test", "test1"},
+ OrderedSlotList: []string{"/test_adunit1234@div1@200x300"},
+ HashValueMap: map[string]string{
+ "/test_adunit1234@div1@200x300": "2aa34b52a9e941c1594af7565e599c8d",
+ },
})
+ mockCache.EXPECT().Get("psregex_5890_123_1_1_/Test_Adunit1234@Div1@200x300").Return(nil, false)
+ mockCache.EXPECT().Set("psregex_5890_123_1_1_/Test_Adunit1234@Div1@200x300", regexSlotEntry{SlotName: "/Test_Adunit1234@Div1@200x300", RegexPattern: "/test_adunit1234@div1@200x300"}).Times(1)
},
want: want{
matchedSlot: "/Test_Adunit1234@Div1@200x300",
- matchedPattern: "",
- isRegexSlot: false,
- params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@Div1@200x300","wrapper":{"version":1,"profile":123},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ matchedPattern: "/test_adunit1234@div1@200x300",
+ isRegexSlot: true,
+ params: []byte(`{"publisherId":"5890","adSlot":"2aa34b52a9e941c1594af7565e599c8d","wrapper":{"version":1,"profile":123},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
wantErr: false,
},
},
@@ -320,23 +327,25 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
1: {
- models.PREBID_PARTNER_NAME: "pubmatic",
- models.BidderCode: "pubmatic",
+ models.PREBID_PARTNER_NAME: "pubmatic2",
+ models.BidderCode: "pubmatic2",
models.TIMEOUT: "200",
models.KEY_GEN_PATTERN: "_AU_@_DIV_@_W_x_H_",
models.SERVER_SIDE_FLAG: "1",
models.KEY_PROFILE_ID: "1323",
+ models.KEY_PUBLISHER_ID: "301",
},
},
},
cache: mockCache,
impExt: models.ImpExtension{
Bidder: map[string]*models.BidderExtension{
- "pubmatic": {
+ "pubmatic2": {
KeyWords: []models.KeyVal{
{
Key: "test_key1",
@@ -377,7 +386,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
matchedSlot: "/Test_Adunit1234@Div1@200x300",
matchedPattern: "",
isRegexSlot: false,
- params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@DIV1@200x300","wrapper":{"version":0,"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ params: []byte(`{"publisherId":"301","adSlot":"/Test_Adunit1234@DIV1@200x300","wrapper":{"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
wantErr: false,
},
},
@@ -387,23 +396,91 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
1: {
- models.PREBID_PARTNER_NAME: "pubmatic",
- models.BidderCode: "pubmatic",
+ models.PREBID_PARTNER_NAME: "pubmatic2",
+ models.BidderCode: "pubmatic2",
models.TIMEOUT: "200",
models.KEY_GEN_PATTERN: "_RE_@_W_x_H_",
models.SERVER_SIDE_FLAG: "1",
models.KEY_PROFILE_ID: "1323",
+ models.KEY_PUBLISHER_ID: "301",
},
},
},
cache: mockCache,
impExt: models.ImpExtension{
Bidder: map[string]*models.BidderExtension{
- "pubmatic": {
+ "pubmatic2": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "/test_adunit1234@200x300": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@200x300",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ "slotName": "/Test_Adunit1234@200x300",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ })
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@200x300",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: []byte(`{"publisherId":"301","adSlot":"/Test_Adunit1234@200x300","wrapper":{"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
+ {
+ name: "exact_matched_slot_found_adslot_updated_from_PubMatic_alias_flow_for_prebids2s_regex",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 0,
+ PubID: 5890,
+ PubIDStr: "5890",
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic_alias",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_RE_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ models.IsAlias: "1",
+ models.PubID: "301",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic_alias": {
KeyWords: []models.KeyVal{
{
Key: "test_key1",
@@ -441,7 +518,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
matchedSlot: "/Test_Adunit1234@200x300",
matchedPattern: "",
isRegexSlot: false,
- params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@200x300","wrapper":{"version":0,"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ params: []byte(`{"publisherId":"301","adSlot":"/Test_Adunit1234@200x300","keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
wantErr: false,
},
},
@@ -451,6 +528,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -514,6 +592,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -583,6 +662,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -649,6 +729,80 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_AU_@_DIV_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ Wrapper: &models.ExtImpWrapper{
+ Div: "Div1",
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ ".*@div.*@.*": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@Div1@200x300",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ HashValueMap: map[string]string{
+ ".*@Div.*@.*": "2aa34b52a9e941c1594af7565e599c8d",
+ },
+ })
+ mockCache.EXPECT().Get("psregex_5890_123_1_1_/Test_Adunit1234@Div1@200x300").Return(regexSlotEntry{
+ SlotName: "/Test_Adunit1234@Div1@200x300",
+ RegexPattern: ".*@Div.*@.*",
+ }, true)
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@Div1@200x300",
+ matchedPattern: ".*@Div.*@.*",
+ isRegexSlot: true,
+ params: []byte(`{"publisherId":"5890","adSlot":"2aa34b52a9e941c1594af7565e599c8d","wrapper":{"version":1,"profile":123},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
+ {
+ name: "regex_matched_slot_found_adSlot_upadted_from_hashValue_for_test_value_1",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 1,
+ PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -721,6 +875,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -787,6 +942,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -853,6 +1009,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -919,6 +1076,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -985,6 +1143,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -1046,11 +1205,12 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
},
},
{
- name: "For test value 1",
+ name: "For_test_value_1_for_regex",
args: args{
rctx: models.RequestCtx{
IsTestRequest: 1,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -1116,12 +1276,218 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
wantErr: false,
},
},
+ {
+ name: "For_test_value_1_for_non_regex",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 1,
+ PubID: 5890,
+ PubIDStr: "5890",
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ Wrapper: &models.ExtImpWrapper{
+ Div: "Div1",
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", false, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "/test_adunit1234@1x1": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@1x1",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ models.KEY_OW_SLOT_NAME: "/Test_Adunit1234@1x1",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ })
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@1x1",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@1x1","wrapper":{"version":1,"profile":123},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
+ {
+ name: "For_test_value_1_exact_matched_slot_found_adslot_updated_from_PubMatic_secondary_flow",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 1,
+ PubID: 5890,
+ PubIDStr: "5890",
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic2",
+ models.BidderCode: "pubmatic2",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_AU_@_DIV_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_PROFILE_ID: "1323",
+ models.KEY_PUBLISHER_ID: "301",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic2": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ Wrapper: &models.ExtImpWrapper{
+ Div: "Div1",
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "/test_adunit1234@div1@200x300": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@Div1@200x300",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ "slotName": "/Test_Adunit1234@DIV1@200x300",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ })
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@Div1@200x300",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: []byte(`{"publisherId":"301","adSlot":"/Test_Adunit1234@DIV1@200x300","wrapper":{"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
+ {
+ name: "For_test_value_1_exact_matched_slot_found_adslot_updated_from_PubMatic_secondary_flow_for_different_slotname",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 1,
+ PubID: 5890,
+ PubIDStr: "5890",
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic2",
+ models.BidderCode: "pubmatic2",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_AU_@_DIV_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_PROFILE_ID: "1323",
+ models.KEY_PUBLISHER_ID: "301",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic2": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ Wrapper: &models.ExtImpWrapper{
+ Div: "Div1",
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "/test_adunit1234@div1@200x300": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@Div1@200x300",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ "slotName": "pubmatic2-slot",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ })
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@Div1@200x300",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: []byte(`{"publisherId":"301","adSlot":"pubmatic2-slot","wrapper":{"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
{
name: "For_test_value_2_with_regex",
args: args{
rctx: models.RequestCtx{
IsTestRequest: 2,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -1171,6 +1537,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 2,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
DisplayID: 1,
PartnerConfigMap: map[int]map[string]string{
@@ -1220,6 +1587,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
rctx: models.RequestCtx{
IsTestRequest: 0,
PubID: 5890,
+ PubIDStr: "5890",
ProfileID: 123,
ProfileIDStr: "123",
DisplayID: 1,
@@ -1231,7 +1599,6 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
models.TIMEOUT: "200",
models.KEY_GEN_PATTERN: "_AU_@_DIV_@_W_x_H_",
models.SERVER_SIDE_FLAG: "1",
- models.KEY_PROFILE_ID: "1323",
},
},
AppLovinMax: models.AppLovinMax{
@@ -1288,7 +1655,7 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
matchedSlot: "/Test_Adunit1234@Div1@200x300",
matchedPattern: "",
isRegexSlot: false,
- params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@DIV1@200x300","wrapper":{"version":0,"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}],"floors":[1.5,1.2,2.2],"sendburl":true}`),
+ params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@DIV1@200x300","wrapper":{"version":1,"profile":123},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}],"floors":[1.5,1.2,2.2],"sendburl":true}`),
wantErr: false,
},
},
@@ -1437,3 +1804,196 @@ func TestGetMatchingSlotAndPattern(t *testing.T) {
})
}
}
+
+func TestGetPubMaticPublisherID(t *testing.T) {
+ type args struct {
+ rctx models.RequestCtx
+ partnerID int
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "pubmatic partner",
+ args: args{
+ partnerID: 789,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 789: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.PubID: "5890",
+ },
+ },
+ PubID: 5890,
+ PubIDStr: "5890",
+ },
+ },
+ want: "5890",
+ },
+ {
+ name: "pubmatic secondary partner",
+ args: args{
+ partnerID: 123,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 123: {
+ models.PREBID_PARTNER_NAME: "pubmatic2",
+ models.BidderCode: "pubmatic2",
+ models.KEY_PUBLISHER_ID: "301",
+ models.PubID: "5890",
+ },
+ },
+ PubID: 5890,
+ PubIDStr: "5890",
+ },
+ },
+ want: "301",
+ },
+ {
+ name: "pubmatic alias partner",
+ args: args{
+ partnerID: 456,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 456: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubm_alias",
+ models.PubID: "301",
+ models.IsAlias: "1",
+ },
+ },
+ PubID: 5890,
+ PubIDStr: "5890",
+ },
+ },
+ want: "301",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := getPubMaticPublisherID(tt.args.rctx, tt.args.partnerID)
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
+
+func TestGetPubMaticWrapperExt(t *testing.T) {
+ type args struct {
+ rctx models.RequestCtx
+ partnerID int
+ }
+ tests := []struct {
+ name string
+ args args
+ want json.RawMessage
+ }{
+ {
+ name: "pubmatic partner",
+ args: args{
+ partnerID: 789,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 789: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.PubID: "5890",
+ },
+ },
+ DisplayID: 1,
+ ProfileID: 1234,
+ PubID: 5890,
+ },
+ },
+ want: json.RawMessage(`{"version":1,"profile":1234}`),
+ },
+ {
+ name: "pubmatic secondary partner",
+ args: args{
+ partnerID: 123,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 123: {
+ models.PREBID_PARTNER_NAME: "pubmatic2",
+ models.BidderCode: "pubmatic2",
+ models.KEY_PROFILE_ID: "222",
+ },
+ },
+ DisplayID: 1,
+ ProfileID: 1234,
+ },
+ },
+ want: json.RawMessage(`{"profile":222}`),
+ },
+ {
+ name: "pubmatic alias partner with pubID different from incoming request pubID",
+ args: args{
+ partnerID: 456,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 456: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubm_alias",
+ models.PubID: "301",
+ models.IsAlias: "1",
+ },
+ },
+ DisplayID: 1,
+ ProfileID: 1234,
+ PubID: 5890,
+ PubIDStr: "5890",
+ },
+ },
+ want: nil,
+ },
+ {
+ name: "pubmatic alias partner with pubID same as incoming request pubID",
+ args: args{
+ partnerID: 456,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 456: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubm_alias",
+ models.PubID: "5890",
+ models.IsAlias: "1",
+ },
+ },
+ DisplayID: 1,
+ ProfileID: 1234,
+ PubID: 5890,
+ PubIDStr: "5890",
+ },
+ },
+ want: json.RawMessage(`{"version":1,"profile":1234}`),
+ },
+ {
+ name: "pubmatic alias partner with no pubID in partner config",
+ args: args{
+ partnerID: 456,
+ rctx: models.RequestCtx{
+ PartnerConfigMap: map[int]map[string]string{
+ 456: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubm_alias",
+ models.IsAlias: "1",
+ },
+ },
+ DisplayID: 1,
+ ProfileID: 1234,
+ PubID: 5890,
+ PubIDStr: "5890",
+ },
+ },
+ want: json.RawMessage(`{"version":1,"profile":1234}`),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := getPubMaticWrapperExt(tt.args.rctx, tt.args.partnerID)
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/cache/gocache/adpod_config_test.go b/modules/pubmatic/openwrap/cache/gocache/adpod_config_test.go
index 28a5991a44f..0763a8f05a4 100644
--- a/modules/pubmatic/openwrap/cache/gocache/adpod_config_test.go
+++ b/modules/pubmatic/openwrap/cache/gocache/adpod_config_test.go
@@ -63,7 +63,7 @@ func TestCachePopulateCacheWithAdpodConfig(t *testing.T) {
MinDuration: 10,
MaxDuration: 20,
PodDur: 60,
- Maxseq: 3,
+ MaxSeq: 3,
},
},
}, nil)
@@ -77,7 +77,7 @@ func TestCachePopulateCacheWithAdpodConfig(t *testing.T) {
MinDuration: 10,
MaxDuration: 20,
PodDur: 60,
- Maxseq: 3,
+ MaxSeq: 3,
},
},
},
@@ -150,7 +150,7 @@ func TestCacheGetAdpodConfigs(t *testing.T) {
MinDuration: 10,
MaxDuration: 20,
PodDur: 60,
- Maxseq: 3,
+ MaxSeq: 3,
},
},
}, nil)
@@ -162,7 +162,7 @@ func TestCacheGetAdpodConfigs(t *testing.T) {
MinDuration: 10,
MaxDuration: 20,
PodDur: 60,
- Maxseq: 3,
+ MaxSeq: 3,
},
},
},
@@ -214,7 +214,7 @@ func TestCacheGetAdpodConfigs(t *testing.T) {
MinDuration: 30,
MaxDuration: 60,
PodDur: 120,
- Maxseq: 4,
+ MaxSeq: 4,
},
},
}
@@ -227,7 +227,7 @@ func TestCacheGetAdpodConfigs(t *testing.T) {
MinDuration: 30,
MaxDuration: 60,
PodDur: 120,
- Maxseq: 4,
+ MaxSeq: 4,
},
},
},
diff --git a/modules/pubmatic/openwrap/config/config.go b/modules/pubmatic/openwrap/config/config.go
index 0a634af2f62..112a50a2770 100755
--- a/modules/pubmatic/openwrap/config/config.go
+++ b/modules/pubmatic/openwrap/config/config.go
@@ -101,7 +101,6 @@ type PixelView struct {
type FeatureToggle struct {
VASTUnwrapPercent int
- VASTUnwrapStatsPercent int
AnalyticsThrottlingPercentage string
}
diff --git a/modules/pubmatic/openwrap/database/mysql/adpod_config_test.go b/modules/pubmatic/openwrap/database/mysql/adpod_config_test.go
index 3feb5d4d2d3..8757acc794c 100644
--- a/modules/pubmatic/openwrap/database/mysql/adpod_config_test.go
+++ b/modules/pubmatic/openwrap/database/mysql/adpod_config_test.go
@@ -65,7 +65,7 @@ func TestMySqlDBGetAdpodConfigs(t *testing.T) {
MaxDuration: 60,
MinDuration: 1,
PodDur: 180,
- Maxseq: 5,
+ MaxSeq: 5,
},
},
},
@@ -105,7 +105,7 @@ func TestMySqlDBGetAdpodConfigs(t *testing.T) {
MaxDuration: 60,
MinDuration: 1,
PodDur: 180,
- Maxseq: 5,
+ MaxSeq: 5,
},
},
},
@@ -143,8 +143,8 @@ func TestMySqlDBGetAdpodConfigs(t *testing.T) {
Dynamic: []adpodconfig.Dynamic{
{
PodDur: 600,
- Maxseq: 5,
- Rqddurs: []int{6, 60, 120, 600},
+ MaxSeq: 5,
+ RqdDurs: []int64{6, 60, 120, 600},
},
},
},
@@ -188,7 +188,7 @@ func TestMySqlDBGetAdpodConfigs(t *testing.T) {
MaxDuration: 60,
MinDuration: 1,
PodDur: 180,
- Maxseq: 5,
+ MaxSeq: 5,
},
},
Structured: []adpodconfig.Structured{
@@ -205,8 +205,8 @@ func TestMySqlDBGetAdpodConfigs(t *testing.T) {
{
MaxDuration: 20,
MinDuration: 5,
- Maxseq: ptrutil.ToPtr(3),
- PodDur: ptrutil.ToPtr(60),
+ MaxSeq: ptrutil.ToPtr(int64(3)),
+ PodDur: ptrutil.ToPtr(int64(60)),
},
},
},
diff --git a/modules/pubmatic/openwrap/device.go b/modules/pubmatic/openwrap/device.go
index 899a0c00d78..82dbd9acf2b 100644
--- a/modules/pubmatic/openwrap/device.go
+++ b/modules/pubmatic/openwrap/device.go
@@ -54,7 +54,7 @@ func updateDeviceIFADetails(dvc *models.DeviceCtx) {
} else {
deviceExt.DeleteIFAType()
}
- } else if extSessionID != "" {
+ } else if extSessionID != "" && dvc.DeviceIFA == "" {
dvc.DeviceIFA = extSessionID
dvc.IFATypeID = ptrutil.ToPtr(models.DeviceIfaTypeIdSessionId)
deviceExt.SetIFAType(models.DeviceIFATypeSESSIONID)
diff --git a/modules/pubmatic/openwrap/device_test.go b/modules/pubmatic/openwrap/device_test.go
index 6fd88da9b6d..c9b48999951 100644
--- a/modules/pubmatic/openwrap/device_test.go
+++ b/modules/pubmatic/openwrap/device_test.go
@@ -390,6 +390,27 @@ func TestUpdateDeviceIFADetails(t *testing.T) {
}(),
},
},
+ want: &models.DeviceCtx{
+ DeviceIFA: `existing_ifa_id`,
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetSessionID(`sample_session_id`)
+ return deviceExt
+ }(),
+ },
+ },
+ {
+ name: `ifa_type_missing_ifa_empty_session_id_present`,
+ args: args{
+ dvc: &models.DeviceCtx{
+ DeviceIFA: "",
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetSessionID(`sample_session_id`)
+ return deviceExt
+ }(),
+ },
+ },
want: &models.DeviceCtx{
IFATypeID: ptrutil.ToPtr(9),
DeviceIFA: `sample_session_id`,
@@ -397,11 +418,33 @@ func TestUpdateDeviceIFADetails(t *testing.T) {
deviceExt := &models.ExtDevice{}
deviceExt.SetIFAType(models.DeviceIFATypeSESSIONID)
deviceExt.SetSessionID(`sample_session_id`)
-
return deviceExt
}(),
},
},
+ {
+ name: `ifa_type_missing_ifa_not_present_session_id_present`,
+ args: args{
+ dvc: &models.DeviceCtx{
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetSessionID(`sample_session_id`)
+ return deviceExt
+ }(),
+ },
+ },
+ want: &models.DeviceCtx{
+ IFATypeID: ptrutil.ToPtr(9),
+ DeviceIFA: `sample_session_id`,
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetIFAType(models.DeviceIFATypeSESSIONID)
+ deviceExt.SetSessionID(`sample_session_id`)
+ return deviceExt
+ }(),
+ },
+ },
+
// TODO: Add test cases.
}
for _, tt := range tests {
diff --git a/modules/pubmatic/openwrap/entrypointhook.go b/modules/pubmatic/openwrap/entrypointhook.go
index 95b069bf4cf..d5b7eb6c2b0 100644
--- a/modules/pubmatic/openwrap/entrypointhook.go
+++ b/modules/pubmatic/openwrap/entrypointhook.go
@@ -112,6 +112,7 @@ func (m OpenWrap) handleEntrypointHook(
LoggerImpressionID: requestExtWrapper.LoggerImpressionID,
ClientConfigFlag: requestExtWrapper.ClientConfigFlag,
SSAI: requestExtWrapper.SSAI,
+ AdruleFlag: requestExtWrapper.Video.AdruleFlag,
IP: models.GetIP(payload.Request),
IsCTVRequest: models.IsCTVAPIRequest(payload.Request.URL.Path),
TrackerEndpoint: m.cfg.Tracker.Endpoint,
@@ -133,12 +134,15 @@ func (m OpenWrap) handleEntrypointHook(
WakandaDebug: &wakanda.Debug{
Config: m.cfg.Wakanda,
},
- SendBurl: endpoint == models.EndpointAppLovinMax || getSendBurl(payload.Body),
+ SendBurl: endpoint == models.EndpointAppLovinMax || getSendBurl(payload.Body),
+ ImpCountingMethodEnabledBidders: make(map[string]struct{}),
}
- // SSAuction will be always 1 for CTV request
if rCtx.IsCTVRequest {
+ // SSAuction will be always 1 for CTV request
rCtx.SSAuction = 1
+
+ rCtx.ImpAdPodConfig = make(map[string][]models.PodConfig)
}
// 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 57b35a17ce1..e2b209a8133 100644
--- a/modules/pubmatic/openwrap/entrypointhook_test.go
+++ b/modules/pubmatic/openwrap/entrypointhook_test.go
@@ -126,17 +126,18 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
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: "5890",
- Endpoint: models.EndpointV25,
- MetricsEngine: mockEngine,
- SeatNonBids: make(map[string][]openrtb_ext.NonBid),
- Method: "POST",
- WakandaDebug: &wakanda.Debug{},
+ 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: "5890",
+ Endpoint: models.EndpointV25,
+ MetricsEngine: mockEngine,
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ Method: "POST",
+ WakandaDebug: &wakanda.Debug{},
+ ImpCountingMethodEnabledBidders: make(map[string]struct{}),
},
},
},
@@ -173,29 +174,30 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
want: hookstage.HookResult[hookstage.EntrypointPayload]{
ModuleContext: hookstage.ModuleContext{
"rctx": models.RequestCtx{
- PubIDStr: "5890",
- PubID: 5890,
- ProfileID: 5890,
- DisplayID: 1,
- DisplayVersionID: 1,
- SSAuction: -1,
- Debug: true,
- UA: "go-test",
- IP: "127.0.0.1",
- IsCTVRequest: false,
- TrackerEndpoint: "t.pubmatic.com",
- VideoErrorTrackerEndpoint: "t.pubmatic.com/error",
- LoggerImpressionID: "4df09505-d0b2-4d70-94d9-dc41e8e777f7",
- Aliases: make(map[string]string),
- ImpBidCtx: make(map[string]models.ImpCtx),
- PrebidBidderCode: make(map[string]string),
- BidderResponseTimeMillis: make(map[string]int),
- ProfileIDStr: "5890",
- Endpoint: models.EndpointV25,
- MetricsEngine: mockEngine,
- SeatNonBids: make(map[string][]openrtb_ext.NonBid),
- Method: "POST",
- WakandaDebug: &wakanda.Debug{},
+ PubIDStr: "5890",
+ PubID: 5890,
+ ProfileID: 5890,
+ DisplayID: 1,
+ DisplayVersionID: 1,
+ SSAuction: -1,
+ Debug: true,
+ UA: "go-test",
+ IP: "127.0.0.1",
+ IsCTVRequest: false,
+ TrackerEndpoint: "t.pubmatic.com",
+ VideoErrorTrackerEndpoint: "t.pubmatic.com/error",
+ LoggerImpressionID: "4df09505-d0b2-4d70-94d9-dc41e8e777f7",
+ Aliases: make(map[string]string),
+ ImpBidCtx: make(map[string]models.ImpCtx),
+ PrebidBidderCode: make(map[string]string),
+ BidderResponseTimeMillis: make(map[string]int),
+ ProfileIDStr: "5890",
+ Endpoint: models.EndpointV25,
+ MetricsEngine: mockEngine,
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ Method: "POST",
+ WakandaDebug: &wakanda.Debug{},
+ ImpCountingMethodEnabledBidders: make(map[string]struct{}),
},
},
},
@@ -276,17 +278,18 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
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: "43563",
- Endpoint: models.EndpointWebS2S,
- MetricsEngine: mockEngine,
- SeatNonBids: make(map[string][]openrtb_ext.NonBid),
- Method: "POST",
- WakandaDebug: &wakanda.Debug{},
+ 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: "43563",
+ Endpoint: models.EndpointWebS2S,
+ MetricsEngine: mockEngine,
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ Method: "POST",
+ WakandaDebug: &wakanda.Debug{},
+ ImpCountingMethodEnabledBidders: make(map[string]struct{}),
},
},
},
@@ -337,17 +340,18 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
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: "43563",
- Endpoint: models.EndpointWebS2S,
- MetricsEngine: mockEngine,
- SeatNonBids: make(map[string][]openrtb_ext.NonBid),
- Method: "POST",
- WakandaDebug: &wakanda.Debug{},
+ 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: "43563",
+ Endpoint: models.EndpointWebS2S,
+ MetricsEngine: mockEngine,
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ Method: "POST",
+ WakandaDebug: &wakanda.Debug{},
+ ImpCountingMethodEnabledBidders: make(map[string]struct{}),
},
},
},
@@ -500,17 +504,18 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
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: "5890",
- Endpoint: models.EndpointV25,
- MetricsEngine: mockEngine,
- SeatNonBids: make(map[string][]openrtb_ext.NonBid),
- Method: "POST",
- WakandaDebug: &wakanda.Debug{},
+ 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: "5890",
+ Endpoint: models.EndpointV25,
+ MetricsEngine: mockEngine,
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ Method: "POST",
+ WakandaDebug: &wakanda.Debug{},
+ ImpCountingMethodEnabledBidders: make(map[string]struct{}),
},
},
},
@@ -593,7 +598,8 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
},
},
},
- SendBurl: true,
+ SendBurl: true,
+ ImpCountingMethodEnabledBidders: make(map[string]struct{}),
},
},
},
diff --git a/modules/pubmatic/openwrap/hook_raw_bidder_response.go b/modules/pubmatic/openwrap/hook_raw_bidder_response.go
index 8bdc4f06b00..c7674f0c436 100644
--- a/modules/pubmatic/openwrap/hook_raw_bidder_response.go
+++ b/modules/pubmatic/openwrap/hook_raw_bidder_response.go
@@ -2,14 +2,20 @@ package openwrap
import (
"fmt"
- "sync"
"github.com/prebid/prebid-server/v2/adapters"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/nbr"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/hooks/hookstage"
)
+type BidUnwrapInfo struct {
+ bid *adapters.TypedBid
+ unwrapStatus string
+}
+
func (m OpenWrap) handleRawBidderResponseHook(
miCtx hookstage.ModuleInvocationContext,
payload hookstage.RawBidderResponsePayload,
@@ -20,41 +26,61 @@ func (m OpenWrap) handleRawBidderResponseHook(
return result, nil
}
- if vastRequestContext.VastUnwrapEnabled {
- // Do Unwrap and Update Adm
- wg := new(sync.WaitGroup)
- for _, bid := range payload.Bids {
- if string(bid.BidType) == models.MediaTypeVideo {
- wg.Add(1)
- go func(bid *adapters.TypedBid) {
- defer wg.Done()
- m.unwrap.Unwrap(miCtx.AccountID, payload.Bidder, bid, vastRequestContext.UA, vastRequestContext.IP, vastRequestContext.VastUnwrapStatsEnabled)
- }(bid)
- }
- }
- wg.Wait()
- changeSet := hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
- changeSet.RawBidderResponse().Bids().Update(payload.Bids)
- result.ChangeSet = changeSet
- } else {
- vastRequestContext.VastUnwrapStatsEnabled = GetRandomNumberIn1To100() <= m.cfg.Features.VASTUnwrapStatsPercent
- if vastRequestContext.VastUnwrapStatsEnabled {
- // Do Unwrap and Collect stats only
- for _, bid := range payload.Bids {
- if string(bid.BidType) == models.MediaTypeVideo {
- go func(bid *adapters.TypedBid) {
- m.unwrap.Unwrap(miCtx.AccountID, payload.Bidder, bid, vastRequestContext.UA, vastRequestContext.IP, vastRequestContext.VastUnwrapStatsEnabled)
- }(bid)
- }
- }
+ if !vastRequestContext.VastUnwrapEnabled {
+ return result, nil
+ }
+
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ unwrappedBids := make([]*adapters.TypedBid, 0, len(payload.BidderResponse.Bids))
+ unwrappedBidsChan := make(chan BidUnwrapInfo, len(payload.BidderResponse.Bids))
+ defer close(unwrappedBidsChan)
+
+ unwrappedBidsCnt := 0
+ // send bids for unwrap
+ for _, bid := range payload.BidderResponse.Bids {
+ if !isEligibleForUnwrap(bid) {
+ continue
}
+ unwrappedBidsCnt++
+ go func(bid adapters.TypedBid) {
+ unwrapStatus := m.unwrap.Unwrap(&bid, miCtx.AccountID, payload.Bidder, vastRequestContext.UA, vastRequestContext.IP)
+ unwrappedBidsChan <- BidUnwrapInfo{&bid, unwrapStatus}
+ }(*bid)
}
- if vastRequestContext.VastUnwrapEnabled || vastRequestContext.VastUnwrapStatsEnabled {
- result.DebugMessages = append(result.DebugMessages,
- fmt.Sprintf("For pubid:[%d] VastUnwrapEnabled: [%v] VastUnwrapStatsEnabled:[%v] ",
- vastRequestContext.PubID, vastRequestContext.VastUnwrapEnabled, vastRequestContext.VastUnwrapStatsEnabled))
+ // collect bids after unwrap
+ for i := 0; i < unwrappedBidsCnt; i++ {
+ unwrappedBid := <-unwrappedBidsChan
+ if !rejectBid(unwrappedBid.unwrapStatus) {
+ unwrappedBids = append(unwrappedBids, unwrappedBid.bid)
+ continue
+ }
+ seatNonBid.AddBid(openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: unwrappedBid.bid.Bid,
+ NonBidReason: int(nbr.LossBidLostInVastUnwrap),
+ DealPriority: unwrappedBid.bid.DealPriority,
+ BidMeta: unwrappedBid.bid.BidMeta,
+ BidType: unwrappedBid.bid.BidType,
+ BidVideo: unwrappedBid.bid.BidVideo,
+ OriginalBidCur: payload.BidderResponse.Currency,
+ }), payload.Bidder,
+ )
}
+ changeSet := hookstage.ChangeSet[hookstage.RawBidderResponsePayload]{}
+ changeSet.RawBidderResponse().Bids().Update(unwrappedBids)
+ result.ChangeSet = changeSet
+ result.SeatNonBid = seatNonBid
+ result.DebugMessages = append(result.DebugMessages,
+ fmt.Sprintf("For pubid:[%d] VastUnwrapEnabled: [%v]", vastRequestContext.PubID, vastRequestContext.VastUnwrapEnabled))
+
return result, nil
}
+
+func isEligibleForUnwrap(bid *adapters.TypedBid) bool {
+ return bid != nil && bid.BidType == openrtb_ext.BidTypeVideo && bid.Bid != nil && bid.Bid.AdM != ""
+}
+
+func rejectBid(bidUnwrapStatus string) bool {
+ return bidUnwrapStatus == models.UnwrapEmptyVASTStatus || bidUnwrapStatus == models.UnwrapInvalidVASTStatus
+}
diff --git a/modules/pubmatic/openwrap/hook_raw_bidder_response_test.go b/modules/pubmatic/openwrap/hook_raw_bidder_response_test.go
index 07130c3aed3..22bbf71b498 100644
--- a/modules/pubmatic/openwrap/hook_raw_bidder_response_test.go
+++ b/modules/pubmatic/openwrap/hook_raw_bidder_response_test.go
@@ -3,7 +3,6 @@ package openwrap
import (
"fmt"
"net/http"
-
"testing"
unWrapCfg "git.pubmatic.com/vastunwrap/config"
@@ -14,7 +13,9 @@ import (
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/config"
mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/nbr"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/unwrap"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/stretchr/testify/assert"
)
@@ -23,7 +24,6 @@ var invalidVastXMLAdM = "PubMaticAcudeo CompatibleVAST 2.0 Instream Test 1VAST 2.0 Instream Test 1https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&er=[ERRORCODE]https://track.dsptracker.com?p=1234&er=[ERRORCODE]https://aktrack.pubmatic.com/AdServer/AdDisplayTrackerServlet?operId=1&pubId=64195&siteId=47105&adId=1405154&adType=13&adServerId=243&kefact=1.000000&kaxefact=1.000000&kadNetFrequecy=0&kadwidth=0&kadheight=0&kadsizeid=97&kltstamp=1536933242&indirectAdId=0&adServerOptimizerId=2&ranreq=0.05969169352174375&kpbmtpfact=11.000000&dcId=1&tldId=0&passback=0&svr=ktk57&ekefact=er2bW2sDAwCra06ACbsIQySn5nqBtYsTl8fy5lupAexh37D_&ekaxefact=er2bW4EDAwB_LQpJJ23Fq0DcNC-NSAFXdpSQC8XBk_S33_Fa&ekpbmtpfact=er2bW5MDAwDJHdBnLBt5IrRuh7x0oqp_tjIALv_VvSQDAl6R&crID=m:1_x:3_y:3_p:11_va:3&lpu=ae.com&ucrid=678722001014421372&campaignId=16774&creativeId=0&pctr=0.000000&wDSPByrId=511&wDspId=27&wbId=0&wrId=0&wAdvID=3170&isRTB=1&rtbId=EBCA079F-8D7C-45B8-B733-92951F670AA1&imprId=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&oid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&pageURL=http%253A%252F%252Fowsdk-stagingams.pubmatic.com%253A8443%252Fvast-validator%252F%2523&sec=1&pmc=1https://DspImpressionTracker.com/https://mytracking.com/linear/closehttps://mytracking.com/linear/skiphttps://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=1https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=2https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=3https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=4https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=5https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=600:00:04https://www.automationtester.inhttps://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=99https://stagingams.pubmatic.com:8443/openwrap/media/pubmatic.mp4https://stagingams.pubmatic.com:8443/openwrap/media/pubmatic.mp4https://stagingams.pubmatic.com:8443/openwrap/media/mp4-sample-3.mp4"
func TestHandleRawBidderResponseHook(t *testing.T) {
-
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockMetricsEngine := mock_metrics.NewMockMetricsEngine(ctrl)
@@ -33,24 +33,21 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
payload hookstage.RawBidderResponsePayload
moduleInvocationCtx hookstage.ModuleInvocationContext
isAdmUpdated bool
- randomNumber int
}
tests := []struct {
- name string
- args args
- wantResult hookstage.HookResult[hookstage.RawBidderResponsePayload]
- setup func()
- wantErr bool
- mockHandler http.HandlerFunc
+ name string
+ args args
+ wantResult hookstage.HookResult[hookstage.RawBidderResponsePayload]
+ setup func()
+ wantSeatNonBid openrtb_ext.NonBidCollection
+ mockHandler http.HandlerFunc
}{
-
{
name: "Empty Request Context",
args: args{
module: OpenWrap{},
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{DebugMessages: []string{"error: request-ctx not found in handleRawBidderResponseHook()"}},
- wantErr: false,
},
{
name: "Set Vast Unwrapper to false in request context with type video",
@@ -64,33 +61,30 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
metricEngine: mockMetricsEngine,
},
payload: hookstage.RawBidderResponsePayload{
- Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{
- ID: "Bid-123",
- ImpID: fmt.Sprintf("div-adunit-%d", 123),
- Price: 2.1,
- AdM: "This is an Ad
",
- CrID: "Cr-234",
- W: 100,
- H: 50,
- },
- BidType: "video",
- }}},
+ BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-123",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: "This is an Ad
",
+ CrID: "Cr-234",
+ W: 100,
+ H: 50,
+ },
+ BidType: "video",
+ }}}},
moduleInvocationCtx: hookstage.ModuleInvocationContext{ModuleContext: hookstage.ModuleContext{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: false}}},
- randomNumber: 1,
},
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: OpenWrap{
cfg: config.Config{
- Features: config.FeatureToggle{
- VASTUnwrapStatsPercent: 2,
- },
+ Features: config.FeatureToggle{},
VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
MaxWrapperSupport: 5,
StatConfig: unWrapCfg.StatConfig{Endpoint: "http://10.172.141.13:8080", PublishInterval: 1},
@@ -99,23 +93,23 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
metricEngine: mockMetricsEngine,
},
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",
- }},
+ BidderResponse: &adapters.BidderResponse{
+ 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{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: false}}},
- randomNumber: 1,
},
mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Add("unwrap-status", "0")
@@ -125,12 +119,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}),
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0")
- mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1")
- mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
- mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any())
},
- wantErr: false,
},
{
name: "Set Vast Unwrapper to true in request context with invalid vast xml",
@@ -138,8 +127,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
module: OpenWrap{
cfg: config.Config{
Features: config.FeatureToggle{
- VASTUnwrapStatsPercent: 2,
- VASTUnwrapPercent: 50,
+ VASTUnwrapPercent: 50,
},
VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
MaxWrapperSupport: 5,
@@ -149,18 +137,20 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
metricEngine: mockMetricsEngine,
},
payload: hookstage.RawBidderResponsePayload{
- Bids: []*adapters.TypedBid{
- {
- Bid: &openrtb2.Bid{
- ID: "Bid-123",
- ImpID: fmt.Sprintf("div-adunit-%d", 123),
- Price: 2.1,
- AdM: invalidVastXMLAdM,
- CrID: "Cr-234",
- W: 100,
- H: 50,
+ BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-123",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: invalidVastXMLAdM,
+ CrID: "Cr-234",
+ W: 100,
+ H: 50,
+ },
+ BidType: "video",
},
- BidType: "video",
},
},
Bidder: "pubmatic",
@@ -176,9 +166,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "1")
mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
},
- wantErr: true,
},
-
{
name: "Set Vast Unwrapper to true in request context with type video",
mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
@@ -191,8 +179,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
module: OpenWrap{
cfg: config.Config{
Features: config.FeatureToggle{
- VASTUnwrapStatsPercent: 2,
- VASTUnwrapPercent: 50,
+ VASTUnwrapPercent: 50,
},
VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
MaxWrapperSupport: 5,
@@ -202,34 +189,34 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
metricEngine: mockMetricsEngine,
},
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,
+ BidderResponse: &adapters.BidderResponse{
+ 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",
},
- BidType: "video",
},
},
Bidder: "pubmatic",
},
moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: true}}},
-
- isAdmUpdated: true,
+ isAdmUpdated: true,
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0")
+ mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1")
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
+ mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any())
},
- wantErr: false,
},
{
name: "Set Vast Unwrapper to true in request context for multiple bids with type video",
@@ -237,8 +224,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
module: OpenWrap{
cfg: config.Config{
Features: config.FeatureToggle{
- VASTUnwrapStatsPercent: 2,
- VASTUnwrapPercent: 50,
+ VASTUnwrapPercent: 50,
},
VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
MaxWrapperSupport: 5,
@@ -248,36 +234,37 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
metricEngine: mockMetricsEngine,
},
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",
- },
- {
- Bid: &openrtb2.Bid{
- ID: "Bid-456",
- ImpID: fmt.Sprintf("div-adunit-%d", 123),
- Price: 2.1,
- AdM: vastXMLAdM,
- CrID: "Cr-789",
- W: 100,
- H: 50,
+ BidderResponse: &adapters.BidderResponse{
+ 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",
},
- BidType: "video",
- }},
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-456",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: vastXMLAdM,
+ CrID: "Cr-789",
+ W: 100,
+ H: 50,
+ },
+ BidType: "video",
+ }},
+ },
Bidder: "pubmatic",
},
moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: true}}},
isAdmUpdated: true,
- randomNumber: 10,
},
mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Add("unwrap-status", "0")
@@ -287,22 +274,19 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}),
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0").Times(2)
+ mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1").Times(2)
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any()).Times(2)
+ mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any()).Times(2)
},
- wantErr: false,
},
-
{
name: "Set Vast Unwrapper to true in request context for multiple bids with different type",
args: args{
module: OpenWrap{
cfg: config.Config{
Features: config.FeatureToggle{
- VASTUnwrapStatsPercent: 2,
- VASTUnwrapPercent: 50,
+ VASTUnwrapPercent: 50,
},
VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
MaxWrapperSupport: 5,
@@ -312,36 +296,37 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
metricEngine: mockMetricsEngine,
},
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,
+ BidderResponse: &adapters.BidderResponse{
+ 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",
},
- BidType: "video",
- },
- {
- Bid: &openrtb2.Bid{
- ID: "Bid-456",
- ImpID: fmt.Sprintf("div-adunit-%d", 123),
- Price: 2.1,
- AdM: "This is banner creative",
- CrID: "Cr-789",
- W: 100,
- H: 50,
- },
- BidType: "banner",
- }},
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-456",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: "This is banner creative",
+ CrID: "Cr-789",
+ W: 100,
+ H: 50,
+ },
+ BidType: "banner",
+ }},
+ },
Bidder: "pubmatic",
},
moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: true}}},
-
- isAdmUpdated: true,
+ isAdmUpdated: true,
},
mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Add("unwrap-status", "0")
@@ -351,12 +336,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}),
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "0", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0")
+ mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "0")
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
+ mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "0", gomock.Any())
},
- wantErr: false,
},
{
name: "Set Vast Unwrapper to true in request context with type video and source owsdk",
@@ -364,8 +348,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
module: OpenWrap{
cfg: config.Config{
Features: config.FeatureToggle{
- VASTUnwrapStatsPercent: 2,
- VASTUnwrapPercent: 50,
+ VASTUnwrapPercent: 50,
},
VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
MaxWrapperSupport: 5,
@@ -375,25 +358,26 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
metricEngine: mockMetricsEngine,
},
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,
+ BidderResponse: &adapters.BidderResponse{
+ 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",
},
- BidType: "video",
},
},
Bidder: "pubmatic",
},
moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: true}}},
-
- isAdmUpdated: true,
+ isAdmUpdated: true,
},
mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Add("unwrap-status", "0")
@@ -403,12 +387,141 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}),
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
- mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1").AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
- mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0")
+ mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1")
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
+ mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any())
+ },
+ },
+ {
+ name: "bid with InvalidVAST should be discarded and should be present in seatNonBid",
+ args: args{
+ module: OpenWrap{
+ cfg: config.Config{
+ Features: config.FeatureToggle{
+ VASTUnwrapPercent: 50,
+ },
+ VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
+ MaxWrapperSupport: 5,
+ StatConfig: unWrapCfg.StatConfig{Endpoint: "http://10.172.141.13:8080", PublishInterval: 1},
+ APPConfig: unWrapCfg.AppConfig{UnwrapDefaultTimeout: 1500},
+ }},
+ metricEngine: mockMetricsEngine,
+ },
+ payload: hookstage.RawBidderResponsePayload{
+ BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-123",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: invalidVastXMLAdM,
+ CrID: "Cr-234",
+ W: 100,
+ H: 50,
+ },
+ BidType: "video",
+ },
+ },
+ },
+ Bidder: "pubmatic",
+ },
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: true}}},
+ },
+ mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
+ w.Header().Add("unwrap-status", models.UnwrapInvalidVASTStatus)
+ w.WriteHeader(http.StatusNoContent)
+ }),
+ wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
+ setup: func() {
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", models.UnwrapInvalidVASTStatus)
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
+ },
+ wantSeatNonBid: func() openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ seatNonBid.AddBid(openrtb_ext.NonBid{
+ ImpId: fmt.Sprintf("div-adunit-%d", 123),
+ StatusCode: int(nbr.LossBidLostInVastUnwrap),
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
+ Price: 2.1,
+ ID: "Bid-123",
+ W: 100,
+ H: 50,
+ Type: openrtb_ext.BidTypeVideo,
+ },
+ },
+ },
+ }, "pubmatic")
+ return seatNonBid
+ }(),
+ },
+ {
+ name: "bid with EmptyVAST should be discarded and should be present in seatNonBid",
+ args: args{
+ module: OpenWrap{
+ cfg: config.Config{
+ Features: config.FeatureToggle{
+ VASTUnwrapPercent: 50,
+ },
+ VastUnwrapCfg: unWrapCfg.VastUnWrapCfg{
+ MaxWrapperSupport: 5,
+ StatConfig: unWrapCfg.StatConfig{Endpoint: "http://10.172.141.13:8080", PublishInterval: 1},
+ APPConfig: unWrapCfg.AppConfig{UnwrapDefaultTimeout: 1500},
+ }},
+ metricEngine: mockMetricsEngine,
+ },
+ payload: hookstage.RawBidderResponsePayload{
+ BidderResponse: &adapters.BidderResponse{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-123",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: invalidVastXMLAdM,
+ CrID: "Cr-234",
+ W: 100,
+ H: 50,
+ },
+ BidType: "video",
+ },
+ },
+ },
+ Bidder: "pubmatic",
+ },
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{models.RequestContext: models.RequestCtx{VastUnwrapEnabled: true}}},
+ },
+ mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
+ w.Header().Add("unwrap-status", models.UnwrapEmptyVASTStatus)
+ w.WriteHeader(http.StatusNoContent)
+ }),
+ wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
+ setup: func() {
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", models.UnwrapEmptyVASTStatus)
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
},
- wantErr: false,
+ wantSeatNonBid: func() openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ seatNonBid.AddBid(openrtb_ext.NonBid{
+ ImpId: fmt.Sprintf("div-adunit-%d", 123),
+ StatusCode: int(nbr.LossBidLostInVastUnwrap),
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
+ Price: 2.1,
+ ID: "Bid-123",
+ W: 100,
+ H: 50,
+ Type: openrtb_ext.BidTypeVideo,
+ },
+ },
+ },
+ }, "pubmatic")
+ return seatNonBid
+ }(),
},
}
for _, tt := range tests {
@@ -417,19 +530,56 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
tt.setup()
}
- GetRandomNumberIn1To100 = func() int {
- return tt.args.randomNumber
- }
-
m := tt.args.module
m.unwrap = unwrap.NewUnwrap("http://localhost:8001/unwrap", 200, tt.mockHandler, m.metricEngine)
- _, err := m.handleRawBidderResponseHook(tt.args.moduleInvocationCtx, tt.args.payload)
- if !assert.NoError(t, err, tt.wantErr) {
- return
- }
+ hookResult, _ := m.handleRawBidderResponseHook(tt.args.moduleInvocationCtx, tt.args.payload)
if tt.args.moduleInvocationCtx.ModuleContext != nil && tt.args.isAdmUpdated {
- assert.Equal(t, inlineXMLAdM, tt.args.payload.Bids[0].Bid.AdM, "AdM is not updated correctly after executing RawBidderResponse hook.")
+ assert.Equal(t, inlineXMLAdM, tt.args.payload.BidderResponse.Bids[0].Bid.AdM, "AdM is not updated correctly after executing RawBidderResponse hook.")
}
+ assert.Equal(t, tt.wantSeatNonBid, hookResult.SeatNonBid, "mismatched seatNonBids")
+ })
+ }
+}
+
+func TestIsEligibleForUnwrap(t *testing.T) {
+ type args struct {
+ bid *adapters.TypedBid
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {
+ name: "Bid is nil",
+ args: args{bid: nil},
+ want: false,
+ },
+ {
+ name: "Bid.Bid is nil",
+ args: args{bid: &adapters.TypedBid{Bid: nil}},
+ want: false,
+ },
+ {
+ name: "AdM is empty",
+ args: args{bid: &adapters.TypedBid{Bid: &openrtb2.Bid{AdM: ""}}},
+ want: false,
+ },
+ {
+ name: "BidType is not video",
+ args: args{bid: &adapters.TypedBid{Bid: &openrtb2.Bid{AdM: "some_adm"}, BidType: openrtb_ext.BidTypeBanner}},
+ want: false,
+ },
+ {
+ name: "Bid is eligible for unwrap",
+ args: args{bid: &adapters.TypedBid{Bid: &openrtb2.Bid{AdM: "some_adm"}, BidType: openrtb_ext.BidTypeVideo}},
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := isEligibleForUnwrap(tt.args.bid)
+ assert.Equal(t, tt.want, got)
})
}
}
diff --git a/modules/pubmatic/openwrap/metrics/config/multimetrics.go b/modules/pubmatic/openwrap/metrics/config/multimetrics.go
index 72a31262ea5..405a15cb20e 100644
--- a/modules/pubmatic/openwrap/metrics/config/multimetrics.go
+++ b/modules/pubmatic/openwrap/metrics/config/multimetrics.go
@@ -529,3 +529,17 @@ func (me *MultiMetricsEngine) RecordSignalDataStatus(pubid, profileid, signalTyp
thisME.RecordSignalDataStatus(pubid, profileid, signalType)
}
}
+
+// RecordBidRecoveryStatus across all engines
+func (me *MultiMetricsEngine) RecordBidRecoveryStatus(publisher, profile string, success bool) {
+ for _, thisME := range *me {
+ thisME.RecordBidRecoveryStatus(publisher, profile, success)
+ }
+}
+
+// RecordBidRecoveryResponseTime across all engines
+func (me *MultiMetricsEngine) RecordBidRecoveryResponseTime(publisher, profile string, responseTime time.Duration) {
+ for _, thisME := range *me {
+ thisME.RecordBidRecoveryResponseTime(publisher, profile, responseTime)
+ }
+}
diff --git a/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go b/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
index 2b206de8715..554ae4dc438 100644
--- a/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
+++ b/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
@@ -223,6 +223,8 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
mockEngine.EXPECT().RecordOWServerPanic("endpoint", "methodName", "nodeName", "podName")
mockEngine.EXPECT().RecordAmpVideoRequests("pubid", "profileid")
mockEngine.EXPECT().RecordAmpVideoResponses("pubid", "profileid")
+ mockEngine.EXPECT().RecordBidRecoveryStatus(publisher, profile, true)
+ mockEngine.EXPECT().RecordBidRecoveryResponseTime(publisher, profile, time.Duration(200))
// create the multi-metric engine
multiMetricEngine := MultiMetricsEngine{}
@@ -291,4 +293,6 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
multiMetricEngine.RecordOWServerPanic("endpoint", "methodName", "nodeName", "podName")
multiMetricEngine.RecordAmpVideoRequests("pubid", "profileid")
multiMetricEngine.RecordAmpVideoResponses("pubid", "profileid")
+ multiMetricEngine.RecordBidRecoveryStatus(publisher, profile, true)
+ multiMetricEngine.RecordBidRecoveryResponseTime(publisher, profile, time.Duration(200))
}
diff --git a/modules/pubmatic/openwrap/metrics/metrics.go b/modules/pubmatic/openwrap/metrics/metrics.go
index dfe45a8d500..6af13a88689 100644
--- a/modules/pubmatic/openwrap/metrics/metrics.go
+++ b/modules/pubmatic/openwrap/metrics/metrics.go
@@ -25,6 +25,8 @@ type MetricsEngine interface {
RecordPublisherRequests(endpoint string, publisher string, platform string)
RecordReqImpsWithContentCount(publisher, contentType string)
RecordInjectTrackerErrorCount(adformat, publisher, partner string)
+ RecordBidRecoveryStatus(publisher, profile string, success bool)
+ RecordBidRecoveryResponseTime(publisher, profile string, responseTime time.Duration)
// not-captured in openwrap module, dont provide enough insights
RecordPBSAuctionRequestsStats()
diff --git a/modules/pubmatic/openwrap/metrics/mock/mock.go b/modules/pubmatic/openwrap/metrics/mock/mock.go
index b98fde7c783..d70dc6a196c 100644
--- a/modules/pubmatic/openwrap/metrics/mock/mock.go
+++ b/modules/pubmatic/openwrap/metrics/mock/mock.go
@@ -815,6 +815,30 @@ func (mr *MockMetricsEngineMockRecorder) RecordVideoInstlImpsStats(arg0, arg1 in
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordVideoInstlImpsStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordVideoInstlImpsStats), arg0, arg1)
}
+// RecordBidRecoveryStatus mocks base method.
+func (m *MockMetricsEngine) RecordBidRecoveryStatus(arg0 string, arg1 string, arg2 bool) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "RecordBidRecoveryStatus", arg0, arg1, arg2)
+}
+
+// RecordBidRecoveryStatus indicates an expected call of RecordBidRecoveryStatus.
+func (mr *MockMetricsEngineMockRecorder) RecordBidRecoveryStatus(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBidRecoveryStatus", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBidRecoveryStatus), arg0, arg1, arg2)
+}
+
+// RecordBidRecoveryResponseTime mocks base method.
+func (m *MockMetricsEngine) RecordBidRecoveryResponseTime(arg0 string, arg1 string, arg2 time.Duration) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "RecordBidRecoveryResponseTime", arg0, arg1, arg2)
+}
+
+// RecordBidRecoveryResponseTime indicates an expected call of RecordBidRecoveryStatus.
+func (mr *MockMetricsEngineMockRecorder) RecordBidRecoveryResponseTime(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBidRecoveryResponseTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBidRecoveryResponseTime), arg0, arg1, arg2)
+}
+
// Shutdown mocks base method.
func (m *MockMetricsEngine) Shutdown() {
m.ctrl.T.Helper()
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
index 2117caabaff..055cdf0a4ee 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
@@ -34,6 +34,8 @@ type Metrics struct {
pubNoBidResponseErrors *prometheus.CounterVec
pubResponseTime *prometheus.HistogramVec
pubImpsWithContent *prometheus.CounterVec
+ pubBidRecoveryStatus *prometheus.CounterVec
+ pubBidRecoveryTime *prometheus.HistogramVec
// publisher-partner-platform level metrics
pubPartnerPlatformRequests *prometheus.CounterVec
@@ -360,6 +362,19 @@ func newMetrics(cfg *config.PrometheusMetrics, promRegistry *prometheus.Registry
[]string{pubIdLabel, profileIDLabel},
)
+ metrics.pubBidRecoveryTime = newHistogramVec(cfg, promRegistry,
+ "bid_recovery_response_time",
+ "Total time taken by request for secondary auction in ms at publisher profile level.",
+ []string{pubIDLabel, profileIDLabel},
+ []float64{100, 200, 300, 400},
+ )
+
+ metrics.pubBidRecoveryStatus = newCounter(cfg, promRegistry,
+ "bid_recovery_response_status",
+ "Count bid recovery status for secondary auction",
+ []string{pubIDLabel, profileIDLabel, successLabel},
+ )
+
newSSHBMetrics(&metrics, cfg, promRegistry)
return &metrics
@@ -680,3 +695,18 @@ func (m *Metrics) RecordPrebidCacheRequestTime(success bool, length time.Duratio
successLabel: strconv.FormatBool(success),
}).Observe(float64(length.Milliseconds()))
}
+
+func (m *Metrics) RecordBidRecoveryStatus(publisherID, profileID string, success bool) {
+ m.pubBidRecoveryStatus.With(prometheus.Labels{
+ pubIDLabel: publisherID,
+ profileIDLabel: profileID,
+ successLabel: strconv.FormatBool(success),
+ }).Inc()
+}
+
+func (m *Metrics) RecordBidRecoveryResponseTime(publisherID, profileID string, responseTime time.Duration) {
+ m.pubBidRecoveryTime.With(prometheus.Labels{
+ pubIDLabel: publisherID,
+ profileIDLabel: profileID,
+ }).Observe(float64(responseTime.Milliseconds()))
+}
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
index faff7bb23dc..9872b7356a9 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
@@ -374,6 +374,30 @@ func TestRecordAdruleValidationFailure(t *testing.T) {
})
}
+func TestRecordBidRecoveryStatus(t *testing.T) {
+ m := createMetricsForTesting()
+
+ m.RecordBidRecoveryStatus("5890", "123", true)
+
+ expectedCount := float64(1)
+ assertCounterVecValue(t, "", "bid_recovery_response_status", m.pubBidRecoveryStatus,
+ expectedCount, prometheus.Labels{
+ pubIDLabel: "5890",
+ profileIDLabel: "123",
+ successLabel: "true",
+ })
+}
+
+func TestRecordBidRecoveryResponseTime(t *testing.T) {
+ m := createMetricsForTesting()
+
+ m.RecordBidRecoveryResponseTime("5890", "12345", time.Duration(70)*time.Millisecond)
+ m.RecordBidRecoveryResponseTime("5890", "12345", time.Duration(130)*time.Millisecond)
+ resultingHistogram := getHistogramFromHistogramVecByTwoKeys(m.pubBidRecoveryTime,
+ pubIDLabel, "5890", profileIDLabel, "12345")
+ assertHistogram(t, "bid_recovery_response_time", resultingHistogram, 2, 200)
+}
+
func getHistogramFromHistogramVec(histogram *prometheus.HistogramVec, labelKey, labelValue string) dto.Histogram {
var result dto.Histogram
processMetrics(histogram, func(m dto.Metric) {
diff --git a/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go b/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
index 94ba5931eaa..82599a54489 100644
--- a/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
+++ b/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
@@ -350,5 +350,8 @@ func (st *StatsTCP) RecordAdruleEnabled(pubId, profId string)
func (st *StatsTCP) RecordAdruleValidationFailure(pubId, profId string) {}
func (st *StatsTCP) RecordSignalDataStatus(pubid, profileid, signalType string) {}
func (st *StatsTCP) RecordPrebidCacheRequestTime(success bool, length time.Duration) {}
+func (st *StatsTCP) RecordBidRecoveryStatus(pubID string, profile string, success bool) {}
+func (st *StatsTCP) RecordBidRecoveryResponseTime(pubID string, profile string, responseTime time.Duration) {
+}
func (st *StatsTCP) RecordPrebidAuctionBidResponse(publisher string, partnerName string, bidderCode string, adapterCode string) {
}
diff --git a/modules/pubmatic/openwrap/models/adpod.go b/modules/pubmatic/openwrap/models/adpod.go
index 4b453d0616a..83f8867a91b 100644
--- a/modules/pubmatic/openwrap/models/adpod.go
+++ b/modules/pubmatic/openwrap/models/adpod.go
@@ -43,3 +43,12 @@ type ImpAdPodConfig struct {
MinDuration int64 `json:"minduration,omitempty"`
MaxDuration int64 `json:"maxduration,omitempty"`
}
+
+type PodConfig struct {
+ PodID string
+ PodDur int64
+ MaxSeq int64
+ MinDuration int64
+ MaxDuration int64
+ RqdDurs []int64
+}
diff --git a/modules/pubmatic/openwrap/models/adpodconfig/adpodconfig.go b/modules/pubmatic/openwrap/models/adpodconfig/adpodconfig.go
index 948670718ce..2da4fdda974 100644
--- a/modules/pubmatic/openwrap/models/adpodconfig/adpodconfig.go
+++ b/modules/pubmatic/openwrap/models/adpodconfig/adpodconfig.go
@@ -7,23 +7,23 @@ type AdpodConfig struct {
}
type Dynamic struct {
- PodDur int `json:"poddur,omitempty"`
- Maxseq int `json:"maxseq,omitempty"`
- MinDuration int `json:"minduration,omitempty"`
- MaxDuration int `json:"maxduration,omitempty"`
- Rqddurs []int `json:"rqddurs,omitempty"`
+ PodDur int64 `json:"poddur,omitempty"`
+ MaxSeq int64 `json:"maxseq,omitempty"`
+ MinDuration int64 `json:"minduration,omitempty"`
+ MaxDuration int64 `json:"maxduration,omitempty"`
+ RqdDurs []int64 `json:"rqddurs,omitempty"`
}
type Structured struct {
- MinDuration int `json:"minduration,omitempty"`
- MaxDuration int `json:"maxduration,omitempty"`
- Rqddurs []int `json:"rqddurs,omitempty"`
+ MinDuration int64 `json:"minduration,omitempty"`
+ MaxDuration int64 `json:"maxduration,omitempty"`
+ RqdDurs []int64 `json:"rqddurs,omitempty"`
}
type Hybrid struct {
- PodDur *int `json:"poddur,omitempty"`
- Maxseq *int `json:"maxseq,omitempty"`
- MinDuration int `json:"minduration,omitempty"`
- MaxDuration int `json:"maxduration,omitempty"`
- Rqddurs []int `json:"rqddurs,omitempty"`
+ PodDur *int64 `json:"poddur,omitempty"`
+ MaxSeq *int64 `json:"maxseq,omitempty"`
+ MinDuration int64 `json:"minduration,omitempty"`
+ MaxDuration int64 `json:"maxduration,omitempty"`
+ RqdDurs []int64 `json:"rqddurs,omitempty"`
}
diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go
index 94f124cbb27..0557c1b2398 100755
--- a/modules/pubmatic/openwrap/models/constants.go
+++ b/modules/pubmatic/openwrap/models/constants.go
@@ -357,6 +357,9 @@ const (
PixelPosAbove = "above"
PixelPosBelow = "below"
+ //constants for tracker impCountingMethod
+ ImpCountingMethod = "imp_ct_mthd"
+
DealIDNotApplicable = "na"
DealTierNotApplicable = "na"
PwtDealTier = "pwtdealtier"
@@ -371,21 +374,23 @@ const (
Enabled = "1"
// VAST Unwrap
- RequestContext = "rctx"
- UnwrapCount = "unwrap-count"
- UnwrapStatus = "unwrap-status"
- Timeout = "Timeout"
- UnwrapSucessStatus = "0"
- UnwrapTimeout = "unwrap-timeout"
- MediaTypeVideo = "video"
- ProfileId = "profileID"
- VersionId = "versionID"
- DisplayId = "DisplayID"
- XUserIP = "X-Forwarded-For"
- XUserAgent = "X-Device-User-Agent"
- CreativeID = "unwrap-ucrid"
- PubID = "pub_id"
- ImpressionID = "imr_id"
+ RequestContext = "rctx"
+ UnwrapCount = "unwrap-count"
+ UnwrapStatus = "unwrap-status"
+ Timeout = "Timeout"
+ UnwrapSucessStatus = "0"
+ UnwrapEmptyVASTStatus = "4"
+ UnwrapInvalidVASTStatus = "6"
+ UnwrapTimeout = "unwrap-timeout"
+ MediaTypeVideo = "video"
+ ProfileId = "profileID"
+ VersionId = "versionID"
+ DisplayId = "DisplayID"
+ XUserIP = "X-Forwarded-For"
+ XUserAgent = "X-Device-User-Agent"
+ CreativeID = "unwrap-ucrid"
+ PubID = "pub_id"
+ ImpressionID = "imr_id"
//Constants for new SDK reporting
ProfileTypeKey = "type"
@@ -593,6 +598,7 @@ const (
FeatureMaxFloors = 5
FeatureBidRecovery = 6
FeatureApplovinMultiFloors = 7
+ FeatureImpCountingMethod = 8
)
// constants for applovinmax requests
diff --git a/modules/pubmatic/openwrap/models/nbr/codes.go b/modules/pubmatic/openwrap/models/nbr/codes.go
index 7eafb8a5d09..fa54481d8d1 100644
--- a/modules/pubmatic/openwrap/models/nbr/codes.go
+++ b/modules/pubmatic/openwrap/models/nbr/codes.go
@@ -9,6 +9,7 @@ const (
RequestBlockedSlotNotMapped openrtb3.NoBidReason = 503
RequestBlockedPartnerThrottle openrtb3.NoBidReason = 504
RequestBlockedPartnerFiltered openrtb3.NoBidReason = 505
+ LossBidLostInVastUnwrap openrtb3.NoBidReason = 506
)
// Openwrap module specific codes
diff --git a/modules/pubmatic/openwrap/models/openwrap.go b/modules/pubmatic/openwrap/models/openwrap.go
index 274e6ecf91a..06ce72fbb1a 100644
--- a/modules/pubmatic/openwrap/models/openwrap.go
+++ b/modules/pubmatic/openwrap/models/openwrap.go
@@ -9,9 +9,13 @@ import (
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/nbr"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/ortb"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/wakanda"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/usersync"
+ "github.com/prebid/prebid-server/v2/util/maputil"
+ "github.com/prebid/prebid-server/v2/util/ptrutil"
+ "github.com/prebid/prebid-server/v2/util/sliceutil"
)
type RequestCtx struct {
@@ -88,36 +92,47 @@ type RequestCtx struct {
BidderResponseTimeMillis map[string]int
- Endpoint string
- PubIDStr, ProfileIDStr string // TODO: remove this once we completely move away from header-bidding
- MetricsEngine metrics.MetricsEngine
- ReturnAllBidStatus bool // ReturnAllBidStatus stores the value of request.ext.prebid.returnallbidstatus
- Sshb string //Sshb query param to identify that the request executed heder-bidding or not, sshb=1(executed HB(8001)), sshb=2(reverse proxy set from HB(8001->8000)), sshb=""(direct request(8000)).
- DCName string
- CachePutMiss int // to be used in case of CTV JSON endpoint/amp/inapp-ott-video endpoint
- CurrencyConversion func(from string, to string, value float64) (float64, error)
- MatchedImpression map[string]int
- CustomDimensions map[string]CustomDimension
- AmpVideoEnabled bool //AmpVideoEnabled indicates whether to include a Video object in an AMP request.
- IsTBFFeatureEnabled bool
- VastUnwrapEnabled bool
- VastUnwrapStatsEnabled bool
- AppLovinMax AppLovinMax
- LoggerDisabled bool
- TrackerDisabled bool
- ProfileType int
- ProfileTypePlatform int
- AppPlatform int
- AppIntegrationPath *int
- AppSubIntegrationPath *int
- Method string
- Errors []error
- RedirectURL string
- ResponseFormat string
- WakandaDebug wakanda.WakandaDebug
- PriceGranularity *openrtb_ext.PriceGranularity
- IsMaxFloorsEnabled bool
- SendBurl bool
+ Endpoint string
+ PubIDStr, ProfileIDStr string // TODO: remove this once we completely move away from header-bidding
+ MetricsEngine metrics.MetricsEngine
+ ReturnAllBidStatus bool // ReturnAllBidStatus stores the value of request.ext.prebid.returnallbidstatus
+ Sshb string //Sshb query param to identify that the request executed heder-bidding or not, sshb=1(executed HB(8001)), sshb=2(reverse proxy set from HB(8001->8000)), sshb=""(direct request(8000)).
+ DCName string
+ CachePutMiss int // to be used in case of CTV JSON endpoint/amp/inapp-ott-video endpoint
+ CurrencyConversion func(from string, to string, value float64) (float64, error)
+ MatchedImpression map[string]int
+ CustomDimensions map[string]CustomDimension
+ AmpVideoEnabled bool //AmpVideoEnabled indicates whether to include a Video object in an AMP request.
+ IsTBFFeatureEnabled bool
+ VastUnwrapEnabled bool
+ VastUnwrapStatsEnabled bool
+ AppLovinMax AppLovinMax
+ LoggerDisabled bool
+ TrackerDisabled bool
+ ProfileType int
+ ProfileTypePlatform int
+ AppPlatform int
+ AppIntegrationPath *int
+ AppSubIntegrationPath *int
+ Method string
+ Errors []error
+ RedirectURL string
+ ResponseFormat string
+ WakandaDebug wakanda.WakandaDebug
+ PriceGranularity *openrtb_ext.PriceGranularity
+ IsMaxFloorsEnabled bool
+ SendBurl bool
+ ImpCountingMethodEnabledBidders map[string]struct{} // Bidders who have enabled ImpCountingMethod feature
+
+ // Adpod
+ AdruleFlag bool
+ AdpodProfileConfig *AdpodProfileConfig
+ ImpAdPodConfig map[string][]PodConfig
+}
+
+type AdpodProfileConfig struct {
+ AdserverCreativeDurations []int `json:"videoadduration,omitempty"` //Range of ad durations allowed in the response
+ AdserverCreativeDurationMatchingPolicy string `json:"videoaddurationmatching,omitempty"` //Flag indicating exact ad duration requirement. (default)empty/exact/round.
}
type OwBid struct {
@@ -168,7 +183,7 @@ type ImpCtx struct {
//temp
BidderError string
- // CTV
+ // Adpod
IsAdPodRequest bool
AdpodConfig *AdPod
ImpAdPodCfg []*ImpAdPodConfig
@@ -282,3 +297,17 @@ func IsNewWinningBid(bid, wbid *OwBid, preferDeals bool) bool {
bid.Nbr = nbr.LossBidLostToHigherBid.Ptr()
return false
}
+
+func (ic *ImpCtx) DeepCopy() ImpCtx {
+ impCtx := *ic
+ impCtx.IsRewardInventory = ptrutil.Clone(ic.IsRewardInventory)
+ impCtx.Video = ortb.DeepCopyImpVideo(ic.Video)
+ impCtx.Native = ortb.DeepCopyImpNative(ic.Native)
+ impCtx.IncomingSlots = sliceutil.Clone(ic.IncomingSlots)
+ impCtx.Bidders = maputil.Clone(ic.Bidders)
+ impCtx.NonMapped = maputil.Clone(ic.NonMapped)
+ impCtx.NewExt = sliceutil.Clone(ic.NewExt)
+ impCtx.BidCtx = maputil.Clone(ic.BidCtx)
+
+ return impCtx
+}
diff --git a/modules/pubmatic/openwrap/models/request.go b/modules/pubmatic/openwrap/models/request.go
index 17051bfe2b3..f6582500905 100644
--- a/modules/pubmatic/openwrap/models/request.go
+++ b/modules/pubmatic/openwrap/models/request.go
@@ -25,14 +25,12 @@ type ExtRequestAdPod struct {
// AdPod holds Video AdPod specific extension parameters at impression level
type AdPod struct {
- MinAds int `json:"minads,omitempty"` //Default 1 if not specified
- MaxAds int `json:"maxads,omitempty"` //Default 1 if not specified
- MinDuration int `json:"adminduration,omitempty"` // (adpod.adminduration * adpod.minads) should be greater than or equal to video.minduration
- MaxDuration int `json:"admaxduration,omitempty"` // (adpod.admaxduration * adpod.maxads) should be less than or equal to video.maxduration + video.maxextended
- AdvertiserExclusionPercent *int `json:"excladv,omitempty"` // Percent value 0 means none of the ads can be from same advertiser 100 means can have all same advertisers
- IABCategoryExclusionPercent *int `json:"excliabcat,omitempty"` // Percent value 0 means all ads should be of different IAB categories.
- VideoAdDuration []int `json:"videoadduration,omitempty"` //Range of ad durations allowed in the response
- VideoAdDurationMatching string `json:"videoaddurationmatching,omitempty"` //Flag indicating exact ad duration requirement. (default)empty/exact/round.
+ MinAds int `json:"minads,omitempty"` //Default 1 if not specified
+ MaxAds int `json:"maxads,omitempty"` //Default 1 if not specified
+ MinDuration int `json:"adminduration,omitempty"` // (adpod.adminduration * adpod.minads) should be greater than or equal to video.minduration
+ MaxDuration int `json:"admaxduration,omitempty"` // (adpod.admaxduration * adpod.maxads) should be less than or equal to video.maxduration + video.maxextended
+ AdvertiserExclusionPercent *int `json:"excladv,omitempty"` // Percent value 0 means none of the ads can be from same advertiser 100 means can have all same advertisers
+ IABCategoryExclusionPercent *int `json:"excliabcat,omitempty"` // Percent value 0 means all ads should be of different IAB categories.
}
// ImpExtension - Impression Extension
@@ -109,9 +107,14 @@ type RequestExtWrapper struct {
LoggerImpressionID string `json:"wiid,omitempty"`
SSAI string `json:"ssai,omitempty"`
KeyValues map[string]interface{} `json:"kv,omitempty"`
+ Video ExtRequestWrapperVideo `json:"video,omitempty"`
PubId int `json:"-"`
}
+type ExtRequestWrapperVideo struct {
+ AdruleFlag bool `json:"adrule,omitempty"`
+}
+
type BidderWrapper struct {
Flag bool
VASTagFlags map[string]bool
diff --git a/modules/pubmatic/openwrap/models/tracker.go b/modules/pubmatic/openwrap/models/tracker.go
index 4d3d6c0b3af..74822a37cb3 100644
--- a/modules/pubmatic/openwrap/models/tracker.go
+++ b/modules/pubmatic/openwrap/models/tracker.go
@@ -9,7 +9,7 @@ type OWTracker struct {
PriceModel string
PriceCurrency string
BidType string `json:"-"` // video, banner, native
- DspId int `json:"-"` // dsp id
+ IsOMEnabled bool `json:"-"` // is om enabled
}
// Tracker tracker url creation parameters
diff --git a/modules/pubmatic/openwrap/models/utils_test.go b/modules/pubmatic/openwrap/models/utils_test.go
index 5e878cfaf19..afff46c2bf4 100644
--- a/modules/pubmatic/openwrap/models/utils_test.go
+++ b/modules/pubmatic/openwrap/models/utils_test.go
@@ -1229,6 +1229,7 @@ func TestGetKGPSV(t *testing.T) {
args: args{
bidderMeta: PartnerData{
KGPV: "kgpv",
+ KGP: "_AU_@_W_x_H_",
},
},
kgpv: "kgpv",
@@ -1240,6 +1241,7 @@ func TestGetKGPSV(t *testing.T) {
bidderMeta: PartnerData{
KGPV: "kgpv",
IsRegex: true,
+ KGP: "_AU_@_DIV_@_W_x_H_",
},
},
kgpv: "kgpv",
@@ -1251,6 +1253,7 @@ func TestGetKGPSV(t *testing.T) {
bidderMeta: PartnerData{
MatchedSlot: "kgpsv",
IsRegex: true,
+ KGP: "_AU_@_DIV_@_W_x_H_",
},
},
kgpv: "kgpsv",
@@ -1269,6 +1272,7 @@ func TestGetKGPSV(t *testing.T) {
KGPV: "kgpv",
MatchedSlot: "kgpsv",
IsRegex: true,
+ KGP: "_AU_@_DIV_@_W_x_H_",
},
},
kgpv: "kgpv",
@@ -1287,27 +1291,14 @@ func TestGetKGPSV(t *testing.T) {
KGPV: "kgpv",
MatchedSlot: "kgpsv",
IsRegex: false,
+ KGP: "_AU_@_W_x_H_",
},
},
kgpv: "kgpv",
kgpsv: "kgpv",
},
{
- name: "KGPV and KGP not present in partnerData,regex false and adformat is video",
- args: args{
- bid: openrtb2.Bid{
- Price: 1,
- DealID: "deal",
- W: 250,
- H: 300,
- },
- adformat: Video,
- },
- kgpv: "",
- kgpsv: "",
- },
- {
- name: "KGPV not present in partnerData,regex false and adformat is video",
+ name: "KGPV not present in partnerData, regex false and adformat is video",
args: args{
bid: openrtb2.Bid{
Price: 1,
@@ -1325,7 +1316,7 @@ func TestGetKGPSV(t *testing.T) {
kgpsv: "adunit@0x0",
},
{
- name: "KGPV not present in partnerData,regex false and adformat is banner",
+ name: "KGPV not present in partnerData, regex false and adformat is banner",
args: args{
bid: openrtb2.Bid{
Price: 1,
@@ -1347,12 +1338,11 @@ func TestGetKGPSV(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1 := GetKGPSV(tt.args.bid, tt.args.bidExt, tt.args.bidderMeta, tt.args.adformat, tt.args.tagId, tt.args.div, tt.args.source)
- if got != tt.kgpv {
- t.Errorf("GetKGPSV() got = %v, want %v", got, tt.kgpv)
- }
- if got1 != tt.kgpsv {
- t.Errorf("GetKGPSV() got1 = %v, want %v", got1, tt.kgpsv)
- }
+
+ // Ensure KGPV is not empty
+ assert.NotEmpty(t, got, "KGPV should not be empty")
+ assert.Equal(t, tt.kgpv, got, "GetKGPSV() got = %v, want %v", got, tt.kgpv)
+ assert.Equal(t, tt.kgpsv, got1, "GetKGPSV() got1 = %v, want %v", got1, tt.kgpsv)
})
}
}
diff --git a/modules/pubmatic/openwrap/ortb/imp.go b/modules/pubmatic/openwrap/ortb/imp.go
new file mode 100644
index 00000000000..9c9326678d3
--- /dev/null
+++ b/modules/pubmatic/openwrap/ortb/imp.go
@@ -0,0 +1,115 @@
+package ortb
+
+import (
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/util/ptrutil"
+ "github.com/prebid/prebid-server/v2/util/sliceutil"
+)
+
+func DeepCloneImpression(imp *openrtb2.Imp) *openrtb2.Imp {
+ clone := *imp
+
+ clone.Metric = sliceutil.Clone(imp.Metric)
+ clone.Banner = DeepCopyImpBanner(imp.Banner)
+ clone.Video = DeepCopyImpVideo(imp.Video)
+ clone.Audio = DeepCopyImpAudio(imp.Audio)
+ clone.Native = DeepCopyImpNative(imp.Native)
+ clone.PMP = DeepCopyImpPMP(imp.PMP)
+ clone.ClickBrowser = ptrutil.Clone(imp.ClickBrowser)
+ clone.Secure = ptrutil.Clone(imp.Secure)
+ clone.IframeBuster = sliceutil.Clone(imp.IframeBuster)
+ clone.Qty = ptrutil.Clone(imp.Qty)
+ clone.Refresh = ptrutil.Clone(imp.Refresh)
+ clone.Ext = sliceutil.Clone(imp.Ext)
+ return &clone
+}
+
+func DeepCopyImpVideo(video *openrtb2.Video) *openrtb2.Video {
+ if video == nil {
+ return nil
+ }
+
+ videoCopy := *video
+ videoCopy.MIMEs = sliceutil.Clone(video.MIMEs)
+ videoCopy.StartDelay = ptrutil.Clone(video.StartDelay)
+ videoCopy.Protocols = sliceutil.Clone(video.Protocols)
+ videoCopy.W = ptrutil.Clone(video.W)
+ videoCopy.H = ptrutil.Clone(video.H)
+ videoCopy.RqdDurs = sliceutil.Clone(video.RqdDurs)
+ videoCopy.Skip = ptrutil.Clone(video.Skip)
+ videoCopy.BAttr = sliceutil.Clone(video.BAttr)
+ videoCopy.BoxingAllowed = ptrutil.Clone(video.BoxingAllowed)
+ videoCopy.PlaybackMethod = sliceutil.Clone(video.PlaybackMethod)
+ videoCopy.Delivery = sliceutil.Clone(video.Delivery)
+ videoCopy.Pos = ptrutil.Clone(video.Pos)
+ videoCopy.CompanionAd = sliceutil.Clone(video.CompanionAd)
+ videoCopy.API = sliceutil.Clone(video.API)
+ videoCopy.CompanionType = sliceutil.Clone(video.CompanionType)
+ videoCopy.DurFloors = sliceutil.Clone(video.DurFloors)
+ videoCopy.Ext = sliceutil.Clone(video.Ext)
+ return &videoCopy
+}
+
+func DeepCopyImpNative(native *openrtb2.Native) *openrtb2.Native {
+ if native == nil {
+ return nil
+ }
+
+ nativeCopy := *native
+ nativeCopy.API = sliceutil.Clone(native.API)
+ nativeCopy.BAttr = sliceutil.Clone(native.BAttr)
+ nativeCopy.Ext = sliceutil.Clone(native.Ext)
+ return &nativeCopy
+}
+
+func DeepCopyImpBanner(banner *openrtb2.Banner) *openrtb2.Banner {
+ if banner == nil {
+ return nil
+ }
+
+ bannerCopy := *banner
+ bannerCopy.Format = sliceutil.Clone(banner.Format)
+ bannerCopy.W = ptrutil.Clone(banner.W)
+ bannerCopy.H = ptrutil.Clone(banner.H)
+ bannerCopy.BType = sliceutil.Clone(banner.BType)
+ bannerCopy.BAttr = sliceutil.Clone(banner.BAttr)
+ bannerCopy.MIMEs = sliceutil.Clone(banner.MIMEs)
+ bannerCopy.ExpDir = sliceutil.Clone(banner.ExpDir)
+ bannerCopy.API = sliceutil.Clone(banner.API)
+ bannerCopy.Vcm = ptrutil.Clone(banner.Vcm)
+ bannerCopy.Ext = sliceutil.Clone(banner.Ext)
+ return &bannerCopy
+}
+
+func DeepCopyImpAudio(audio *openrtb2.Audio) *openrtb2.Audio {
+ if audio == nil {
+ return nil
+ }
+
+ audioCopy := *audio
+ audioCopy.MIMEs = sliceutil.Clone(audio.MIMEs)
+ audioCopy.Protocols = sliceutil.Clone(audio.Protocols)
+ audioCopy.StartDelay = ptrutil.Clone(audio.StartDelay)
+ audioCopy.RqdDurs = sliceutil.Clone(audio.RqdDurs)
+ audioCopy.BAttr = sliceutil.Clone(audio.BAttr)
+ audioCopy.Delivery = sliceutil.Clone(audio.Delivery)
+ audioCopy.CompanionAd = sliceutil.Clone(audio.CompanionAd)
+ audioCopy.API = sliceutil.Clone(audio.API)
+ audioCopy.CompanionType = sliceutil.Clone(audio.CompanionType)
+ audioCopy.Stitched = ptrutil.Clone(audio.Stitched)
+ audioCopy.NVol = ptrutil.Clone(audio.NVol)
+ audioCopy.DurFloors = sliceutil.Clone(audio.DurFloors)
+ audioCopy.Ext = sliceutil.Clone(audio.Ext)
+ return &audioCopy
+}
+
+func DeepCopyImpPMP(pmp *openrtb2.PMP) *openrtb2.PMP {
+ if pmp == nil {
+ return nil
+ }
+
+ pmpCopy := *pmp
+ pmpCopy.Deals = sliceutil.Clone(pmp.Deals)
+ pmpCopy.Ext = sliceutil.Clone(pmp.Ext)
+ return &pmpCopy
+}
diff --git a/modules/pubmatic/openwrap/processedauctionhook.go b/modules/pubmatic/openwrap/processedauctionhook.go
index 5d381d36194..2ecc1b7c5f0 100644
--- a/modules/pubmatic/openwrap/processedauctionhook.go
+++ b/modules/pubmatic/openwrap/processedauctionhook.go
@@ -39,7 +39,7 @@ func (m OpenWrap) HandleProcessedAuctionHook(
var imps []*openrtb_ext.ImpWrapper
var errs []error
if rctx.IsCTVRequest {
- imps, errs = impressions.GenerateImpressions(payload.Request, rctx.ImpBidCtx, rctx.PubIDStr, m.metricEngine)
+ imps, errs = impressions.GenerateImpressions(payload.Request, rctx.ImpBidCtx, rctx.AdpodProfileConfig, rctx.PubIDStr, m.metricEngine)
if len(errs) > 0 {
for i := range errs {
result.Warnings = append(result.Warnings, errs[i].Error())
diff --git a/modules/pubmatic/openwrap/publisherfeature/feature.go b/modules/pubmatic/openwrap/publisherfeature/feature.go
index ae8fc05ee32..1c4e785cc86 100644
--- a/modules/pubmatic/openwrap/publisherfeature/feature.go
+++ b/modules/pubmatic/openwrap/publisherfeature/feature.go
@@ -11,4 +11,5 @@ type Feature interface {
IsBidRecoveryEnabled(pubID int, profileID int) bool
IsApplovinMultiFloorsEnabled(pubID int, profileID string) bool
GetApplovinMultiFloors(pubID int, profileID string) models.ApplovinAdUnitFloors
+ GetImpCountingMethodEnabledBidders() map[string]struct{}
}
diff --git a/modules/pubmatic/openwrap/publisherfeature/impcountingmethod.go b/modules/pubmatic/openwrap/publisherfeature/impcountingmethod.go
new file mode 100644
index 00000000000..8c51b5715ad
--- /dev/null
+++ b/modules/pubmatic/openwrap/publisherfeature/impcountingmethod.go
@@ -0,0 +1,48 @@
+package publisherfeature
+
+import (
+ "strings"
+
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+)
+
+type impCountingMethod struct {
+ enabledBidders [2]map[string]struct{}
+ index int32
+}
+
+func newImpCountingMethod() impCountingMethod {
+ return impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ make(map[string]struct{}),
+ make(map[string]struct{}),
+ },
+ index: 0,
+ }
+}
+
+func (fe *feature) updateImpCountingMethodEnabledBidders() {
+ if fe.publisherFeature == nil {
+ return
+ }
+
+ enabledBidders := make(map[string]struct{})
+ for pubID, feature := range fe.publisherFeature {
+ if val, ok := feature[models.FeatureImpCountingMethod]; ok && pubID == 0 && val.Enabled == 1 {
+ bidders := strings.Split(val.Value, ",")
+ for _, bidder := range bidders {
+ bidder = strings.TrimSpace(bidder)
+ if bidder != "" {
+ enabledBidders[bidder] = struct{}{}
+ }
+ }
+ }
+ }
+
+ fe.impCountingMethod.enabledBidders[fe.impCountingMethod.index^1] = enabledBidders
+ fe.impCountingMethod.index ^= 1
+}
+
+func (fe *feature) GetImpCountingMethodEnabledBidders() map[string]struct{} {
+ return fe.impCountingMethod.enabledBidders[fe.impCountingMethod.index]
+}
diff --git a/modules/pubmatic/openwrap/publisherfeature/impcountingmethod_test.go b/modules/pubmatic/openwrap/publisherfeature/impcountingmethod_test.go
new file mode 100644
index 00000000000..61d95b4aac9
--- /dev/null
+++ b/modules/pubmatic/openwrap/publisherfeature/impcountingmethod_test.go
@@ -0,0 +1,267 @@
+package publisherfeature
+
+import (
+ "testing"
+
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/cache"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFeatureUpdateImpCountingMethodEnabledBidders(t *testing.T) {
+ type fields struct {
+ cache cache.Cache
+ publisherFeature map[int]map[int]models.FeatureData
+ impCountingMethod impCountingMethod
+ }
+ tests := []struct {
+ name string
+ fields fields
+ wantImpCoutingMethodEnabledBidders [2]map[string]struct{}
+ wantImpCoutingMethodIndex int32
+ }{
+ {
+ name: "publisherFeature_map_is_nil",
+ fields: fields{
+ cache: nil,
+ publisherFeature: nil,
+ impCountingMethod: newImpCountingMethod(),
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ make(map[string]struct{}),
+ make(map[string]struct{}),
+ },
+ wantImpCoutingMethodIndex: 0,
+ },
+ {
+ name: "publisherFeature_map_is_present_but_impCountingMethod_is_not_present_in_DB",
+ fields: fields{
+ cache: nil,
+ publisherFeature: map[int]map[int]models.FeatureData{},
+ impCountingMethod: newImpCountingMethod(),
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ wantImpCoutingMethodIndex: 1,
+ },
+ {
+ name: "update _imp_counting_method_enabled_bidders",
+ fields: fields{
+ cache: nil,
+ publisherFeature: map[int]map[int]models.FeatureData{
+ 0: {
+ models.FeatureImpCountingMethod: {
+ Enabled: 1,
+ Value: `appnexus,rubicon`,
+ },
+ },
+ },
+ impCountingMethod: newImpCountingMethod(),
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ {},
+ {
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ wantImpCoutingMethodIndex: 1,
+ },
+ {
+ name: "update _imp_counting_method_enabled_bidders_with_bidders_in_flip_map",
+ fields: fields{
+ cache: nil,
+ publisherFeature: map[int]map[int]models.FeatureData{
+ 0: {
+ models.FeatureImpCountingMethod: {
+ Enabled: 1,
+ Value: `appnexus,rubicon`,
+ },
+ },
+ },
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {
+ "magnite": {},
+ "ix": {},
+ },
+ {
+ "pgam": {},
+ "ix": {},
+ },
+ },
+ index: 0,
+ },
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ {
+ "magnite": {},
+ "ix": {},
+ },
+ {
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ wantImpCoutingMethodIndex: 1,
+ },
+ {
+ name: "update_imp_counting_method_enabled_bidders_with_space_in_value",
+ fields: fields{
+ cache: nil,
+ publisherFeature: map[int]map[int]models.FeatureData{
+ 0: {
+ models.FeatureImpCountingMethod: {
+ Enabled: 1,
+ Value: ` appnexus,rubicon `,
+ },
+ },
+ },
+ impCountingMethod: newImpCountingMethod(),
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ {},
+ {
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ wantImpCoutingMethodIndex: 1,
+ },
+ {
+ name: "update_imp_counting_method_with_feature_disabled",
+ fields: fields{
+ cache: nil,
+ publisherFeature: map[int]map[int]models.FeatureData{
+ 0: {
+ models.FeatureImpCountingMethod: {
+ Enabled: 0,
+ Value: `appnexus,rubicon`,
+ },
+ },
+ },
+ impCountingMethod: newImpCountingMethod(),
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ wantImpCoutingMethodIndex: 1,
+ },
+ {
+ name: "update_imp_counting_method_with_feature_disabled",
+ fields: fields{
+ cache: nil,
+ publisherFeature: map[int]map[int]models.FeatureData{
+ 0: {
+ models.FeatureImpCountingMethod: {
+ Enabled: 0,
+ Value: `appnexus,rubicon`,
+ },
+ },
+ },
+ impCountingMethod: newImpCountingMethod(),
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ wantImpCoutingMethodIndex: 1,
+ },
+ {
+ name: "update_imp_counting_method_with_feature_enabled_but_empty_value",
+ fields: fields{
+ cache: nil,
+ publisherFeature: map[int]map[int]models.FeatureData{
+ 0: {
+ models.FeatureImpCountingMethod: {
+ Enabled: 1,
+ Value: ``,
+ },
+ },
+ },
+ impCountingMethod: newImpCountingMethod(),
+ },
+ wantImpCoutingMethodEnabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ wantImpCoutingMethodIndex: 1,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ var fe *feature
+ fe = &feature{
+ publisherFeature: tt.fields.publisherFeature,
+ impCountingMethod: tt.fields.impCountingMethod,
+ }
+ defer func() {
+ fe = nil
+ }()
+ fe.updateImpCountingMethodEnabledBidders()
+ assert.Equal(t, tt.wantImpCoutingMethodEnabledBidders, fe.impCountingMethod.enabledBidders)
+ assert.Equal(t, tt.wantImpCoutingMethodIndex, fe.impCountingMethod.index)
+ })
+ }
+}
+
+func TestFeatureGetImpCountingMethodEnabledBidders(t *testing.T) {
+ type fields struct {
+ impCountingMethod impCountingMethod
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want map[string]struct{}
+ }{
+ {
+ name: "get_imp_counting_method_enabled_bidders_when_index_is_0",
+ fields: fields{
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ index: 0,
+ },
+ },
+ want: map[string]struct{}{
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ {
+ name: "get_imp_counting_method_enabled_bidders_when_index_is_1",
+ fields: fields{
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {},
+ {
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ index: 1,
+ },
+ },
+ want: map[string]struct{}{
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ fe := &feature{
+ impCountingMethod: tt.fields.impCountingMethod,
+ }
+ got := fe.GetImpCountingMethodEnabledBidders()
+ assert.Equal(t, tt.want, got, tt.name)
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/publisherfeature/mock/mock.go b/modules/pubmatic/openwrap/publisherfeature/mock/mock.go
index f27748a1c8e..d22eb6b28ff 100644
--- a/modules/pubmatic/openwrap/publisherfeature/mock/mock.go
+++ b/modules/pubmatic/openwrap/publisherfeature/mock/mock.go
@@ -47,6 +47,20 @@ func (mr *MockFeatureMockRecorder) GetApplovinMultiFloors(arg0, arg1 interface{}
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetApplovinMultiFloors", reflect.TypeOf((*MockFeature)(nil).GetApplovinMultiFloors), arg0, arg1)
}
+// GetImpCountingMethodEnabledBidders mocks base method
+func (m *MockFeature) GetImpCountingMethodEnabledBidders() map[string]struct{} {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetImpCountingMethodEnabledBidders")
+ ret0, _ := ret[0].(map[string]struct{})
+ return ret0
+}
+
+// GetImpCountingMethodEnabledBidders indicates an expected call of GetImpCountingMethodEnabledBidders
+func (mr *MockFeatureMockRecorder) GetImpCountingMethodEnabledBidders() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetImpCountingMethodEnabledBidders", reflect.TypeOf((*MockFeature)(nil).GetImpCountingMethodEnabledBidders))
+}
+
// IsAmpMultiformatEnabled mocks base method
func (m *MockFeature) IsAmpMultiformatEnabled(arg0 int) bool {
m.ctrl.T.Helper()
diff --git a/modules/pubmatic/openwrap/publisherfeature/reloader.go b/modules/pubmatic/openwrap/publisherfeature/reloader.go
index a5ded2cc516..6aafe9beee2 100644
--- a/modules/pubmatic/openwrap/publisherfeature/reloader.go
+++ b/modules/pubmatic/openwrap/publisherfeature/reloader.go
@@ -28,6 +28,7 @@ type feature struct {
maxFloors maxFloors
bidRecovery bidRecovery
appLovinMultiFloors appLovinMultiFloors
+ impCountingMethod impCountingMethod
}
var fe *feature
@@ -60,6 +61,7 @@ func New(config Config) *feature {
appLovinMultiFloors: appLovinMultiFloors{
enabledPublisherProfile: make(map[int]map[string]models.ApplovinAdUnitFloors),
},
+ impCountingMethod: newImpCountingMethod(),
}
})
return fe
@@ -117,6 +119,7 @@ func (fe *feature) updateFeatureConfigMaps() {
fe.updateAnalyticsThrottling()
fe.updateBidRecoveryEnabledPublishers()
fe.updateApplovinMultiFloorsFeature()
+ fe.updateImpCountingMethodEnabledBidders()
if err != nil {
glog.Error(err.Error())
diff --git a/modules/pubmatic/openwrap/publisherfeature/reloader_test.go b/modules/pubmatic/openwrap/publisherfeature/reloader_test.go
index b432d95971e..2c351c5dce9 100644
--- a/modules/pubmatic/openwrap/publisherfeature/reloader_test.go
+++ b/modules/pubmatic/openwrap/publisherfeature/reloader_test.go
@@ -113,7 +113,7 @@ func Test_feature_Start(t *testing.T) {
}
}
-func Test_feature_updateFeatureConfigMaps(t *testing.T) {
+func TestFeatureUpdateFeatureConfigMaps(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockCache := mock_cache.NewMockCache(ctrl)
@@ -127,6 +127,7 @@ func Test_feature_updateFeatureConfigMaps(t *testing.T) {
ampMultiformat ampMultiformat
bidRecovery bidRecovery
appLovinMultiFloors appLovinMultiFloors
+ impCountingMethod impCountingMethod
}
tests := []struct {
name string
@@ -158,6 +159,13 @@ func Test_feature_updateFeatureConfigMaps(t *testing.T) {
tbf: tbf{
pubProfileTraffic: map[int]map[int]int{},
},
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ index: 0,
+ },
},
},
{
@@ -205,6 +213,13 @@ func Test_feature_updateFeatureConfigMaps(t *testing.T) {
bidRecovery: bidRecovery{
enabledPublisherProfile: map[int]map[int]struct{}{},
},
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ index: 1,
+ },
},
},
{
@@ -256,6 +271,13 @@ func Test_feature_updateFeatureConfigMaps(t *testing.T) {
appLovinMultiFloors: appLovinMultiFloors{
enabledPublisherProfile: map[int]map[string]models.ApplovinAdUnitFloors{},
},
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ index: 1,
+ },
},
},
{
@@ -331,6 +353,60 @@ func Test_feature_updateFeatureConfigMaps(t *testing.T) {
},
},
},
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {},
+ {},
+ },
+ index: 1,
+ },
+ },
+ },
+ {
+ name: "fetch impcountingmethod feature data with multiple bidders",
+ fields: fields{
+ cache: mockCache,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetPublisherFeatureMap().Return(map[int]map[int]models.FeatureData{
+ 0: {
+ models.FeatureImpCountingMethod: {
+ Enabled: 1,
+ Value: "appnexus, rubicon",
+ },
+ },
+ }, nil)
+ mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{6: 100}, nil)
+ },
+ want: want{
+ fsc: fsc{
+ disabledPublishers: map[int]struct{}{},
+ thresholdsPerDsp: map[int]int{
+ 6: 100,
+ },
+ },
+ ampMultiformat: ampMultiformat{
+ enabledPublishers: map[int]struct{}{},
+ },
+ tbf: tbf{
+ pubProfileTraffic: map[int]map[int]int{},
+ },
+ bidRecovery: bidRecovery{
+ enabledPublisherProfile: map[int]map[int]struct{}{},
+ },
+ appLovinMultiFloors: appLovinMultiFloors{
+ enabledPublisherProfile: map[int]map[string]models.ApplovinAdUnitFloors{},
+ },
+ impCountingMethod: impCountingMethod{
+ enabledBidders: [2]map[string]struct{}{
+ {},
+ {
+ "appnexus": {},
+ "rubicon": {},
+ },
+ },
+ index: 1,
+ },
},
},
}
@@ -349,13 +425,18 @@ func Test_feature_updateFeatureConfigMaps(t *testing.T) {
ampMultiformat: ampMultiformat{
enabledPublishers: make(map[int]struct{}),
},
+ impCountingMethod: newImpCountingMethod(),
}
+ defer func() {
+ fe = nil
+ }()
fe.updateFeatureConfigMaps()
assert.Equal(t, tt.want.fsc, fe.fsc, tt.name)
assert.Equal(t, tt.want.tbf, fe.tbf, tt.name)
assert.Equal(t, tt.want.ampMultiformat, fe.ampMultiformat, tt.name)
assert.Equal(t, tt.want.bidRecovery, fe.bidRecovery, tt.name)
assert.Equal(t, tt.want.appLovinMultiFloors, fe.appLovinMultiFloors, tt.name)
+ assert.Equal(t, tt.want.impCountingMethod, fe.impCountingMethod, tt.name)
})
}
}
diff --git a/modules/pubmatic/openwrap/tracker/banner.go b/modules/pubmatic/openwrap/tracker/banner.go
index b092c2e5bdb..96d6fffd8a7 100644
--- a/modules/pubmatic/openwrap/tracker/banner.go
+++ b/modules/pubmatic/openwrap/tracker/banner.go
@@ -16,7 +16,7 @@ func injectBannerTracker(rctx models.RequestCtx, tracker models.OWTracker, bid o
var replacedTrackerStr, trackerFormat string
trackerFormat = models.TrackerCallWrap
- if trackerWithOM(tracker, rctx.Platform, seat) {
+ if tracker.IsOMEnabled {
trackerFormat = models.TrackerCallWrapOMActive
}
replacedTrackerStr = strings.Replace(trackerFormat, "${escapedUrl}", tracker.TrackerURL, 1)
@@ -40,14 +40,20 @@ func appendUPixelinBanner(adm string, universalPixel []adunitconfig.UniversalPix
return adm
}
-// TrackerWithOM checks for OM active condition for DV360
-func trackerWithOM(tracker models.OWTracker, platform, bidderCode string) bool {
- if platform == models.PLATFORM_APP && bidderCode == string(openrtb_ext.BidderPubmatic) {
- if tracker.DspId == models.DspId_DV360 {
- return true
- }
+// TrackerWithOM checks for OM active condition for DV360 with Pubmatic and other bidders
+func trackerWithOM(rctx models.RequestCtx, prebidPartnerName string, dspID int) bool {
+ if rctx.Platform != models.PLATFORM_APP {
+ return false
+ }
+
+ // check for OM active for DV360 with Pubmatic
+ if prebidPartnerName == string(openrtb_ext.BidderPubmatic) && dspID == models.DspId_DV360 {
+ return true
}
- return false
+
+ // check for OM active for other bidders
+ _, isPresent := rctx.ImpCountingMethodEnabledBidders[prebidPartnerName]
+ return isPresent
}
// applyTBFFeature adds the tracker before or after the actual bid.Adm
diff --git a/modules/pubmatic/openwrap/tracker/banner_test.go b/modules/pubmatic/openwrap/tracker/banner_test.go
index c72f6c6b4e0..448c78de943 100644
--- a/modules/pubmatic/openwrap/tracker/banner_test.go
+++ b/modules/pubmatic/openwrap/tracker/banner_test.go
@@ -6,10 +6,11 @@ import (
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/stretchr/testify/assert"
)
-func Test_injectBannerTracker(t *testing.T) {
+func TestInjectBannerTracker(t *testing.T) {
type args struct {
rctx models.RequestCtx
tracker models.OWTracker
@@ -17,11 +18,14 @@ func Test_injectBannerTracker(t *testing.T) {
seat string
pixels []adunitconfig.UniversalPixel
}
+ type want struct {
+ adm string
+ burl string
+ }
tests := []struct {
- name string
- args args
- wantAdm string
- wantBurl string
+ name string
+ args args
+ want want
}{
{
name: "endpoint_applovinmax",
@@ -39,8 +43,10 @@ func Test_injectBannerTracker(t *testing.T) {
},
seat: "pubmatic",
},
- wantAdm: ``,
- wantBurl: `sample.com/track?tid=1234&owsspburl=http://burl.com`,
+ want: want{
+ adm: ``,
+ burl: `sample.com/track?tid=1234&owsspburl=http%3A%2F%2Fburl.com`,
+ },
},
{
name: "app_platform",
@@ -56,7 +62,9 @@ func Test_injectBannerTracker(t *testing.T) {
},
seat: "test",
},
- wantAdm: `sample_creative`,
+ want: want{
+ adm: `sample_creative`,
+ },
},
{
name: "app_platform_OM_Inactive_pubmatic",
@@ -65,15 +73,17 @@ func Test_injectBannerTracker(t *testing.T) {
Platform: models.PLATFORM_APP,
},
tracker: models.OWTracker{
- TrackerURL: `Tracking URL`,
- DspId: -1,
+ TrackerURL: `Tracking URL`,
+ IsOMEnabled: false,
},
bid: openrtb2.Bid{
AdM: `sample_creative`,
},
seat: models.BidderPubMatic,
},
- wantAdm: `sample_creative`,
+ want: want{
+ adm: `sample_creative`,
+ },
},
{
name: "app_platform_OM_Active_pubmatic",
@@ -82,15 +92,17 @@ func Test_injectBannerTracker(t *testing.T) {
Platform: models.PLATFORM_APP,
},
tracker: models.OWTracker{
- TrackerURL: `Tracking URL`,
- DspId: models.DspId_DV360,
+ TrackerURL: `Tracking URL`,
+ IsOMEnabled: true,
},
bid: openrtb2.Bid{
AdM: `sample_creative`,
},
seat: models.BidderPubMatic,
},
- wantAdm: `sample_creative`,
+ want: want{
+ adm: `sample_creative`,
+ },
},
{
name: "tbf_feature_enabled",
@@ -107,23 +119,68 @@ func Test_injectBannerTracker(t *testing.T) {
AdM: `sample_creative`,
},
},
- wantAdm: `sample_creative`,
+ want: want{
+ adm: `sample_creative`,
+ },
+ },
+ {
+ name: "app_platform_partner_other_than_pubmatic_imp_counting_method_enabled",
+ args: args{
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
+ ImpCountingMethodEnabledBidders: map[string]struct{}{
+ string(openrtb_ext.BidderIx): {},
+ },
+ },
+ tracker: models.OWTracker{
+ TrackerURL: `Tracking URL`,
+ IsOMEnabled: true,
+ },
+ bid: openrtb2.Bid{
+ AdM: `sample_creative`,
+ },
+ seat: string(openrtb_ext.BidderIx),
+ },
+ want: want{
+ adm: `sample_creative`,
+ },
+ },
+ {
+ name: "app_platform_partner_other_than_pubmatic_imp_counting_method_disabled",
+ args: args{
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
+ ImpCountingMethodEnabledBidders: map[string]struct{}{
+ string(openrtb_ext.BidderIx): {},
+ },
+ },
+ tracker: models.OWTracker{
+ TrackerURL: `Tracking URL`,
+ },
+ bid: openrtb2.Bid{
+ AdM: `sample_creative`,
+ },
+ seat: string(openrtb_ext.BidderAppnexus),
+ },
+ want: want{
+ adm: `sample_creative`,
+ },
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotAdm, gotBurl := injectBannerTracker(tt.args.rctx, tt.args.tracker, tt.args.bid, tt.args.seat, tt.args.pixels)
- assert.Equal(t, tt.wantAdm, gotAdm)
- assert.Equal(t, tt.wantBurl, gotBurl)
+ assert.Equal(t, tt.want.adm, gotAdm)
+ assert.Equal(t, tt.want.burl, gotBurl)
})
}
}
-func Test_trackerWithOM(t *testing.T) {
+func TestTrackerWithOM(t *testing.T) {
type args struct {
- tracker models.OWTracker
- platform string
- bidderCode string
+ rctx models.RequestCtx
+ prebidPartnerName string
+ dspID int
}
tests := []struct {
name string
@@ -131,54 +188,81 @@ func Test_trackerWithOM(t *testing.T) {
want bool
}{
{
- name: "in-app_partner_otherthan_pubmatic",
+ name: "in-app_partner_other_than_pubmatic",
args: args{
- tracker: models.OWTracker{
- DspId: models.DspId_DV360,
+
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
},
- platform: models.PLATFORM_APP,
- bidderCode: "test",
+ prebidPartnerName: "test",
},
want: false,
},
{
name: "in-app_partner_pubmatic_other_dv360",
args: args{
- tracker: models.OWTracker{
- DspId: -1,
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
},
- platform: models.PLATFORM_APP,
- bidderCode: models.BidderPubMatic,
+ prebidPartnerName: models.BidderPubMatic,
+ dspID: -1,
},
want: false,
},
{
name: "display_partner_pubmatic_dv360",
args: args{
- tracker: models.OWTracker{
- DspId: models.DspId_DV360,
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_DISPLAY,
},
- platform: models.PLATFORM_DISPLAY,
- bidderCode: models.BidderPubMatic,
+ prebidPartnerName: models.BidderPubMatic,
+ dspID: models.DspId_DV360,
},
want: false,
},
{
name: "in-app_partner_pubmatic_dv360",
args: args{
- tracker: models.OWTracker{
- DspId: models.DspId_DV360,
+
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
+ },
+ prebidPartnerName: models.BidderPubMatic,
+ dspID: models.DspId_DV360,
+ },
+ want: true,
+ },
+ {
+ name: "in-app_partner_other_than_pubmatic_imp_counting_method_enabled",
+ args: args{
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
+ ImpCountingMethodEnabledBidders: map[string]struct{}{
+ "ix": {},
+ },
},
- platform: models.PLATFORM_APP,
- bidderCode: models.BidderPubMatic,
+ prebidPartnerName: "ix",
},
want: true,
},
+ {
+ name: "in-app_partner_other_than_pubmatic_imp_counting_method_disabled",
+ args: args{
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
+ ImpCountingMethodEnabledBidders: map[string]struct{}{
+ "ix": {},
+ },
+ },
+ prebidPartnerName: "magnite",
+ },
+ want: false,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if got := trackerWithOM(tt.args.tracker, tt.args.platform, tt.args.bidderCode); got != tt.want {
- t.Errorf("trackerWithOM() = %v, want %v", got, tt.want)
+ if got := trackerWithOM(tt.args.rctx, tt.args.prebidPartnerName, tt.args.dspID); got != tt.want {
+ assert.Equal(t, tt.want, got)
}
})
}
diff --git a/modules/pubmatic/openwrap/tracker/create.go b/modules/pubmatic/openwrap/tracker/create.go
index 5c1410ff3b7..9ed7bae433c 100644
--- a/modules/pubmatic/openwrap/tracker/create.go
+++ b/modules/pubmatic/openwrap/tracker/create.go
@@ -214,7 +214,7 @@ func createTrackers(rctx models.RequestCtx, trackers map[string]models.OWTracker
PriceCurrency: bidResponse.Cur,
ErrorURL: constructVideoErrorURL(rctx, rctx.VideoErrorTrackerEndpoint, bid, tracker),
BidType: adformat,
- DspId: dspId,
+ IsOMEnabled: trackerWithOM(rctx, partnerID, dspId),
}
}
}
diff --git a/modules/pubmatic/openwrap/tracker/inject.go b/modules/pubmatic/openwrap/tracker/inject.go
index 06cb70c25e3..bd050200c6f 100644
--- a/modules/pubmatic/openwrap/tracker/inject.go
+++ b/modules/pubmatic/openwrap/tracker/inject.go
@@ -3,10 +3,12 @@ package tracker
import (
"errors"
"fmt"
+ "net/url"
"strings"
"golang.org/x/exp/slices"
+ "github.com/buger/jsonparser"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
@@ -20,8 +22,10 @@ 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
- var err error
+ var (
+ errMsg string
+ err error
+ )
tracker := rctx.Trackers[bid.ID]
adformat := tracker.BidType
if rctx.Platform == models.PLATFORM_VIDEO {
@@ -32,6 +36,9 @@ func InjectTrackers(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) (
switch adformat {
case models.Banner:
bidResponse.SeatBid[i].Bid[j].AdM, bidResponse.SeatBid[i].Bid[j].BURL = injectBannerTracker(rctx, tracker, bid, seatBid.Seat, pixels)
+ if tracker.IsOMEnabled {
+ bidResponse.SeatBid[i].Bid[j].Ext, err = jsonparser.Set(bid.Ext, []byte(`1`), models.ImpCountingMethod)
+ }
case models.Video:
trackers := []models.OWTracker{tracker}
bidResponse.SeatBid[i].Bid[j].AdM, bidResponse.SeatBid[i].Bid[j].BURL, err = injectVideoCreativeTrackers(rctx, bid, trackers)
@@ -91,5 +98,6 @@ func getBURL(burl, trackerURL string) string {
return trackerURL
}
- return trackerURL + "&" + models.OwSspBurl + "=" + burl
+ escapedBurl := url.QueryEscape(burl)
+ return trackerURL + "&" + models.OwSspBurl + "=" + escapedBurl
}
diff --git a/modules/pubmatic/openwrap/tracker/inject_test.go b/modules/pubmatic/openwrap/tracker/inject_test.go
index 0eed8b3e37a..397f761ef66 100644
--- a/modules/pubmatic/openwrap/tracker/inject_test.go
+++ b/modules/pubmatic/openwrap/tracker/inject_test.go
@@ -8,6 +8,7 @@ import (
mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/stretchr/testify/assert"
)
@@ -343,10 +344,10 @@ func TestInjectTrackers(t *testing.T) {
Platform: models.PLATFORM_APP,
Trackers: map[string]models.OWTracker{
"12345": {
- BidType: "banner",
- TrackerURL: `Tracking URL`,
- ErrorURL: `Error URL`,
- DspId: -1,
+ BidType: "banner",
+ TrackerURL: `Tracking URL`,
+ ErrorURL: `Error URL`,
+ IsOMEnabled: false,
},
},
},
@@ -386,10 +387,10 @@ func TestInjectTrackers(t *testing.T) {
Platform: models.PLATFORM_APP,
Trackers: map[string]models.OWTracker{
"12345": {
- BidType: "banner",
- TrackerURL: `Tracking URL`,
- ErrorURL: `Error URL`,
- DspId: models.DspId_DV360,
+ BidType: "banner",
+ TrackerURL: `Tracking URL`,
+ ErrorURL: `Error URL`,
+ IsOMEnabled: true,
},
},
},
@@ -400,6 +401,7 @@ func TestInjectTrackers(t *testing.T) {
{
ID: "12345",
AdM: `sample_creative`,
+ Ext: []byte(`{"key":"value"}`),
},
},
Seat: models.BidderPubMatic,
@@ -414,6 +416,7 @@ func TestInjectTrackers(t *testing.T) {
{
ID: "12345",
AdM: `sample_creative`,
+ Ext: []byte(`{"key":"value","imp_ct_mthd":1}`),
},
},
Seat: models.BidderPubMatic,
@@ -548,7 +551,7 @@ func TestInjectTrackers(t *testing.T) {
Bid: []openrtb2.Bid{
{
ID: "12345",
- BURL: `Tracking URL&owsspburl=http://burl.com`,
+ BURL: `Tracking URL&owsspburl=http%3A%2F%2Fburl.com`,
AdM: ``,
},
},
@@ -591,7 +594,7 @@ func TestInjectTrackers(t *testing.T) {
Bid: []openrtb2.Bid{
{
ID: "12345",
- BURL: `Tracking URL&owsspburl=http://burl.com`,
+ BURL: `Tracking URL&owsspburl=http%3A%2F%2Fburl.com`,
AdM: ``,
},
},
@@ -643,7 +646,7 @@ func TestInjectTrackers(t *testing.T) {
{
ID: "12345",
ImpID: "imp123",
- BURL: `Tracking URL&owsspburl=http://burl.com`,
+ BURL: `Tracking URL&owsspburl=http%3A%2F%2Fburl.com`,
AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
},
},
@@ -911,6 +914,54 @@ func TestInjectTrackers(t *testing.T) {
},
wantErr: false,
},
+ {
+ name: "platform_is_app_with_imp_counting_method_enabled_ix",
+ args: args{
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
+ Trackers: map[string]models.OWTracker{
+ "12345": {
+ BidType: "banner",
+ TrackerURL: `Tracking URL`,
+ ErrorURL: `Error URL`,
+ IsOMEnabled: true,
+ },
+ },
+ ImpCountingMethodEnabledBidders: map[string]struct{}{
+ string(openrtb_ext.BidderIx): {},
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ AdM: `sample_creative`,
+ Ext: []byte(`{"key":"value"}`),
+ },
+ },
+ Seat: string(openrtb_ext.BidderIx),
+ },
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ AdM: `sample_creative`,
+ Ext: []byte(`{"key":"value","imp_ct_mthd":1}`),
+ },
+ },
+ Seat: string(openrtb_ext.BidderIx),
+ },
+ },
+ },
+ wantErr: false,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -1138,10 +1189,10 @@ func Test_getBurlAppLovinMax(t *testing.T) {
{
name: "valid_burl_and_tracker_url",
args: args{
- burl: `sampleBurl.com`,
+ burl: `https://abc.xyz.com/AdServer/AdDisplayTrackerServlet?operId=1&pubId=161527&siteId=991727&adId=4695996&imprId=B430AE6F-4768-41D0-BC55-8CF9D5DD4DA6&cksum=41C0F6460C2ACF7F&adType=10&adServerId=243&kefact=0.095500&kaxefact=0.095500&kadNetFrequecy=0&kadwidth=300&kadheight=250&kadsizeid=9&kltstamp=1721827593&indirectAdId=0`,
TrackerURL: `sampleTracker.com?id=123`,
},
- want: `sampleTracker.com?id=123&owsspburl=sampleBurl.com`,
+ want: `sampleTracker.com?id=123&owsspburl=https%3A%2F%2Fabc.xyz.com%2FAdServer%2FAdDisplayTrackerServlet%3FoperId%3D1%26pubId%3D161527%26siteId%3D991727%26adId%3D4695996%26imprId%3DB430AE6F-4768-41D0-BC55-8CF9D5DD4DA6%26cksum%3D41C0F6460C2ACF7F%26adType%3D10%26adServerId%3D243%26kefact%3D0.095500%26kaxefact%3D0.095500%26kadNetFrequecy%3D0%26kadwidth%3D300%26kadheight%3D250%26kadsizeid%3D9%26kltstamp%3D1721827593%26indirectAdId%3D0`,
},
}
for _, tt := range tests {
diff --git a/modules/pubmatic/openwrap/tracker/native_test.go b/modules/pubmatic/openwrap/tracker/native_test.go
index 3c8a030d445..5b1d1ef1b37 100644
--- a/modules/pubmatic/openwrap/tracker/native_test.go
+++ b/modules/pubmatic/openwrap/tracker/native_test.go
@@ -36,7 +36,7 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
},
endpoint: models.EndpointAppLovinMax,
},
- wantBurl: `t.pubmatic.com/track?tid=1234&owsspburl=http://burl.com`,
+ wantBurl: `t.pubmatic.com/track?tid=1234&owsspburl=http%3A%2F%2Fburl.com`,
wantAdm: ``,
wantErr: false,
},
diff --git a/modules/pubmatic/openwrap/tracker/video_test.go b/modules/pubmatic/openwrap/tracker/video_test.go
index 7a4599335d5..b8629f1afc9 100644
--- a/modules/pubmatic/openwrap/tracker/video_test.go
+++ b/modules/pubmatic/openwrap/tracker/video_test.go
@@ -289,7 +289,7 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
},
},
},
- wantAdm: ``,
+ wantAdm: ` `,
wantErr: false,
},
{
@@ -311,7 +311,7 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
Endpoint: models.EndpointAppLovinMax,
},
},
- wantBurl: "Tracking URL&owsspburl=https://burl.com",
+ wantBurl: "Tracking URL&owsspburl=https%3A%2F%2Fburl.com",
wantAdm: ``,
wantErr: false,
},
@@ -334,7 +334,7 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
Endpoint: models.EndpointAppLovinMax,
},
},
- wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantBurl: "Tracker URL&owsspburl=https%3A%2F%2Fburl.com",
wantAdm: ``,
wantErr: false,
},
@@ -357,7 +357,7 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
Endpoint: models.EndpointAppLovinMax,
},
},
- wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantBurl: "Tracker URL&owsspburl=https%3A%2F%2Fburl.com",
wantAdm: ``,
wantErr: false,
},
@@ -380,7 +380,7 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
Endpoint: models.EndpointAppLovinMax,
},
},
- wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantBurl: "Tracker URL&owsspburl=https%3A%2F%2Fburl.com",
wantAdm: ``,
wantErr: false,
},
@@ -403,7 +403,7 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
Endpoint: models.EndpointAppLovinMax,
},
},
- wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantBurl: "Tracker URL&owsspburl=https%3A%2F%2Fburl.com",
wantAdm: ``,
wantErr: false,
},
@@ -426,7 +426,7 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
Endpoint: models.EndpointAppLovinMax,
},
},
- wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantBurl: "Tracker URL&owsspburl=https%3A%2F%2Fburl.com",
wantAdm: ``,
wantErr: false,
},
@@ -448,8 +448,8 @@ func TestInjectVideoCreativeTrackers(t *testing.T) {
Endpoint: models.EndpointAppLovinMax,
},
},
- wantBurl: "Tracker URL&owsspburl=https://burl.com",
- wantAdm: ``,
+ wantBurl: "Tracker URL&owsspburl=https%3A%2F%2Fburl.com",
+ wantAdm: ` `,
wantErr: false,
},
}
diff --git a/modules/pubmatic/openwrap/unwrap/unwrap.go b/modules/pubmatic/openwrap/unwrap/unwrap.go
index ef002929116..24c5b24ba38 100644
--- a/modules/pubmatic/openwrap/unwrap/unwrap.go
+++ b/modules/pubmatic/openwrap/unwrap/unwrap.go
@@ -40,21 +40,17 @@ func NewUnwrap(Endpoint string, DefaultTime int, handler http.HandlerFunc, Metri
}
-func (uw Unwrap) Unwrap(accountID, bidder string, bid *adapters.TypedBid, userAgent, ip string, isStatsEnabled bool) {
+func (uw Unwrap) Unwrap(bid *adapters.TypedBid, accountID, bidder, userAgent, ip string) (unwrapStatus string) {
startTime := time.Now()
var wrapperCnt int64
- var respStatus string
- if bid == nil || bid.Bid == nil || bid.Bid.AdM == "" {
- return
- }
defer func() {
if r := recover(); r != nil {
glog.Errorf("AdM:[%s] Error:[%v] stacktrace:[%s]", bid.Bid.AdM, r, string(debug.Stack()))
}
respTime := time.Since(startTime)
uw.metricEngine.RecordUnwrapRequestTime(accountID, bidder, respTime)
- uw.metricEngine.RecordUnwrapRequestStatus(accountID, bidder, respStatus)
- if respStatus == "0" {
+ uw.metricEngine.RecordUnwrapRequestStatus(accountID, bidder, unwrapStatus)
+ if unwrapStatus == "0" {
uw.metricEngine.RecordUnwrapWrapperCount(accountID, bidder, strconv.Itoa(int(wrapperCnt)))
uw.metricEngine.RecordUnwrapRespTime(accountID, strconv.Itoa(int(wrapperCnt)), respTime)
}
@@ -76,13 +72,14 @@ func (uw Unwrap) Unwrap(accountID, bidder string, bid *adapters.TypedBid, userAg
httpReq.Header = headers
httpResp := NewCustomRecorder()
uw.unwrapRequest(httpResp, httpReq)
- respStatus = httpResp.Header().Get(models.UnwrapStatus)
+ unwrapStatus = httpResp.Header().Get(models.UnwrapStatus)
wrapperCnt, _ = strconv.ParseInt(httpResp.Header().Get(models.UnwrapCount), 10, 0)
- if !isStatsEnabled && httpResp.Code == http.StatusOK && respStatus == models.UnwrapSucessStatus {
+ if httpResp.Code == http.StatusOK && unwrapStatus == models.UnwrapSucessStatus {
respBody := httpResp.Body.Bytes()
bid.Bid.AdM = string(respBody)
}
- glog.V(models.LogLevelDebug).Infof("[VAST_UNWRAPPER] pubid:[%v] bidder:[%v] impid:[%v] bidid:[%v] status_code:[%v] wrapper_cnt:[%v] httpRespCode= [%v] statsEnabled:[%v]",
- accountID, bidder, bid.Bid.ImpID, bid.Bid.ID, respStatus, wrapperCnt, httpResp.Code, isStatsEnabled)
+ glog.V(models.LogLevelDebug).Infof("[VAST_UNWRAPPER] pubid:[%v] bidder:[%v] impid:[%v] bidid:[%v] status_code:[%v] wrapper_cnt:[%v] httpRespCode= [%v]",
+ accountID, bidder, bid.Bid.ImpID, bid.Bid.ID, unwrapStatus, wrapperCnt, httpResp.Code)
+ return unwrapStatus
}
diff --git a/modules/pubmatic/openwrap/unwrap/unwrap_test.go b/modules/pubmatic/openwrap/unwrap/unwrap_test.go
index a7f3e7be050..763ba071c8c 100644
--- a/modules/pubmatic/openwrap/unwrap/unwrap_test.go
+++ b/modules/pubmatic/openwrap/unwrap/unwrap_test.go
@@ -8,7 +8,6 @@ import (
"github.com/golang/mock/gomock"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/adapters"
- metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics"
mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock"
"github.com/stretchr/testify/assert"
)
@@ -18,35 +17,32 @@ var invalidVastXMLAdM = "PubMaticAcudeo CompatibleVAST 2.0 Instream Test 1VAST 2.0 Instream Test 1https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&er=[ERRORCODE]https://track.dsptracker.com?p=1234&er=[ERRORCODE]https://aktrack.pubmatic.com/AdServer/AdDisplayTrackerServlet?operId=1&pubId=64195&siteId=47105&adId=1405154&adType=13&adServerId=243&kefact=1.000000&kaxefact=1.000000&kadNetFrequecy=0&kadwidth=0&kadheight=0&kadsizeid=97&kltstamp=1536933242&indirectAdId=0&adServerOptimizerId=2&ranreq=0.05969169352174375&kpbmtpfact=11.000000&dcId=1&tldId=0&passback=0&svr=ktk57&ekefact=er2bW2sDAwCra06ACbsIQySn5nqBtYsTl8fy5lupAexh37D_&ekaxefact=er2bW4EDAwB_LQpJJ23Fq0DcNC-NSAFXdpSQC8XBk_S33_Fa&ekpbmtpfact=er2bW5MDAwDJHdBnLBt5IrRuh7x0oqp_tjIALv_VvSQDAl6R&crID=m:1_x:3_y:3_p:11_va:3&lpu=ae.com&ucrid=678722001014421372&campaignId=16774&creativeId=0&pctr=0.000000&wDSPByrId=511&wDspId=27&wbId=0&wrId=0&wAdvID=3170&isRTB=1&rtbId=EBCA079F-8D7C-45B8-B733-92951F670AA1&imprId=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&oid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&pageURL=http%253A%252F%252Fowsdk-stagingams.pubmatic.com%253A8443%252Fvast-validator%252F%2523&sec=1&pmc=1https://DspImpressionTracker.com/https://mytracking.com/linear/closehttps://mytracking.com/linear/skiphttps://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=1https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=2https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=3https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=4https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=5https://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=600:00:04https://www.automationtester.inhttps://aktrack.pubmatic.com/track?operId=7&p=64195&s=47105&a=1405154&wa=243&ts=1536933242&wc=16774&crId=m:1_x:3_y:3_p:11_va:3&ucrid=678722001014421372&impid=24D9FEDA-C97D-4DF7-B747-BD3CFF5AC7B5&advertiser_id=3170&ecpm=1.000000&e=99https://stagingams.pubmatic.com:8443/openwrap/media/pubmatic.mp4https://stagingams.pubmatic.com:8443/openwrap/media/pubmatic.mp4https://stagingams.pubmatic.com:8443/openwrap/media/mp4-sample-3.mp4"
func TestUnwrap_Unwrap(t *testing.T) {
-
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockMetricsEngine := mock_metrics.NewMockMetricsEngine(ctrl)
type fields struct {
- endpoint string
- defaultTime int
- metricEngine metrics.MetricsEngine
- unwrapRequest http.HandlerFunc
+ endpoint string
}
type args struct {
- accountID string
- bidder string
- bid *adapters.TypedBid
- userAgent string
- ip string
- isStatsEnabled bool
+ accountID string
+ bidder string
+ bid *adapters.TypedBid
+ userAgent string
+ ip string
}
tests := []struct {
- name string
- fields fields
- args args
- setup func()
- mockHandler http.HandlerFunc
- expectedAdm string
+ name string
+ fields fields
+ args args
+ setup func()
+ mockHandler http.HandlerFunc
+ expectedAdm string
+ expectedUnwrapStatus string
}{
{
- name: "Stats enabled only",
+ name: "Unwrap enabled with valid adm",
+ fields: fields{endpoint: "http://localhost:8001/unwrap"},
args: args{
accountID: "5890",
bidder: "pubmatic",
@@ -55,9 +51,8 @@ func TestUnwrap_Unwrap(t *testing.T) {
AdM: vastXMLAdM,
},
},
- userAgent: "UA",
- ip: "10.12.13.14",
- isStatsEnabled: true,
+ userAgent: "UA",
+ ip: "10.12.13.14",
},
setup: func() {
mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0")
@@ -69,40 +64,39 @@ func TestUnwrap_Unwrap(t *testing.T) {
w.Header().Add("unwrap-status", "0")
w.Header().Add("unwrap-count", "1")
w.WriteHeader(http.StatusOK)
- _, _ = w.Write([]byte(vastXMLAdM))
+ _, _ = w.Write([]byte(inlineXMLAdM))
}),
- expectedAdm: vastXMLAdM,
+ expectedAdm: inlineXMLAdM,
+ expectedUnwrapStatus: "0",
},
{
- name: "Unwrap enabled with valid adm",
+ name: "Unwrap enabled with invalid adm",
+ fields: fields{endpoint: "http://localhost:8001/unwrap"},
args: args{
accountID: "5890",
bidder: "pubmatic",
bid: &adapters.TypedBid{
Bid: &openrtb2.Bid{
- AdM: vastXMLAdM,
+ AdM: invalidVastXMLAdM,
},
},
- userAgent: "UA",
- ip: "10.12.13.14",
- isStatsEnabled: false,
+ userAgent: "UA",
+ ip: "10.12.13.14",
},
setup: func() {
- mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "0")
- mockMetricsEngine.EXPECT().RecordUnwrapWrapperCount("5890", "pubmatic", "1")
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "1")
mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
- mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any())
},
mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
- w.Header().Add("unwrap-status", "0")
- w.Header().Add("unwrap-count", "1")
- w.WriteHeader(http.StatusOK)
- _, _ = w.Write([]byte(inlineXMLAdM))
+ w.Header().Add("unwrap-status", "1")
+ w.WriteHeader(http.StatusNoContent)
}),
- expectedAdm: inlineXMLAdM,
+ expectedAdm: invalidVastXMLAdM,
+ expectedUnwrapStatus: "1",
},
{
- name: "Unwrap enabled with invalid adm",
+ name: "Error while forming the HTTPRequest for unwrap process",
+ fields: fields{endpoint: ":"},
args: args{
accountID: "5890",
bidder: "pubmatic",
@@ -111,33 +105,29 @@ func TestUnwrap_Unwrap(t *testing.T) {
AdM: invalidVastXMLAdM,
},
},
- userAgent: "UA",
- ip: "10.12.13.14",
- isStatsEnabled: false,
+ userAgent: "UA",
+ ip: "10.12.13.14",
},
setup: func() {
- mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "1")
+ mockMetricsEngine.EXPECT().RecordUnwrapRequestStatus("5890", "pubmatic", "")
mockMetricsEngine.EXPECT().RecordUnwrapRequestTime("5890", "pubmatic", gomock.Any())
},
- mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
- w.Header().Add("unwrap-status", "1")
- w.WriteHeader(http.StatusNoContent)
- }),
- expectedAdm: invalidVastXMLAdM,
+ mockHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {}),
+ expectedAdm: invalidVastXMLAdM,
+ expectedUnwrapStatus: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
-
if tt.setup != nil {
tt.setup()
}
- uw := NewUnwrap("http://localhost:8001/unwrap", 200, tt.mockHandler, mockMetricsEngine)
- uw.Unwrap(tt.args.accountID, tt.args.bidder, tt.args.bid, tt.args.userAgent, tt.args.ip, tt.args.isStatsEnabled)
- if !tt.args.isStatsEnabled && strings.Compare(tt.args.bid.Bid.AdM, tt.expectedAdm) != 0 {
+ uw := NewUnwrap(tt.fields.endpoint, 200, tt.mockHandler, mockMetricsEngine)
+ unwrapStatus := uw.Unwrap(tt.args.bid, tt.args.accountID, tt.args.bidder, tt.args.userAgent, tt.args.ip)
+ if strings.Compare(tt.args.bid.Bid.AdM, tt.expectedAdm) != 0 {
assert.Equal(t, inlineXMLAdM, tt.args.bid.Bid.AdM, "AdM is not updated correctly after unwrap ")
-
}
+ assert.Equal(t, tt.expectedUnwrapStatus, unwrapStatus, "mismatched unwrap status")
})
}
}
diff --git a/openrtb_ext/fastxml_ow.go b/openrtb_ext/fastxml_ow.go
new file mode 100644
index 00000000000..30e55ba11b4
--- /dev/null
+++ b/openrtb_ext/fastxml_ow.go
@@ -0,0 +1,241 @@
+package openrtb_ext
+
+import (
+ "bufio"
+ "fmt"
+ "math/rand"
+ "os"
+ "path/filepath"
+ "runtime/debug"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/golang/glog"
+)
+
+type RandomGenerator interface {
+ GenerateIntn(int) int
+}
+
+type RandomNumberGenerator struct{}
+
+func (RandomNumberGenerator) GenerateIntn(n int) int {
+ return rand.Intn(n)
+}
+
+var pid = os.Getpid()
+
+const maxFileSize = 1 * 1024 * 1024 * 1024
+const maxBufferSize = 256 * 1024
+const maxFiles = 10
+const flushInterval = time.Second * time.Duration(300)
+
+// Writer interface can be used to define variable returned by GetWriter() method
+type Writer interface {
+ Write(data []byte) (int, error)
+ Sync() error
+}
+
+// FileWriter ...
+type FileWriter struct {
+ mu sync.Mutex
+ file Writer
+ fileName string
+}
+
+// NewFileWriter ...
+func NewFileWriter(dirPath, fileName, ext string) Writer {
+ //create directory if not exists
+ _ = os.MkdirAll(dirPath, 0755)
+
+ writer := &FileWriter{
+ mu: sync.Mutex{},
+ file: NewBufferFileWriter(dirPath, fileName, ext),
+ fileName: fileName,
+ }
+
+ go purge(dirPath, fileName, ext)
+ go writer.flush(flushInterval)
+
+ return writer
+}
+
+// Flushd ...
+func (f *FileWriter) flush(t time.Duration) {
+ defer func() {
+ if errInterface := recover(); errInterface != nil {
+ glog.Infof("Recovered panic \n Error: %v \n StackTrace: %v", errInterface, string(debug.Stack()))
+ }
+ }()
+
+ for {
+ f.Sync()
+ time.Sleep(t)
+ }
+}
+
+// Sync ...
+func (f *FileWriter) Sync() (err error) {
+ f.mu.Lock()
+ err = f.file.Sync()
+ f.mu.Unlock()
+ return err
+}
+
+// Write ...
+func (f *FileWriter) Write(data []byte) (n int, err error) {
+ f.mu.Lock()
+ n, err = f.file.Write(data)
+ f.mu.Unlock()
+ return n, err
+}
+
+// purge files
+func purge(dirPath, fileName, ext string) {
+ fileFormat := dirPath + fileName + "*" + ext
+ for {
+ _purge(fileFormat, maxFiles)
+ time.Sleep(flushInterval)
+ }
+}
+
+func _purge(fileFormat string, maxFiles int) {
+ defer func() {
+ if errInterface := recover(); errInterface != nil {
+ glog.Infof("Recovered panic \n Error: %v \n StackTrace: %v", errInterface, string(debug.Stack()))
+ }
+ }()
+
+ files, _ := filepath.Glob(fileFormat)
+ sort.Strings(files)
+
+ //remove last files
+ if len(files) <= maxFiles {
+ //no files to purge
+ return
+ }
+
+ //limit files to max files
+ files = files[:len(files)-maxFiles]
+ for _, file := range files {
+ glog.Infof("[purger] filename:[%s]\n", file)
+ if err := os.Remove(file); err != nil {
+ glog.Infof("[purger] error:[purge_failed] file:[%s] message:[%s]", file, err.Error())
+ //do not delete status file if original file not deleted
+ continue
+ }
+ }
+}
+
+// bufferFileWriter ...
+type bufferFileWriter struct {
+ dirPath, fileName, ext string
+
+ buf *bufio.Writer
+ file *os.File
+ nbytes uint64
+}
+
+func NewBufferFileWriter(dirPath, fileName, ext string) *bufferFileWriter {
+ writer := &bufferFileWriter{
+ dirPath: dirPath,
+ fileName: fileName,
+ ext: ext,
+ }
+ return writer
+}
+
+// Sync ...
+func (b *bufferFileWriter) Sync() (err error) {
+ if b.buf != nil {
+ if err = b.buf.Flush(); err != nil {
+ return err
+ }
+ }
+ if b.file != nil {
+ if err = b.file.Sync(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Write ...
+func (b *bufferFileWriter) Write(data []byte) (int, error) {
+ if b.file == nil {
+ //create new file
+ if err := b.create(time.Now()); err != nil {
+ return 0, err
+ }
+ }
+
+ if b.nbytes+uint64(len(data)) >= maxFileSize {
+ //rotate file
+ if err := b.create(time.Now()); err != nil {
+ return 0, err
+ }
+ }
+
+ n, err := b.buf.Write(data)
+ b.nbytes += uint64(n)
+ if err != nil {
+ return 0, err
+ }
+
+ return n, nil
+}
+
+func (b *bufferFileWriter) create(t time.Time) (err error) {
+ if b.file != nil {
+ if err = b.buf.Flush(); err != nil {
+ return err
+ }
+
+ if err = b.file.Close(); err != nil {
+ return err
+ }
+ }
+
+ fname := filepath.Join(b.dirPath, fileNameFormat(b.fileName, b.ext, t))
+ b.file, err = os.Create(fname)
+ b.nbytes = 0
+ if err != nil {
+ return err
+ }
+
+ glog.Infof("[file_writer] type:[new_file] filename:[%s]\n", fname)
+ b.buf = bufio.NewWriterSize(b.file, int(maxBufferSize))
+ return err
+}
+
+func fileNameFormat(name, ext string, t time.Time) string {
+ return fmt.Sprintf("%s.%04d%02d%02d-%02d%02d%02d.%d%s",
+ name,
+ t.Year(),
+ t.Month(),
+ t.Day(),
+ t.Hour(),
+ t.Minute(),
+ t.Second(),
+ pid,
+ ext)
+}
+
+func IsFastXMLEnabled(enabledPercentage int) bool {
+ return enabledPercentage > 0 && enabledPercentage >= rg.GenerateIntn(enabledPercentage)
+}
+
+func FastXMLLogf(format string, args ...any) {
+ if bfw != nil {
+ fmt.Fprintf(bfw, format, args...)
+ }
+}
+
+var rg RandomGenerator
+var bfw Writer
+
+func init() {
+ rg = &RandomNumberGenerator{}
+ bfw = NewFileWriter(`/var/log/ssheaderbidding/`, `fastxml`, `.txt`)
+}