Skip to content

Commit

Permalink
Merge pull request #784 from PubMatic-OpenWrap/ci
Browse files Browse the repository at this point in the history
Release 7th May 2024
  • Loading branch information
pm-nilesh-chate authored May 3, 2024
2 parents cb8ef8a + 8d38608 commit f2256b9
Show file tree
Hide file tree
Showing 44 changed files with 3,476 additions and 371 deletions.
12 changes: 9 additions & 3 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ name: Validate

on:
push:
branches: [master]
branches:
- master
- main
- ci
pull_request:
branches: [master]
branches:
- master
- main
- ci

jobs:
validate:
strategy:
matrix:
go-version: [1.19.x, 1.20.x]
go-version: [1.20.x]
os: [ubuntu-20.04]
runs-on: ${{ matrix.os }}

Expand Down
33 changes: 32 additions & 1 deletion analytics/pubmatic/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package pubmatic

import (
"encoding/json"
"errors"
"net/http"
"net/url"
"strconv"
"time"

"github.com/golang/glog"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/analytics"
"github.com/prebid/prebid-server/v2/analytics/pubmatic/mhttp"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
)
Expand Down Expand Up @@ -69,6 +72,34 @@ func send(rCtx *models.RequestCtx, url string, headers http.Header, mhc mhttp.Mu
rCtx.MetricsEngine.RecordPublisherWrapperLoggerFailure(rCtx.PubIDStr, rCtx.ProfileIDStr, "")
return
}
rCtx.MetricsEngine.RecordSendLoggerDataTime(rCtx.Endpoint, rCtx.ProfileIDStr, time.Since(startTime))
rCtx.MetricsEngine.RecordSendLoggerDataTime(time.Since(startTime))
// TODO: this will increment HB specific metric (ow_pbs_sshb_*), verify labels
}

// RestoreBidResponse restores the original bid response for AppLovinMax from the signal data
func RestoreBidResponse(rctx *models.RequestCtx, ao analytics.AuctionObject) error {
if rctx.Endpoint != models.EndpointAppLovinMax {
return nil
}

if ao.Response.NBR != nil {
return nil
}

signalData := map[string]string{}
if err := json.Unmarshal(ao.Response.SeatBid[0].Bid[0].Ext, &signalData); err != nil {
return err
}

if val, ok := signalData[models.SignalData]; !ok || val == "" {
return errors.New("signal data not found in the response")
}

orignalResponse := &openrtb2.BidResponse{}
if err := json.Unmarshal([]byte(signalData[models.SignalData]), orignalResponse); err != nil {
return err
}

*ao.Response = *orignalResponse
return nil
}
227 changes: 226 additions & 1 deletion analytics/pubmatic/helper_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package pubmatic

import (
"encoding/json"
"net/http"
"net/url"
"testing"

"github.com/golang/mock/gomock"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/analytics"
"github.com/prebid/prebid-server/v2/analytics/pubmatic/mhttp"
mock_mhttp "github.com/prebid/prebid-server/v2/analytics/pubmatic/mhttp/mock"
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/util/ptrutil"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -176,7 +181,7 @@ func TestSendMethod(t *testing.T) {
},
getMetricsEngine: func() *mock_metrics.MockMetricsEngine {
mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
mockEngine.EXPECT().RecordSendLoggerDataTime(models.EndpointV25, "1", gomock.Any())
mockEngine.EXPECT().RecordSendLoggerDataTime(gomock.Any())
return mockEngine
},
getMockMultiHttpContext: func() *mock_mhttp.MockMultiHttpContextInterface {
Expand Down Expand Up @@ -220,3 +225,223 @@ func TestSendMethod(t *testing.T) {
})
}
}

func TestRestoreBidResponse(t *testing.T) {
type args struct {
ao analytics.AuctionObject
rctx *models.RequestCtx
}
tests := []struct {
name string
args args
want *openrtb2.BidResponse
wantErr string
}{
{
name: "Endpoint is not AppLovinMax",
args: args{
ao: analytics.AuctionObject{
Response: &openrtb2.BidResponse{
ID: "test-case-1",
},
},
rctx: &models.RequestCtx{
Endpoint: models.EndpointV25,
},
},
want: &openrtb2.BidResponse{
ID: "test-case-1",
},
},
{
name: "NBR is not nil",
args: args{
ao: analytics.AuctionObject{
Response: &openrtb2.BidResponse{
ID: "test-case-1",
NBR: ptrutil.ToPtr(nbr.InvalidProfileConfiguration),
},
},
rctx: &models.RequestCtx{
Endpoint: models.EndpointAppLovinMax,
},
},
want: &openrtb2.BidResponse{
ID: "test-case-1",
NBR: ptrutil.ToPtr(nbr.InvalidProfileConfiguration),
},
},
{
name: "failed to unmarshal BidResponse.SeatBid[0].Bid[0].Ext",
args: args{
ao: analytics.AuctionObject{
Response: &openrtb2.BidResponse{
ID: "test-case-1",
SeatBid: []openrtb2.SeatBid{
{
Bid: []openrtb2.Bid{
{
ID: "123",
Ext: json.RawMessage(`{`),
},
},
},
},
},
},
rctx: &models.RequestCtx{
Endpoint: models.EndpointAppLovinMax,
},
},
want: &openrtb2.BidResponse{
ID: "test-case-1",
SeatBid: []openrtb2.SeatBid{
{
Bid: []openrtb2.Bid{
{
ID: "123",
Ext: json.RawMessage(`{`),
},
},
},
},
},
wantErr: "unexpected end of JSON input",
},
{
name: "signaldata not present in ext",
args: args{
ao: analytics.AuctionObject{
Response: &openrtb2.BidResponse{
ID: "test-case-1",
SeatBid: []openrtb2.SeatBid{
{
Bid: []openrtb2.Bid{
{
ID: "123",
Ext: json.RawMessage(`{"signalData1": "{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}\r\n"}`),
},
},
},
},
},
},
rctx: &models.RequestCtx{
Endpoint: models.EndpointAppLovinMax,
},
},
want: &openrtb2.BidResponse{
ID: "test-case-1",
SeatBid: []openrtb2.SeatBid{
{
Bid: []openrtb2.Bid{
{
ID: "123",
Ext: json.RawMessage(`{"signalData1": "{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}\r\n"}`),
},
},
},
},
},
wantErr: "signal data not found in the response",
},
{
name: "failed to unmarshal signaldata",
args: args{
ao: analytics.AuctionObject{
Response: &openrtb2.BidResponse{
ID: "123",
BidID: "bid-id-1",
Cur: "USD",
SeatBid: []openrtb2.SeatBid{
{
Seat: "pubmatic",
Bid: []openrtb2.Bid{
{
ID: "bid-id-1",
ImpID: "imp_1",
Ext: json.RawMessage(`{"signaldata": "{"id":123}"}"`),
},
},
},
},
},
},
rctx: &models.RequestCtx{
Endpoint: models.EndpointAppLovinMax,
},
},
want: &openrtb2.BidResponse{
ID: "123",
BidID: "bid-id-1",
Cur: "USD",
SeatBid: []openrtb2.SeatBid{
{
Seat: "pubmatic",
Bid: []openrtb2.Bid{
{
ID: "bid-id-1",
ImpID: "imp_1",
Ext: json.RawMessage(`{"signaldata": "{"id":123}"}"`),
},
},
},
},
},
wantErr: `invalid character 'i' after object key:value pair`,
},
{
name: "valid AppLovinMax Response",
args: args{
ao: analytics.AuctionObject{
Response: &openrtb2.BidResponse{
ID: "123",
BidID: "bid-id-1",
Cur: "USD",
SeatBid: []openrtb2.SeatBid{
{
Seat: "pubmatic",
Bid: []openrtb2.Bid{
{
ID: "bid-id-1",
ImpID: "imp_1",
Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"bid-id-1\",\"impid\":\"imp_1\",\"price\":0}],\"seat\":\"pubmatic\"}],\"bidid\":\"bid-id-1\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}}\r\n"}`),
},
},
},
},
},
},
rctx: &models.RequestCtx{
Endpoint: models.EndpointAppLovinMax,
},
},
want: &openrtb2.BidResponse{
ID: "123",
BidID: "bid-id-1",
Cur: "USD",
SeatBid: []openrtb2.SeatBid{
{
Seat: "pubmatic",
Bid: []openrtb2.Bid{
{
ID: "bid-id-1",
ImpID: "imp_1",
},
},
},
},
Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := RestoreBidResponse(tt.args.rctx, tt.args.ao)
if err != nil {
assert.Equal(t, tt.wantErr, err.Error(), tt.name)
}
assert.Equal(t, tt.want, tt.args.ao.Response, tt.name)
})
}
}
6 changes: 3 additions & 3 deletions analytics/pubmatic/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ type bidWrapper struct {
Nbr *openrtb3.NoBidReason
}

// getUUID is a function variable which will return uuid
var getUUID = func() string {
// GetUUID is a function variable which will return uuid
var GetUUID = func() string {
return uuid.NewV4().String()
}

Expand Down Expand Up @@ -103,7 +103,7 @@ func GetLogAuctionObjectAsURL(ao analytics.AuctionObject, rCtx *models.RequestCt
}

slots = append(slots, SlotRecord{
SlotId: getUUID(),
SlotId: GetUUID(),
SlotName: impCtx.SlotName,
SlotSize: impCtx.IncomingSlots,
Adunit: impCtx.AdUnitName,
Expand Down
12 changes: 6 additions & 6 deletions analytics/pubmatic/logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4011,13 +4011,13 @@ func TestGetLogAuctionObjectAsURLForFloorType(t *testing.T) {
}
func TestGetLogAuctionObjectAsURLForFloorDetailsAndCDS(t *testing.T) {
cfg := ow.cfg
uuidFunc := getUUID
uuidFunc := GetUUID
defer func() {
ow.cfg = cfg
getUUID = uuidFunc
GetUUID = uuidFunc
}()

getUUID = func() string { return "uuid" }
GetUUID = func() string { return "uuid" }
ow.cfg.Endpoint = "http://10.172.141.11/wl"
ow.cfg.PublicEndpoint = "http://t.pubmatic.com/wl"

Expand Down Expand Up @@ -4204,13 +4204,13 @@ func TestGetLogAuctionObjectAsURLForFloorDetailsAndCDS(t *testing.T) {
}
func TestSlotRecordsInGetLogAuctionObjectAsURL(t *testing.T) {
cfg := ow.cfg
uuidFunc := getUUID
uuidFunc := GetUUID
defer func() {
ow.cfg = cfg
getUUID = uuidFunc
GetUUID = uuidFunc
}()

getUUID = func() string {
GetUUID = func() string {
return "sid"
}

Expand Down
5 changes: 5 additions & 0 deletions analytics/pubmatic/pubmatic.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ func (ow HTTPLogger) LogAuctionObject(ao *analytics.AuctionObject) {
return
}

err := RestoreBidResponse(rCtx, *ao)
if err != nil {
glog.Error("Failed to restore bid response for pub:[%d], profile:[%d], version:[%d], err:[%s].", rCtx.PubID, rCtx.ProfileID, rCtx.VersionID, err.Error())
}

url, headers := GetLogAuctionObjectAsURL(*ao, rCtx, false, false)
if url == "" {
glog.Errorf("Failed to prepare the owlogger for pub:[%d], profile:[%d], version:[%d].",
Expand Down
Loading

0 comments on commit f2256b9

Please sign in to comment.