Skip to content

Commit

Permalink
OTT-1823: Added fast xml related metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
pm-jaydeep-mohite committed Jun 13, 2024
1 parent 84625ef commit cfff01d
Show file tree
Hide file tree
Showing 14 changed files with 211 additions and 13 deletions.
1 change: 1 addition & 0 deletions adapters/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type BidderResponse struct {
Currency string
Bids []*TypedBid
FledgeAuctionConfigs []*openrtb_ext.FledgeAuctionConfig
FastXMLMetrics *openrtb_ext.FastXMLMetrics
}

// NewBidderResponseWithBidsCapacity create a new BidderResponse initialising the bids array capacity and the default currency value
Expand Down
57 changes: 49 additions & 8 deletions adapters/vastbidder/vastbidder.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package vastbidder

import (
"time"

"github.com/PubMatic-OpenWrap/prebid-server/v2/util/jsonutil"
"github.com/golang/glog"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/adapters"
"github.com/prebid/prebid-server/v2/config"
Expand All @@ -10,8 +14,9 @@ import (
// VASTBidder is default implementation of ITagBidder
type VASTBidder struct {
adapters.Bidder
bidderName openrtb_ext.BidderName
adapterConfig *config.Adapter
bidderName openrtb_ext.BidderName
adapterConfig *config.Adapter
fastXMLExpriement bool
}

// MakeRequests will contains default definition for processing queries
Expand Down Expand Up @@ -63,26 +68,62 @@ func (a *VASTBidder) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapter

// MakeBids makes bids
func (a *VASTBidder) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {

parser := getXMLParser(etreeXMLParserType)
handler := newResponseHandler(internalRequest, externalRequest, response, parser)

etreeStart := time.Now()
if err := handler.Validate(); len(err) > 0 {
return nil, err[:]
}

return handler.MakeBids()
etreeParserResp, etrrErr := handler.MakeBids()
etreeEnd := time.Since(etreeStart)

if a.fastXMLExpriement {
var xmlEnd time.Duration
var xmlResp []byte

xmlParser := getXMLParser(fastXMLParserType)
xmlHandler := newResponseHandler(internalRequest, externalRequest, response, xmlParser)

xmlStart := time.Now()
if err := xmlHandler.Validate(); len(err) == 0 {
xmlParserResp, _ := xmlHandler.MakeBids()
xmlEnd = time.Since(xmlStart)
xmlResp, _ = jsonutil.Marshal(xmlParserResp)
}

etrrResp, _ := jsonutil.Marshal(etreeParserResp)

isVASTMismatch := false
if string(xmlResp) != string(etrrResp) {
isVASTMismatch = true
glog.V(2).Infof("\n [VAST_BIDDER] Response Mismatch for Creative : %s", string(handler.response.Body))
}

vastBidderInfo := &openrtb_ext.FastXMLMetrics{
XMLParserTime: xmlEnd,
EtreeParserTime: etreeEnd,
IsRespMismatch: isVASTMismatch,
}

etreeParserResp.FastXMLMetrics = vastBidderInfo
}
return etreeParserResp, etrrErr
}

// NewTagBidder is an constructor for TagBidder
func NewTagBidder(bidderName openrtb_ext.BidderName, config config.Adapter) *VASTBidder {
func NewTagBidder(bidderName openrtb_ext.BidderName, config config.Adapter, enableFastXML bool) *VASTBidder {
obj := &VASTBidder{
bidderName: bidderName,
adapterConfig: &config,
bidderName: bidderName,
adapterConfig: &config,
fastXMLExpriement: 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, _ config.Server) (adapters.Bidder, error) {
return NewTagBidder(bidderName, config), nil
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, serverConfig config.Server) (adapters.Bidder, error) {
return NewTagBidder(bidderName, config, serverConfig.EnableFastXML), nil
}
2 changes: 1 addition & 1 deletion adapters/vastbidder/vastbidder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func TestMakeRequests(t *testing.T) {
RegisterNewBidderMacro(bidderName, func() IBidderMacro {
return newMyVastBidderMacro(tt.args.customHeaders)
})
bidder := NewTagBidder(bidderName, config.Adapter{})
bidder := NewTagBidder(bidderName, config.Adapter{}, false)
reqData, err := bidder.MakeRequests(tt.args.req, nil)
assert.Nil(t, err)
for _, req := range reqData {
Expand Down
7 changes: 4 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -654,9 +654,10 @@ type Debug struct {
}

type Server struct {
ExternalUrl string
GvlID int
DataCenter string
ExternalUrl string
GvlID int
DataCenter string
EnableFastXML bool
}

func (server *Server) Empty() bool {
Expand Down
2 changes: 1 addition & 1 deletion exchange/adapter_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
server := config.Server{ExternalUrl: cfg.ExternalURL, GvlID: cfg.GDPR.HostVendorID, DataCenter: cfg.DataCenter, EnableFastXML: cfg.EnableFastXML}

Check failure on line 14 in exchange/adapter_util.go

View workflow job for this annotation

GitHub Actions / validate-merge

cfg.EnableFastXML undefined (type *config.Configuration has no field or method EnableFastXML)

Check failure on line 14 in exchange/adapter_util.go

View workflow job for this annotation

GitHub Actions / validate (1.20.x, ubuntu-20.04)

cfg.EnableFastXML undefined (type *config.Configuration has no field or method EnableFastXML)
bidders, errs := buildBidders(infos, newAdapterBuilders(), server)

if len(errs) > 0 {
Expand Down
5 changes: 5 additions & 0 deletions exchange/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ func (bidder *bidderAdapter) requestBid(ctx context.Context, bidderRequest Bidde
errs = append(errs, moreErrs...)

if bidResponse != nil {

if bidResponse.FastXMLMetrics != nil {
recordFastXMLMetrics(bidder.me, string(bidder.BidderName), bidResponse.FastXMLMetrics)
}

recordVASTTagType(bidder.me, bidResponse, bidder.BidderName)
reject := hookExecutor.ExecuteRawBidderResponseStage(bidResponse, string(bidder.BidderName))
if reject != nil {
Expand Down
6 changes: 6 additions & 0 deletions exchange/exchange_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ func recordVastVersion(metricsEngine metrics.MetricsEngine, adapterBids map[open
}
}

func recordFastXMLMetrics(metricsEngine metrics.MetricsEngine, bidder string, vastBidderInfo *openrtb_ext.FastXMLMetrics) {
metricsEngine.RecordFastXMLParserResponseTime(bidder, vastBidderInfo.XMLParserTime)
metricsEngine.RecordEtreeParserResponseTime(bidder, vastBidderInfo.EtreeParserTime)
metricsEngine.RecordResponseMismatch(bidder, vastBidderInfo.IsRespMismatch)
}

func recordVASTTagType(metricsEngine metrics.MetricsEngine, adapterBids *adapters.BidderResponse, bidder openrtb_ext.BidderName) {
for _, adapterBid := range adapterBids.Bids {
if adapterBid.BidType == openrtb_ext.BidTypeVideo {
Expand Down
19 changes: 19 additions & 0 deletions exchange/exchange_ow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1817,3 +1817,22 @@ func TestIsUrl(t *testing.T) {
})
}
}

func Test_recordFastXMLMetrics(t *testing.T) {
type args struct {
metricsEngine metrics.MetricsEngine
bidder string
vastBidderInfo *openrtb_ext.FastXMLMetrics
}
tests := []struct {
name string
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
recordFastXMLMetrics(tt.args.metricsEngine, tt.args.bidder, tt.args.vastBidderInfo)
})
}
}
32 changes: 32 additions & 0 deletions metrics/config/metrics_ow.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import (
"time"

"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prometheus/client_golang/prometheus"
gometrics "github.com/rcrowley/go-metrics"
Expand All @@ -22,6 +24,24 @@ func NewMetricsRegistry() MetricsRegistry {
}
}

func (me *MultiMetricsEngine) RecordFastXMLParserResponseTime(bidder string, respTime time.Duration) {
for _, thisME := range *me {
thisME.RecordFastXMLParserResponseTime(bidder, respTime)
}
}

func (me *MultiMetricsEngine) RecordEtreeParserResponseTime(bidder string, respTime time.Duration) {
for _, thisME := range *me {
thisME.RecordEtreeParserResponseTime(bidder, respTime)
}
}

func (me *MultiMetricsEngine) RecordResponseMismatch(bidder string, isMismatch bool) {
for _, thisME := range *me {
thisME.RecordResponseMismatch(bidder, isMismatch)
}
}

func (me *MultiMetricsEngine) RecordVASTTagType(biddder, vastTag string) {
for _, thisME := range *me {
thisME.RecordVASTTagType(biddder, vastTag)
Expand Down Expand Up @@ -60,6 +80,18 @@ func (me *MultiMetricsEngine) RecordFloorStatus(pubId, source, code string) {
}
}

// RecordFastXMLParserResponseTime as a noop
func (me *NilMetricsEngine) RecordFastXMLParserResponseTime(bidder string, respTime time.Duration) {
}

// RecordEtreeParserResponseTime as a noop
func (me *NilMetricsEngine) RecordEtreeParserResponseTime(bidder string, respTime time.Duration) {
}

// RecordResponseMismatch as a noop
func (me *NilMetricsEngine) RecordResponseMismatch(bidder string, isMismatch bool) {
}

// RecordVASTTagType as a noop
func (me *NilMetricsEngine) RecordVASTTagType(biddder, vastTag string) {
}
Expand Down
12 changes: 12 additions & 0 deletions metrics/go_metrics_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,15 @@ func (me *Metrics) RecordVastVersion(biddder, vastVersion string) {
// RecordVASTTagType as a noop
func (me *Metrics) RecordVASTTagType(biddder, vastTag string) {
}

// RecordFastXMLParserResponseTime as a noop
func (me *Metrics) RecordFastXMLParserResponseTime(bidder string, respTime time.Duration) {
}

// RecordEtreeParserResponseTime as a noop
func (me *Metrics) RecordEtreeParserResponseTime(bidder string, respTime time.Duration) {
}

// RecordResponseMismatch as a noop
func (me *Metrics) RecordResponseMismatch(bidder string, isMismatch bool) {
}
15 changes: 15 additions & 0 deletions metrics/metrics_mock_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,18 @@ func (me *MetricsEngineMock) RecordVastVersion(coreBidder, vastVersion string) {
func (me *MetricsEngineMock) RecordVASTTagType(bidder, vastTagType string) {
me.Called(bidder, vastTagType)
}

// RecordFastXMLParserResponseTime mock
func (me *MetricsEngineMock) RecordFastXMLParserResponseTime(bidder string, respTime time.Duration) {
me.Called(bidder, respTime)
}

// RecordEtreeParserResponseTime mock
func (me *MetricsEngineMock) RecordEtreeParserResponseTime(bidder string, respTime time.Duration) {
me.Called(bidder, respTime)
}

// RecordResponseMismatch mock
func (me *MetricsEngineMock) RecordResponseMismatch(bidder string, isMismatch bool) {
me.Called(bidder, isMismatch)
}
10 changes: 10 additions & 0 deletions metrics/metrics_ow.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
package metrics

import "time"

type OWMetricsEngine interface {
//RecordBids records the bidder deal bids labeled by pubid, profile, bidder and deal
RecordBids(pubid, profileid, bidder, deal string)
//RecordVastVersion record the count of vast version labelled by bidder and vast version
RecordVastVersion(coreBidder, vastVersion string)
//RecordVASTTagType record the count of vast tag type labeled by bidder and vast tag
RecordVASTTagType(bidder, vastTagType string)

// Below metrics are added for FAST XML parser
//RecordFastXMLParserResponseTime records exexution time of fast xml parser
RecordFastXMLParserResponseTime(bidder string, respTime time.Duration)
//RecordEtreeParserResponseTime records exexution time of etree xml parser
RecordEtreeParserResponseTime(bidder string, espTime time.Duration)
//RecordResponseMismatch records number of response mismatch
RecordResponseMismatch(bidder string, isMismatch bool)
}
49 changes: 49 additions & 0 deletions metrics/prometheus/prometheus_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ type OWMetrics struct {
// podCompExclTimer indicates time taken by compititve exclusion
// algorithm to generate final pod response based on bid response and ad pod request
podCompExclTimer *prometheus.HistogramVec

// podImpGenTimer indicates time taken by impression generator
// algorithm to generate impressions for given ad pod request
fastXMLParserTime *prometheus.HistogramVec
etreeXMLParserTime *prometheus.HistogramVec
respMismatchCount *prometheus.CounterVec
respMatchCount *prometheus.CounterVec
}

// RecordAdapterDuplicateBidID captures the bid.ID collisions when adaptor
Expand Down Expand Up @@ -145,6 +152,7 @@ func (m *OWMetrics) RecordVASTTagType(bidder, vastTagType string) {
vastTagTypeLabel: vastTagType,
}).Inc()
}

func (m *Metrics) RecordRejectedBidsForAccount(pubId string) {
if pubId != metrics.PublisherUnknown {
m.accountRejectedBid.With(prometheus.Labels{
Expand All @@ -160,6 +168,7 @@ func (m *Metrics) RecordFloorsRequestForAccount(pubId string) {
}).Inc()
}
}

func (m *Metrics) RecordFloorStatus(pubId, source, code string) {
if pubId != metrics.PublisherUnknown {
m.dynamicFetchFailure.With(prometheus.Labels{
Expand All @@ -170,6 +179,25 @@ func (m *Metrics) RecordFloorStatus(pubId, source, code string) {
}
}

// RecordVastVersion record the count of vast version labelled by bidder and vast version
func (m *OWMetrics) RecordFastXMLParserResponseTime(bidder string, respTime time.Duration) {
m.fastXMLParserTime.With(prometheus.Labels{adapterLabel: bidder}).Observe(respTime.Seconds())
}

// RecordVastVersion record the count of vast version labelled by bidder and vast version
func (m *OWMetrics) RecordEtreeParserResponseTime(bidder string, respTime time.Duration) {
m.etreeXMLParserTime.With(prometheus.Labels{adapterLabel: bidder}).Observe(respTime.Seconds())
}

// RecordVastVersion record the count of vast version labelled by bidder and vast version
func (m *OWMetrics) RecordResponseMismatch(bidder string, isMismatch bool) {
if isMismatch {
m.respMismatchCount.With(prometheus.Labels{adapterLabel: bidder}).Inc()
} else {
m.respMatchCount.With(prometheus.Labels{adapterLabel: bidder}).Inc()
}
}

func (m *OWMetrics) init(cfg config.PrometheusMetrics, reg *prometheus.Registry) {
m.rejectedBids = newCounter(cfg, reg,
"rejected_bids",
Expand Down Expand Up @@ -243,4 +271,25 @@ func (m *OWMetrics) init(cfg config.PrometheusMetrics, reg *prometheus.Registry)
//[]float64{0.000200000, 0.000250000, 0.000275000, 0.000300000})
[]float64{0.000100000, 0.000200000, 0.000300000, 0.000400000, 0.000500000, 0.000600000})

// Fast XMl specific metrics
m.fastXMLParserTime = newHistogramVec(cfg, reg,
"fast_xml_parser",
"Time taken by fast xml parser", []string{accountLabel},
[]float64{0.000100000, 0.000200000, 0.000300000, 0.000400000, 0.000500000, 0.000600000})

// Fast XMl specific metrics
m.etreeXMLParserTime = newHistogramVec(cfg, reg,
"etree_xml_parser",
"Time taken by etree xml parser", []string{adapterLabel},
[]float64{0.000100000, 0.000200000, 0.000300000, 0.000400000, 0.000500000, 0.000600000})

m.respMismatchCount = newCounter(cfg, reg,
"resp_mismatch",
"Count of no of bids for which fast xml and etree response mismatch",
[]string{adapterLabel})

m.respMatchCount = newCounter(cfg, reg,
"resp_match",
"Count of no of bids for which fast xml and etree response matched",
[]string{adapterLabel})
}
7 changes: 7 additions & 0 deletions openrtb_ext/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package openrtb_ext

import (
"encoding/json"
"time"

"github.com/prebid/openrtb/v20/adcom1"
"github.com/prebid/openrtb/v20/openrtb2"
Expand Down Expand Up @@ -60,6 +61,12 @@ type ExtResponsePrebid struct {
Floors *PriceFloorRules `json:"floors,omitempty"`
}

type FastXMLMetrics struct {
XMLParserTime time.Duration `json:"xmlparsertime,omitempty"`
EtreeParserTime time.Duration `json:"etreeparsertime,omitempty"`
IsRespMismatch bool `json:"isrespmismatch,omitempty"`
}

// FledgeResponse defines the contract for bidresponse.ext.fledge
type Fledge struct {
AuctionConfigs []*FledgeAuctionConfig `json:"auctionconfigs,omitempty"`
Expand Down

0 comments on commit cfff01d

Please sign in to comment.