Skip to content

Commit 27ec65d

Browse files
guscarreonGus CarreonGus CarreonGus Carreon
authored
Simplifying exchange module: bidResponseExt gets built anyway (#1518)
* first draft * Scott's feedback * stepping out real quick * add cache errors to bidResponseExt before marshalling * Removed vim's swp file Co-authored-by: Gus Carreon <[email protected]> Co-authored-by: Gus Carreon <[email protected]> Co-authored-by: Gus Carreon <[email protected]>
1 parent 0a34a01 commit 27ec65d

File tree

2 files changed

+70
-64
lines changed

2 files changed

+70
-64
lines changed

exchange/exchange.go

Lines changed: 65 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ func NewExchange(client *http.Client, cache prebid_cache_client.Client, cfg *con
9696

9797
func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidRequest, usersyncs IdFetcher, labels pbsmetrics.Labels, account *config.Account, categoriesFetcher *stored_requests.CategoryFetcher, debugLog *DebugLog) (*openrtb.BidResponse, error) {
9898

99+
var err error
99100
requestExt, err := extractBidRequestExt(bidRequest)
100101
if err != nil {
101102
return nil, err
@@ -114,34 +115,11 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
114115

115116
bidAdjustmentFactors := getExtBidAdjustmentFactors(requestExt)
116117

117-
for _, impInRequest := range bidRequest.Imp {
118-
var impLabels pbsmetrics.ImpLabels = pbsmetrics.ImpLabels{
119-
BannerImps: impInRequest.Banner != nil,
120-
VideoImps: impInRequest.Video != nil,
121-
AudioImps: impInRequest.Audio != nil,
122-
NativeImps: impInRequest.Native != nil,
123-
}
124-
e.me.RecordImps(impLabels)
125-
}
118+
recordImpMetrics(bidRequest, e.me)
126119

127120
// Make our best guess if GDPR applies
128-
usersyncIfAmbiguous := e.UsersyncIfAmbiguous
129-
var geo *openrtb.Geo = nil
130-
if bidRequest.User != nil && bidRequest.User.Geo != nil {
131-
geo = bidRequest.User.Geo
132-
} else if bidRequest.Device != nil && bidRequest.Device.Geo != nil {
133-
geo = bidRequest.Device.Geo
134-
}
135-
if geo != nil {
136-
// If we have a country set, and it is on the list, we assume GDPR applies if not set on the request.
137-
// Otherwise we assume it does not apply as long as it appears "valid" (is 3 characters long).
138-
if _, found := e.privacyConfig.GDPR.EEACountriesMap[strings.ToUpper(geo.Country)]; found {
139-
usersyncIfAmbiguous = false
140-
} else if len(geo.Country) == 3 {
141-
// The country field is formatted properly as a three character country code
142-
usersyncIfAmbiguous = true
143-
}
144-
}
121+
usersyncIfAmbiguous := e.parseUsersyncIfAmbiguous(bidRequest)
122+
145123
// Slice of BidRequests, each a copy of the original cleaned to only contain bidder data for the named bidder
146124
blabels := make(map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels)
147125
cleanRequests, aliases, privacyLabels, errs := cleanOpenRTBRequests(ctx, bidRequest, requestExt, usersyncs, blabels, labels, e.gDPR, usersyncIfAmbiguous, e.privacyConfig)
@@ -161,14 +139,13 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
161139

162140
adapterBids, adapterExtra, anyBidsReturned := e.getAllBids(auctionCtx, cleanRequests, aliases, bidAdjustmentFactors, blabels, conversions)
163141

164-
var auc *auction = nil
165-
var bidResponseExt *openrtb_ext.ExtBidResponse = nil
142+
var auc *auction
143+
var cacheErrs []error
166144
if anyBidsReturned {
167145

168146
var bidCategory map[string]string
169147
//If includebrandcategory is present in ext then CE feature is on.
170148
if requestExt.Prebid.Targeting != nil && requestExt.Prebid.Targeting.IncludeBrandCategory != nil {
171-
var err error
172149
var rejections []string
173150
bidCategory, adapterBids, rejections, err = applyCategoryMapping(ctx, requestExt, adapterBids, *categoriesFetcher, targData)
174151
if err != nil {
@@ -189,42 +166,33 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
189166
errs = append(errs, dealErrs...)
190167
}
191168

192-
if debugLog != nil && debugLog.Enabled {
193-
bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, bidRequest, debugInfo, errs)
194-
if bidRespExtBytes, err := json.Marshal(bidResponseExt); err == nil {
195-
debugLog.Data.Response = string(bidRespExtBytes)
196-
} else {
197-
debugLog.Data.Response = "Unable to marshal response ext for debugging"
198-
errs = append(errs, errors.New(debugLog.Data.Response))
199-
}
200-
}
201-
202169
cacheErrs := auc.doCache(ctx, e.cache, targData, bidRequest, 60, &account.CacheTTL, bidCategory, debugLog)
203170
if len(cacheErrs) > 0 {
204171
errs = append(errs, cacheErrs...)
205172
}
206173
targData.setTargeting(auc, bidRequest.App != nil, bidCategory)
207174

208-
// Ensure caching errors are added if the bid response ext has already been created
209-
if bidResponseExt != nil && len(cacheErrs) > 0 {
210-
bidderCacheErrs := errsToBidderErrors(cacheErrs)
211-
bidResponseExt.Errors[openrtb_ext.PrebidExtKey] = append(bidResponseExt.Errors[openrtb_ext.PrebidExtKey], bidderCacheErrs...)
212-
}
213175
}
176+
}
214177

178+
bidResponseExt := e.makeExtBidResponse(adapterBids, adapterExtra, bidRequest, debugInfo, errs)
179+
180+
// Ensure caching errors are added in case auc.doCache was called and errors were returned
181+
if len(cacheErrs) > 0 {
182+
bidderCacheErrs := errsToBidderErrors(cacheErrs)
183+
bidResponseExt.Errors[openrtb_ext.PrebidExtKey] = append(bidResponseExt.Errors[openrtb_ext.PrebidExtKey], bidderCacheErrs...)
215184
}
216185

217-
if !anyBidsReturned {
218-
if debugLog != nil && debugLog.Enabled {
186+
if debugLog != nil && debugLog.Enabled {
187+
if bidRespExtBytes, err := json.Marshal(bidResponseExt); err == nil {
188+
debugLog.Data.Response = string(bidRespExtBytes)
189+
} else {
190+
debugLog.Data.Response = "Unable to marshal response ext for debugging"
191+
errs = append(errs, err)
192+
}
193+
if !anyBidsReturned {
219194
if rawUUID, err := uuid.NewV4(); err == nil {
220195
debugLog.CacheKey = rawUUID.String()
221-
222-
bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, bidRequest, debugInfo, errs)
223-
if bidRespExtBytes, err := json.Marshal(bidResponseExt); err == nil {
224-
debugLog.Data.Response = string(bidRespExtBytes)
225-
} else {
226-
debugLog.Data.Response = "Unable to marshal response ext for debugging"
227-
}
228196
} else {
229197
errs = append(errs, err)
230198
}
@@ -235,6 +203,41 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
235203
return e.buildBidResponse(ctx, liveAdapters, adapterBids, bidRequest, adapterExtra, auc, bidResponseExt, cacheInstructions.returnCreative, errs)
236204
}
237205

206+
func (e *exchange) parseUsersyncIfAmbiguous(bidRequest *openrtb.BidRequest) bool {
207+
usersyncIfAmbiguous := e.UsersyncIfAmbiguous
208+
var geo *openrtb.Geo = nil
209+
210+
if bidRequest.User != nil && bidRequest.User.Geo != nil {
211+
geo = bidRequest.User.Geo
212+
} else if bidRequest.Device != nil && bidRequest.Device.Geo != nil {
213+
geo = bidRequest.Device.Geo
214+
}
215+
if geo != nil {
216+
// If we have a country set, and it is on the list, we assume GDPR applies if not set on the request.
217+
// Otherwise we assume it does not apply as long as it appears "valid" (is 3 characters long).
218+
if _, found := e.privacyConfig.GDPR.EEACountriesMap[strings.ToUpper(geo.Country)]; found {
219+
usersyncIfAmbiguous = false
220+
} else if len(geo.Country) == 3 {
221+
// The country field is formatted properly as a three character country code
222+
usersyncIfAmbiguous = true
223+
}
224+
}
225+
226+
return usersyncIfAmbiguous
227+
}
228+
229+
func recordImpMetrics(bidRequest *openrtb.BidRequest, metricsEngine pbsmetrics.MetricsEngine) {
230+
for _, impInRequest := range bidRequest.Imp {
231+
var impLabels pbsmetrics.ImpLabels = pbsmetrics.ImpLabels{
232+
BannerImps: impInRequest.Banner != nil,
233+
VideoImps: impInRequest.Video != nil,
234+
AudioImps: impInRequest.Audio != nil,
235+
NativeImps: impInRequest.Native != nil,
236+
}
237+
metricsEngine.RecordImps(impLabels)
238+
}
239+
}
240+
238241
type DealTierInfo struct {
239242
Prefix string `json:"prefix"`
240243
MinDealTier int `json:"minDealTier"`
@@ -479,6 +482,7 @@ func errsToBidderErrors(errs []error) []openrtb_ext.ExtBidderError {
479482
// This piece takes all the bids supplied by the adapters and crafts an openRTB response to send back to the requester
480483
func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_ext.BidderName, adapterBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, bidRequest *openrtb.BidRequest, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, bidResponseExt *openrtb_ext.ExtBidResponse, returnCreative bool, errList []error) (*openrtb.BidResponse, error) {
481484
bidResponse := new(openrtb.BidResponse)
485+
var err error
482486

483487
bidResponse.ID = bidRequest.ID
484488
if len(liveAdapters) == 0 {
@@ -500,21 +504,19 @@ func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_
500504

501505
bidResponse.SeatBid = seatBids
502506

503-
if bidResponseExt == nil {
504-
contextDebugValue := ctx.Value(DebugContextKey)
505-
var debugInfo bool
506-
if contextDebugValue != nil {
507-
debugInfo = contextDebugValue.(bool)
508-
}
509-
bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, bidRequest, debugInfo, errList)
510-
}
507+
bidResponse.Ext, err = encodeBidResponseExt(bidResponseExt)
508+
509+
return bidResponse, err
510+
}
511+
512+
func encodeBidResponseExt(bidResponseExt *openrtb_ext.ExtBidResponse) ([]byte, error) {
511513
buffer := &bytes.Buffer{}
512514
enc := json.NewEncoder(buffer)
515+
513516
enc.SetEscapeHTML(false)
514517
err := enc.Encode(bidResponseExt)
515-
bidResponse.Ext = buffer.Bytes()
516518

517-
return bidResponse, err
519+
return buffer.Bytes(), err
518520
}
519521

520522
func applyCategoryMapping(ctx context.Context, requestExt *openrtb_ext.ExtRequest, seatBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, categoriesFetcher stored_requests.CategoryFetcher, targData *targetData) (map[string]string, map[openrtb_ext.BidderName]*pbsOrtbSeatBid, []string, error) {

exchange/exchange_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,9 +955,13 @@ func TestBidResponseCurrency(t *testing.T) {
955955
},
956956
}
957957

958+
bidResponseExt := &openrtb_ext.ExtBidResponse{
959+
ResponseTimeMillis: map[openrtb_ext.BidderName]int{openrtb_ext.BidderName("appnexus"): 5},
960+
RequestTimeoutMillis: 500,
961+
}
958962
// Run tests
959963
for i := range testCases {
960-
actualBidResp, err := e.buildBidResponse(context.Background(), liveAdapters, testCases[i].adapterBids, bidRequest, adapterExtra, nil, nil, true, errList)
964+
actualBidResp, err := e.buildBidResponse(context.Background(), liveAdapters, testCases[i].adapterBids, bidRequest, adapterExtra, nil, bidResponseExt, true, errList)
961965
assert.NoError(t, err, fmt.Sprintf("[TEST_FAILED] e.buildBidResponse resturns error in test: %s Error message: %s \n", testCases[i].description, err))
962966
assert.Equalf(t, testCases[i].expectedBidResponse, actualBidResp, fmt.Sprintf("[TEST_FAILED] Objects must be equal for test: %s \n Expected: >>%s<< \n Actual: >>%s<< ", testCases[i].description, testCases[i].expectedBidResponse.Ext, actualBidResp.Ext))
963967
}

0 commit comments

Comments
 (0)