Skip to content

Commit

Permalink
Debug warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
Veronika Solovei committed Mar 15, 2021
1 parent e53fd87 commit 2f66d76
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 95 deletions.
20 changes: 12 additions & 8 deletions endpoints/openrtb2/amp_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ import (
const defaultAmpRequestTimeoutMillis = 900

type AmpResponse struct {
Targeting map[string]string `json:"targeting"`
Debug *openrtb_ext.ExtResponseDebug `json:"debug,omitempty"`
Errors map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderError `json:"errors,omitempty"`
Warnings map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderError `json:"warnings,omitempty"`
Targeting map[string]string `json:"targeting"`
Debug *openrtb_ext.ExtResponseDebug `json:"debug,omitempty"`
Errors map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage `json:"errors,omitempty"`
Warnings map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage `json:"warnings,omitempty"`
}

// NewAmpEndpoint modifies the OpenRTB endpoint to handle AMP requests. This will basically modify the parsing
Expand Down Expand Up @@ -239,9 +239,12 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
ao.Errors = append(ao.Errors, fmt.Errorf("AMP response: failed to unpack OpenRTB response.ext, debug info cannot be forwarded: %v", eRErr))
}

warnings := make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderError)
warnings := extResponse.Warnings
if warnings == nil {
warnings = make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage)
}
for _, v := range errortypes.WarningOnly(errL) {
bidderErr := openrtb_ext.ExtBidderError{
bidderErr := openrtb_ext.ExtBidderMessage{
Code: errortypes.ReadCode(v),
Message: v.Error(),
}
Expand Down Expand Up @@ -528,8 +531,9 @@ func readPolicy(consent string) (privacy.PolicyWriter, error) {
return ccpa.ConsentWriter{consent}, nil
}

return privacy.NilPolicyWriter{}, &errortypes.InvalidPrivacyConsent{
Message: fmt.Sprintf("Consent '%s' is not recognized as either CCPA or GDPR TCF.", consent),
return privacy.NilPolicyWriter{}, &errortypes.Warning{
Message: fmt.Sprintf("Consent '%s' is not recognized as either CCPA or GDPR TCF.", consent),
WarningCode: errortypes.InvalidPrivacyConsentWarningCode,
}
}

Expand Down
4 changes: 2 additions & 2 deletions endpoints/openrtb2/amp_auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ func TestInvalidConsent(t *testing.T) {
}

// Assert Result
expectedWarnings := map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderError{
expectedWarnings := map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage{
openrtb_ext.BidderReservedGeneral: {
{
Code: 10001,
Expand Down Expand Up @@ -929,7 +929,7 @@ type mockAmpExchange struct {
lastRequest *openrtb.BidRequest
}

var expectedErrorsFromHoldAuction map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderError = map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderError{
var expectedErrorsFromHoldAuction map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage = map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage{
openrtb_ext.BidderName("openx"): {
{
Code: 1,
Expand Down
8 changes: 6 additions & 2 deletions endpoints/openrtb2/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
if errortypes.ContainsFatalError(errL) && writeError(errL, w, &labels) {
return
}
warnings := errortypes.WarningOnly(errL)

ctx := context.Background()

Expand Down Expand Up @@ -179,6 +180,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
Warnings: warnings,
}

response, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
Expand Down Expand Up @@ -363,8 +365,10 @@ func (deps *endpointDeps) validateRequest(req *openrtb.BidRequest) []error {
if ccpaPolicy, err := ccpa.ReadFromRequest(req); err != nil {
return append(errL, err)
} else if _, err := ccpaPolicy.Parse(exchange.GetValidBidders(aliases)); err != nil {
if _, invalidConsent := err.(*errortypes.InvalidPrivacyConsent); invalidConsent {
errL = append(errL, &errortypes.InvalidPrivacyConsent{Message: fmt.Sprintf("CCPA consent is invalid and will be ignored. (%v)", err)})
if _, invalidConsent := err.(*errortypes.Warning); invalidConsent {
errL = append(errL, &errortypes.Warning{
Message: fmt.Sprintf("CCPA consent is invalid and will be ignored. (%v)", err),
WarningCode: errortypes.InvalidPrivacyConsentWarningCode})
consentWriter := ccpa.ConsentWriter{Consent: ""}
if err := consentWriter.Write(req); err != nil {
return append(errL, fmt.Errorf("Unable to remove invalid CCPA consent from the request. (%v)", err))
Expand Down
52 changes: 51 additions & 1 deletion endpoints/openrtb2/auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,9 @@ func TestCCPAInvalid(t *testing.T) {

errL := deps.validateRequest(&req)

expectedWarning := errortypes.InvalidPrivacyConsent{Message: "CCPA consent is invalid and will be ignored. (request.regs.ext.us_privacy must contain 4 characters)"}
expectedWarning := errortypes.Warning{
Message: "CCPA consent is invalid and will be ignored. (request.regs.ext.us_privacy must contain 4 characters)",
WarningCode: errortypes.InvalidPrivacyConsentWarningCode}
assert.ElementsMatch(t, errL, []error{&expectedWarning})

assert.Empty(t, req.Regs.Ext, "Invalid Consent Removed From Request")
Expand Down Expand Up @@ -2104,6 +2106,54 @@ func TestIOS14EndToEnd(t *testing.T) {
assert.Equal(t, &lmtOne, result.Device.Lmt)
}

func TestAuctionWarnings(t *testing.T) {
reqBody := validRequest(t, "us-privacy-invalid.json")
deps := &endpointDeps{
&warningsCheckExchange{},
newParamsValidator(t),
&mockStoredReqFetcher{},
empty_fetcher.EmptyFetcher{},
empty_fetcher.EmptyFetcher{},
&config.Configuration{MaxRequestSize: int64(len(reqBody))},
newTestMetrics(),
analyticsConf.NewPBSAnalytics(&config.Analytics{}),
map[string]string{},
false,
[]byte{},
openrtb_ext.BuildBidderMap(),
nil,
nil,
hardcodedResponseIPValidator{response: true},
}

req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(reqBody))
recorder := httptest.NewRecorder()

deps.Auction(recorder, req, nil)

if recorder.Code != http.StatusOK {
t.Errorf("Endpoint should return a 200")
}
warnings := deps.ex.(*warningsCheckExchange).auctionRequest.Warnings
assert.Len(t, warnings, 1, "One warning should be returned from exchange")

actualWarning := warnings[0].(*errortypes.Warning)
expectedMessage := "CCPA consent is invalid and will be ignored. (request.regs.ext.us_privacy must contain 4 characters)"
assert.Equal(t, expectedMessage, actualWarning.Message, "Warning message is incorrect")

assert.Equal(t, errortypes.InvalidPrivacyConsentWarningCode, actualWarning.WarningCode, "Warning code is incorrect")
}

// warningsCheckExchange is a well-behaved exchange which stores all incoming warnings.
type warningsCheckExchange struct {
auctionRequest exchange.AuctionRequest
}

func (e *warningsCheckExchange) HoldAuction(ctx context.Context, r exchange.AuctionRequest, debugLog *exchange.DebugLog) (*openrtb.BidResponse, error) {
e.auctionRequest = r
return nil, nil
}

// nobidExchange is a well-behaved exchange which always bids "no bid".
type nobidExchange struct {
gotRequest *openrtb.BidRequest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"description": "Well formed amp request with invalid CCPA consent value",
"mockBidRequest": {
"id": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5",
"site": {
"page": "prebid.org",
"publisher": {
"id": "a3de7af2-a86a-4043-a77b-c7e86744155e"
}
},
"source": {
"tid": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5"
},
"tmax": 1000,
"imp": [
{
"id": "/19968336/header-bid-tag-0",
"ext": {
"appnexus": {
"placementId": 12883451
}
},
"banner": {
"format": [
{
"w": 300,
"h": 250
},
{
"w": 300,
"h": 300
}
]
}
}
],
"regs": {
"ext": {
"us_privacy": "{invalid}"
}
},
"user": {
"ext": {}
}
},
"expectedBidResponse": {
"id":"b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5",
"bidid":"test bid id",
"nbr":0
},
"expectedReturnCode": 200
}
2 changes: 2 additions & 0 deletions errortypes/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const (
const (
UnknownWarningCode = 10999
InvalidPrivacyConsentWarningCode = iota + 10000
AccountLevelDebugDisabledWarningCode
BidderLevelDebugDisabledWarningCode
)

// Coder provides an error or warning code with severity.
Expand Down
22 changes: 3 additions & 19 deletions errortypes/errortypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,34 +167,18 @@ func (err *BidderTemporarilyDisabled) Severity() Severity {

// Warning is a generic non-fatal error.
type Warning struct {
Message string
Message string
WarningCode int
}

func (err *Warning) Error() string {
return err.Message
}

func (err *Warning) Code() int {
return UnknownWarningCode
return err.WarningCode
}

func (err *Warning) Severity() Severity {
return SeverityWarning
}

// InvalidPrivacyConsent is a warning for when the privacy consent string is invalid and is ignored.
type InvalidPrivacyConsent struct {
Message string
}

func (err *InvalidPrivacyConsent) Error() string {
return err.Message
}

func (err *InvalidPrivacyConsent) Code() int {
return InvalidPrivacyConsentWarningCode
}

func (err *InvalidPrivacyConsent) Severity() Severity {
return SeverityWarning
}
14 changes: 11 additions & 3 deletions exchange/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,17 @@ func (bidder *bidderAdapter) requestBid(ctx context.Context, request *openrtb.Bi
// - debugContextKey (url param) in true
// - account debug is allowed
// - bidder debug is allowed
if accountDebugAllowed && bidder.config.DebugInfo.Allow {
if debugInfo := ctx.Value(DebugContextKey); debugInfo != nil && debugInfo.(bool) {
seatBid.httpCalls = append(seatBid.httpCalls, makeExt(httpInfo))
if debugInfo := ctx.Value(DebugContextKey); debugInfo != nil && debugInfo.(bool) {
if accountDebugAllowed {
if bidder.config.DebugInfo.Allow {
seatBid.httpCalls = append(seatBid.httpCalls, makeExt(httpInfo))
} else {
debugDisabledWarning := errortypes.Warning{
WarningCode: errortypes.BidderLevelDebugDisabledWarningCode,
Message: "debug turned off for bidder",
}
errs = append(errs, &debugDisabledWarning)
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion exchange/bidder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/currency"
"github.com/prebid/prebid-server/errortypes"
"github.com/prebid/prebid-server/metrics"
metricsConfig "github.com/prebid/prebid-server/metrics/config"
"github.com/prebid/prebid-server/openrtb_ext"
Expand Down Expand Up @@ -109,9 +110,13 @@ func TestSingleBidder(t *testing.T) {
}

// Make sure the returned values are what we expect
if len(errs) != 0 {
if len(errortypes.FatalOnly(errs)) != 0 {
t.Errorf("bidder.Bid returned %d errors. Expected 0", len(errs))
}

if !test.debugInfo.Allow && len(errortypes.WarningOnly(errs)) != 1 {
t.Errorf("bidder.Bid returned %d warnings. Expected 1", len(errs))
}
if len(seatBid.bids) != len(mockBidderResponse.Bids) {
t.Fatalf("Expected %d bids. Got %d", len(mockBidderResponse.Bids), len(seatBid.bids))
}
Expand Down
Loading

0 comments on commit 2f66d76

Please sign in to comment.