Skip to content

Commit

Permalink
OTT-1084: Adding vast version count prometheus stats (prebid#497)
Browse files Browse the repository at this point in the history
* OTT-1084: Adding vast version count prometheus stats
  • Loading branch information
Pubmatic-Dhruv-Sonone authored May 31, 2023
1 parent c46be9c commit 30428e1
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 1 deletion.
1 change: 1 addition & 0 deletions exchange/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *

if anyBidsReturned {
recordBids(ctx, e.me, r.PubID, adapterBids)
recordVastVersion(e.me, adapterBids)
//If floor enforcement config enabled then filter bids
adapterBids, enforceErrs := enforceFloors(&r, adapterBids, e.floor, conversions, responseDebugAllow)
errs = append(errs, enforceErrs...)
Expand Down
24 changes: 24 additions & 0 deletions exchange/exchange_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net/url"
"regexp"
"strings"

"github.com/golang/glog"
Expand All @@ -23,6 +24,10 @@ const (
nodeal = "nodeal"
)

var (
vastVersionRegex = regexp.MustCompile(`<VAST\s*version\s*=\s*(.*?)\s*>`)
)

// recordAdaptorDuplicateBidIDs finds the bid.id collisions for each bidder and records them with metrics engine
// it returns true if collosion(s) is/are detected in any of the bidder's bids
func recordAdaptorDuplicateBidIDs(metricsEngine metrics.MetricsEngine, adapterBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid) bool {
Expand Down Expand Up @@ -182,7 +187,26 @@ func recordBids(ctx context.Context, metricsEngine metrics.MetricsEngine, pubID
}
}
}
}

func recordVastVersion(metricsEngine metrics.MetricsEngine, adapterBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid) {
for _, seatBid := range adapterBids {
for _, pbsBid := range seatBid.Bids {
if pbsBid.BidType != openrtb_ext.BidTypeVideo {
continue
}
if pbsBid.Bid.AdM == "" {
continue
}
matches := vastVersionRegex.FindStringSubmatch(pbsBid.Bid.AdM)
if len(matches) < 2 {
continue
}
vastVersion := matches[1]
vastVersion = vastVersion[1 : len(vastVersion)-1]
metricsEngine.RecordVastVersion(string(seatBid.BidderCoreName), vastVersion)
}
}
}

// recordPartnerTimeout captures the partnertimeout if any at publisher profile level
Expand Down
218 changes: 218 additions & 0 deletions exchange/exchange_ow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1118,3 +1118,221 @@ func TestCallRecordBids(t *testing.T) {
})
}
}

func TestRecordVastVersion(t *testing.T) {
type args struct {
metricsEngine metrics.MetricsEngine
adapterBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid
getMetricsEngine func() *metrics.MetricsEngineMock
}
tests := []struct {
name string
args args
}{
{
name: "No Bids",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
return metricEngine
},
},
},
{
name: "Empty Bids in SeatBid",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
"pubmatic": {
Bids: []*entities.PbsOrtbBid{},
},
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
return metricEngine
},
},
},
{
name: "Empty Bids in SeatBid",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
"pubmatic": {
Bids: []*entities.PbsOrtbBid{},
},
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
return metricEngine
},
},
},
{
name: "Invalid Bid Type",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
"pubmatic": {
Bids: []*entities.PbsOrtbBid{
{
BidType: openrtb_ext.BidTypeBanner,
},
},
},
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
return metricEngine
},
},
},
{
name: "No Adm in Bids",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
"pubmatic": {
Bids: []*entities.PbsOrtbBid{
{
Bid: &openrtb2.Bid{
AdM: "",
},
BidType: openrtb_ext.BidTypeVideo,
},
},
},
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
return metricEngine
},
},
},
{
name: "No version found in Adm",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
"pubmatic": {
Bids: []*entities.PbsOrtbBid{
{
Bid: &openrtb2.Bid{
AdM: "<Vast> <Vast>",
},
BidType: openrtb_ext.BidTypeVideo,
},
},
},
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
return metricEngine
},
},
},
{
name: "Version found in Adm",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
"pubmatic": {
BidderCoreName: "pubmatic",
Bids: []*entities.PbsOrtbBid{
{
BidType: openrtb_ext.BidTypeVideo,
Bid: &openrtb2.Bid{
AdM: `<VAST version="2.0">
  <Ad id="601364">
    <InLine>
      <AdSystem>Adsystem Example</AdSystem>
      <AdTitle>VAST 2.0</AdTitle>
      <Description>VAST 2.0</Description>
      <Error>http://myErrorURL/error</Error>
      <Impression>http://myTrackingURL/impression</Impression>
      <Creatives>
        <Creative AdID="12345">
          <Linear>
           <Duration>00:00:30</Duration>
            <TrackingEvents>
              <Tracking event="creativeView">http://myTrackingURL/creativeView</Tracking>
              <Tracking event="start">http://myTrackingURL/start</Tracking>
              <Tracking event="midpoint">http://myTrackingURL/midpoint</Tracking>
              <Tracking event="firstQuartile">http://myTrackingURL/firstQuartile</Tracking>
              <Tracking event="thirdQuartile">http://myTrackingURL/thirdQuartile</Tracking>
              <Tracking event="complete">http://myTrackingURL/complete</Tracking>
            </TrackingEvents>
            <VideoClicks>
              <ClickThrough>http://www.examplemedia.com</ClickThrough>
              <ClickTracking>http://myTrackingURL/click</ClickTracking>
            </VideoClicks>
            <MediaFiles>
             <MediaFile delivery="progressive" type="video/x-flv" bitrate="500" width="400" height="300" scalable="true" maintainAspectRatio="true">
        http://demo.examplemedia.com/video/acudeo/Carrot_400x300_500kb.flv
          </MediaFile>
         </MediaFiles>
          </Linear>
    </Creative>
    <Creative AdID="601364-Companion">
      <CompanionAds>
           <Companion width="300" height="250">
             <StaticResource creativeType="image/jpeg">
             http://demo.examplemedia.com/vast/this_is_the_ad.jpg
             </StaticResource>
             <TrackingEvents>
               <Tracking event="creativeView">http://myTrackingURL/tracking</Tracking>
             </TrackingEvents>
           <CompanionClickThrough>http://www.examplemedia.com</CompanionClickThrough>
           </Companion>
           <Companion width="728" height="90">
             <StaticResource creativeType="image/jpeg">
             http://demo.examplemedia.com/vast/trackingbanner
             </StaticResource>
           <CompanionClickThrough>http://www.examplemedia.com</CompanionClickThrough>
           </Companion>
         </CompanionAds>
       </Creative>
     </Creatives>
   </InLine>
   </Ad>
</VAST>`,
},
},
},
},
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
metricEngine.Mock.On("RecordVastVersion", "pubmatic", "2.0").Return()
return metricEngine
},
},
},
{
name: "Version found in Adm with spaces in tag",
args: args{
adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
"pubmatic": {
BidderCoreName: "pubmatic",
Bids: []*entities.PbsOrtbBid{
{
BidType: openrtb_ext.BidTypeVideo,
Bid: &openrtb2.Bid{
AdM: `<VAST version = "2.0">
</VAST>`,
},
},
},
},
},
getMetricsEngine: func() *metrics.MetricsEngineMock {
metricEngine := &metrics.MetricsEngineMock{}
metricEngine.Mock.On("RecordVastVersion", "pubmatic", "2.0").Return()
return metricEngine
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockMetricEngine := tt.args.getMetricsEngine()
recordVastVersion(mockMetricEngine, tt.args.adapterBids)
mockMetricEngine.AssertExpectations(t)
})
}
}
10 changes: 10 additions & 0 deletions metrics/config/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,12 @@ func (me *MultiMetricsEngine) RecordBids(pubid, profileid, biddder, deal string)
}
}

func (me *MultiMetricsEngine) RecordVastVersion(biddder, vastVersion string) {
for _, thisME := range *me {
thisME.RecordVastVersion(biddder, vastVersion)
}
}

// NilMetricsEngine implements the MetricsEngine interface where no metrics are actually captured. This is
// used if no metric backend is configured and also for tests.
type NilMetricsEngine struct{}
Expand Down Expand Up @@ -623,3 +629,7 @@ func (me *NilMetricsEngine) RecordRejectedBids(pubid, bidder, code string) {
// RecordBids as a noop
func (me *NilMetricsEngine) RecordBids(pubid, profileid, biddder, deal string) {
}

// RecordVastVersion as a noop
func (me *NilMetricsEngine) RecordVastVersion(biddder, vastVersion string) {
}
4 changes: 4 additions & 0 deletions metrics/go_metrics_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ func (me *Metrics) RecordRejectedBids(pubid, biddder, code string) {
// RecordBids as a noop
func (me *Metrics) RecordBids(pubid, profileid, biddder, deal string) {
}

// RecordVastVersion as a noop
func (me *Metrics) RecordVastVersion(biddder, vastVersion string) {
}
3 changes: 3 additions & 0 deletions metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,4 +501,7 @@ type MetricsEngine 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)
}
5 changes: 5 additions & 0 deletions metrics/metrics_mock_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ func (me *MetricsEngineMock) RecordAdapterVideoBidDuration(labels AdapterLabels,
func (me *MetricsEngineMock) RecordBids(pubid, profileid, biddder, deal string) {
me.Called(pubid, profileid, biddder, deal)
}

// RecordVastVersion mock
func (me *MetricsEngineMock) RecordVastVersion(coreBidder, vastVersion string) {
me.Called(coreBidder, vastVersion)
}
6 changes: 6 additions & 0 deletions metrics/prometheus/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type Metrics struct {
// Rejected Bids
rejectedBids *prometheus.CounterVec
bids *prometheus.CounterVec
vastVersion *prometheus.CounterVec
//rejectedBids *prometheus.CounterVec
accountRejectedBid *prometheus.CounterVec
accountFloorsRequest *prometheus.CounterVec
Expand Down Expand Up @@ -535,6 +536,11 @@ func NewMetrics(cfg config.PrometheusMetrics, disabledMetrics config.DisabledMet
"Count of rejected bids by publisher id, bidder and rejection reason code",
[]string{pubIDLabel, bidderLabel, codeLabel})

metrics.vastVersion = newCounter(cfg, reg,
"vast_version",
"Count of vast version by bidder and vast version",
[]string{adapterLabel, versionLabel})

metrics.dynamicFetchFailure = newCounter(cfg, reg,
"floors_account_fetch_err",
"Count of failures in case of dynamic fetch labeled by account",
Expand Down
9 changes: 8 additions & 1 deletion metrics/prometheus/prometheus_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,18 @@ func (m *Metrics) RecordRejectedBids(pubid, biddder, code string) {

// RecordBids records bids labeled by pubid, profileid, bidder and deal
func (m *Metrics) RecordBids(pubid, profileid, biddder, deal string) {

m.bids.With(prometheus.Labels{
pubIDLabel: pubid,
profileLabel: profileid,
bidderLabel: biddder,
dealLabel: deal,
}).Inc()
}

// RecordVastVersion record the count of vast version labelled by bidder and vast version
func (m *Metrics) RecordVastVersion(coreBiddder, vastVersion string) {
m.vastVersion.With(prometheus.Labels{
adapterLabel: coreBiddder,
versionLabel: vastVersion,
}).Inc()
}
Loading

0 comments on commit 30428e1

Please sign in to comment.