Skip to content

Commit

Permalink
Merge branch 'master' into EX-4884_make_minduration_optional
Browse files Browse the repository at this point in the history
  • Loading branch information
ikagotso committed Oct 6, 2023
2 parents 138b3a3 + 8cdfe48 commit 894e9a4
Show file tree
Hide file tree
Showing 28 changed files with 323 additions and 332 deletions.
47 changes: 30 additions & 17 deletions analytics/config/config.go → analytics/build/build.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package config
package build

import (
"github.com/benbjohnson/clock"
Expand All @@ -8,14 +8,15 @@ import (
"github.com/prebid/prebid-server/analytics/filesystem"
"github.com/prebid/prebid-server/analytics/pubstack"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/privacy"
)

// Modules that need to be logged to need to be initialized here
func NewPBSAnalytics(analytics *config.Analytics) analytics.PBSAnalyticsModule {
func New(analytics *config.Analytics) analytics.Runner {
modules := make(enabledAnalytics, 0)
if len(analytics.File.Filename) > 0 {
if mod, err := filesystem.NewFileLogger(analytics.File.Filename); err == nil {
modules = append(modules, mod)
modules["filelogger"] = mod
} else {
glog.Fatalf("Could not initialize FileLogger for file %v :%v", analytics.File.Filename, err)
}
Expand All @@ -32,7 +33,7 @@ func NewPBSAnalytics(analytics *config.Analytics) analytics.PBSAnalyticsModule {
analytics.Pubstack.Buffers.Timeout,
clock.New())
if err == nil {
modules = append(modules, pubstackModule)
modules["pubstack"] = pubstackModule
} else {
glog.Errorf("Could not initialize PubstackModule: %v", err)
}
Expand All @@ -41,17 +42,23 @@ func NewPBSAnalytics(analytics *config.Analytics) analytics.PBSAnalyticsModule {
}

// Collection of all the correctly configured analytics modules - implements the PBSAnalyticsModule interface
type enabledAnalytics []analytics.PBSAnalyticsModule
type enabledAnalytics map[string]analytics.Module

func (ea enabledAnalytics) LogAuctionObject(ao *analytics.AuctionObject) {
for _, module := range ea {
module.LogAuctionObject(ao)
func (ea enabledAnalytics) LogAuctionObject(ao *analytics.AuctionObject, ac privacy.ActivityControl) {
for name, module := range ea {
component := privacy.Component{Type: privacy.ComponentTypeAnalytics, Name: name}
if ac.Allow(privacy.ActivityReportAnalytics, component, privacy.ActivityRequest{}) {
module.LogAuctionObject(ao)
}
}
}

func (ea enabledAnalytics) LogVideoObject(vo *analytics.VideoObject) {
for _, module := range ea {
module.LogVideoObject(vo)
func (ea enabledAnalytics) LogVideoObject(vo *analytics.VideoObject, ac privacy.ActivityControl) {
for name, module := range ea {
component := privacy.Component{Type: privacy.ComponentTypeAnalytics, Name: name}
if ac.Allow(privacy.ActivityReportAnalytics, component, privacy.ActivityRequest{}) {
module.LogVideoObject(vo)
}
}
}

Expand All @@ -67,14 +74,20 @@ func (ea enabledAnalytics) LogSetUIDObject(so *analytics.SetUIDObject) {
}
}

func (ea enabledAnalytics) LogAmpObject(ao *analytics.AmpObject) {
for _, module := range ea {
module.LogAmpObject(ao)
func (ea enabledAnalytics) LogAmpObject(ao *analytics.AmpObject, ac privacy.ActivityControl) {
for name, module := range ea {
component := privacy.Component{Type: privacy.ComponentTypeAnalytics, Name: name}
if ac.Allow(privacy.ActivityReportAnalytics, component, privacy.ActivityRequest{}) {
module.LogAmpObject(ao)
}
}
}

func (ea enabledAnalytics) LogNotificationEventObject(ne *analytics.NotificationEvent) {
for _, module := range ea {
module.LogNotificationEventObject(ne)
func (ea enabledAnalytics) LogNotificationEventObject(ne *analytics.NotificationEvent, ac privacy.ActivityControl) {
for name, module := range ea {
component := privacy.Component{Type: privacy.ComponentTypeAnalytics, Name: name}
if ac.Allow(privacy.ActivityReportAnalytics, component, privacy.ActivityRequest{}) {
module.LogNotificationEventObject(ne)
}
}
}
116 changes: 101 additions & 15 deletions analytics/config/config_test.go → analytics/build/build_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package config
package build

import (
"github.com/prebid/prebid-server/analytics"
"net/http"
"os"
"testing"

"github.com/prebid/openrtb/v19/openrtb2"
"github.com/stretchr/testify/assert"

"github.com/prebid/prebid-server/analytics"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/privacy"
"github.com/prebid/prebid-server/util/ptrutil"
"github.com/stretchr/testify/assert"
)

const TEST_DIR string = "testFiles"
Expand All @@ -21,7 +22,7 @@ func TestSampleModule(t *testing.T) {
Status: http.StatusOK,
Errors: nil,
Response: &openrtb2.BidResponse{},
})
}, privacy.ActivityControl{})
if count != 1 {
t.Errorf("PBSAnalyticsModule failed at LogAuctionObject")
}
Expand All @@ -42,17 +43,17 @@ func TestSampleModule(t *testing.T) {
t.Errorf("PBSAnalyticsModule failed at LogCookieSyncObject")
}

am.LogAmpObject(&analytics.AmpObject{})
am.LogAmpObject(&analytics.AmpObject{}, privacy.ActivityControl{})
if count != 4 {
t.Errorf("PBSAnalyticsModule failed at LogAmpObject")
}

am.LogVideoObject(&analytics.VideoObject{})
am.LogVideoObject(&analytics.VideoObject{}, privacy.ActivityControl{})
if count != 5 {
t.Errorf("PBSAnalyticsModule failed at LogVideoObject")
}

am.LogNotificationEventObject(&analytics.NotificationEvent{})
am.LogNotificationEventObject(&analytics.NotificationEvent{}, privacy.ActivityControl{})
if count != 6 {
t.Errorf("PBSAnalyticsModule failed at LogNotificationEventObject")
}
Expand All @@ -74,14 +75,14 @@ func (m *sampleModule) LogAmpObject(ao *analytics.AmpObject) { *m.count++ }

func (m *sampleModule) LogNotificationEventObject(ne *analytics.NotificationEvent) { *m.count++ }

func initAnalytics(count *int) analytics.PBSAnalyticsModule {
func initAnalytics(count *int) analytics.Runner {
modules := make(enabledAnalytics, 0)
modules = append(modules, &sampleModule{count})
modules["sampleModule"] = &sampleModule{count}
return &modules
}

func TestNewPBSAnalytics(t *testing.T) {
pbsAnalytics := NewPBSAnalytics(&config.Analytics{})
pbsAnalytics := New(&config.Analytics{})
instance := pbsAnalytics.(enabledAnalytics)

assert.Equal(t, len(instance), 0)
Expand All @@ -94,7 +95,7 @@ func TestNewPBSAnalytics_FileLogger(t *testing.T) {
}
}
defer os.RemoveAll(TEST_DIR)
mod := NewPBSAnalytics(&config.Analytics{File: config.FileLogs{Filename: TEST_DIR + "/test"}})
mod := New(&config.Analytics{File: config.FileLogs{Filename: TEST_DIR + "/test"}})
switch modType := mod.(type) {
case enabledAnalytics:
if len(enabledAnalytics(modType)) != 1 {
Expand All @@ -104,15 +105,15 @@ func TestNewPBSAnalytics_FileLogger(t *testing.T) {
t.Fatalf("Failed to initialize analytics module")
}

pbsAnalytics := NewPBSAnalytics(&config.Analytics{File: config.FileLogs{Filename: TEST_DIR + "/test"}})
pbsAnalytics := New(&config.Analytics{File: config.FileLogs{Filename: TEST_DIR + "/test"}})
instance := pbsAnalytics.(enabledAnalytics)

assert.Equal(t, len(instance), 1)
}

func TestNewPBSAnalytics_Pubstack(t *testing.T) {

pbsAnalyticsWithoutError := NewPBSAnalytics(&config.Analytics{
pbsAnalyticsWithoutError := New(&config.Analytics{
Pubstack: config.Pubstack{
Enabled: true,
ScopeId: "scopeId",
Expand All @@ -129,11 +130,96 @@ func TestNewPBSAnalytics_Pubstack(t *testing.T) {

assert.Equal(t, len(instanceWithoutError), 1)

pbsAnalyticsWithError := NewPBSAnalytics(&config.Analytics{
pbsAnalyticsWithError := New(&config.Analytics{
Pubstack: config.Pubstack{
Enabled: true,
},
})
instanceWithError := pbsAnalyticsWithError.(enabledAnalytics)
assert.Equal(t, len(instanceWithError), 0)
}

func TestSampleModuleActivitiesAllowed(t *testing.T) {
var count int
am := initAnalytics(&count)

acAllowed := privacy.NewActivityControl(getDefaultActivityConfig("sampleModule", true))

ao := &analytics.AuctionObject{
Status: http.StatusOK,
Errors: nil,
Response: &openrtb2.BidResponse{},
}

am.LogAuctionObject(ao, acAllowed)
if count != 1 {
t.Errorf("PBSAnalyticsModule failed at LogAuctionObject")
}

am.LogAmpObject(&analytics.AmpObject{}, acAllowed)
if count != 2 {
t.Errorf("PBSAnalyticsModule failed at LogAmpObject")
}

am.LogVideoObject(&analytics.VideoObject{}, acAllowed)
if count != 3 {
t.Errorf("PBSAnalyticsModule failed at LogVideoObject")
}

am.LogNotificationEventObject(&analytics.NotificationEvent{}, acAllowed)
if count != 4 {
t.Errorf("PBSAnalyticsModule failed at LogNotificationEventObject")
}
}

func TestSampleModuleActivitiesDenied(t *testing.T) {
var count int
am := initAnalytics(&count)

acDenied := privacy.NewActivityControl(getDefaultActivityConfig("sampleModule", false))

ao := &analytics.AuctionObject{
Status: http.StatusOK,
Errors: nil,
Response: &openrtb2.BidResponse{},
}

am.LogAuctionObject(ao, acDenied)
if count != 0 {
t.Errorf("PBSAnalyticsModule failed at LogAuctionObject")
}

am.LogAmpObject(&analytics.AmpObject{}, acDenied)
if count != 0 {
t.Errorf("PBSAnalyticsModule failed at LogAmpObject")
}

am.LogVideoObject(&analytics.VideoObject{}, acDenied)
if count != 0 {
t.Errorf("PBSAnalyticsModule failed at LogVideoObject")
}

am.LogNotificationEventObject(&analytics.NotificationEvent{}, acDenied)
if count != 0 {
t.Errorf("PBSAnalyticsModule failed at LogNotificationEventObject")
}
}

func getDefaultActivityConfig(componentName string, allow bool) *config.AccountPrivacy {
return &config.AccountPrivacy{
AllowActivities: &config.AllowActivities{
ReportAnalytics: config.Activity{
Default: ptrutil.ToPtr(true),
Rules: []config.ActivityRule{
{
Allow: allow,
Condition: config.ActivityCondition{
ComponentName: []string{componentName},
ComponentType: []string{"analytics"},
},
},
},
},
},
}
}
4 changes: 2 additions & 2 deletions analytics/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"github.com/prebid/prebid-server/openrtb_ext"
)

// PBSAnalyticsModule must be implemented by analytics modules to extract the required information and logging
// Module must be implemented by analytics modules to extract the required information and logging
// activities. Do not use marshal the parameter objects directly as they can change over time. Use a separate
// model for each analytics module and transform as appropriate.
type PBSAnalyticsModule interface {
type Module interface {
LogAuctionObject(*AuctionObject)
LogVideoObject(*VideoObject)
LogCookieSyncObject(*CookieSyncObject)
Expand Down
2 changes: 1 addition & 1 deletion analytics/filesystem/file_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (f *FileLogger) LogNotificationEventObject(ne *analytics.NotificationEvent)
}

// Method to initialize the analytic module
func NewFileLogger(filename string) (analytics.PBSAnalyticsModule, error) {
func NewFileLogger(filename string) (analytics.Module, error) {
options := glog.LogOptions{
File: filename,
Flag: glog.LstdFlags,
Expand Down
4 changes: 2 additions & 2 deletions analytics/pubstack/pubstack_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type PubstackModule struct {
clock clock.Clock
}

func NewModule(client *http.Client, scope, endpoint, configRefreshDelay string, maxEventCount int, maxByteSize, maxTime string, clock clock.Clock) (analytics.PBSAnalyticsModule, error) {
func NewModule(client *http.Client, scope, endpoint, configRefreshDelay string, maxEventCount int, maxByteSize, maxTime string, clock clock.Clock) (analytics.Module, error) {
configUpdateTask, err := NewConfigUpdateHttpTask(
client,
scope,
Expand All @@ -63,7 +63,7 @@ func NewModule(client *http.Client, scope, endpoint, configRefreshDelay string,
return NewModuleWithConfigTask(client, scope, endpoint, maxEventCount, maxByteSize, maxTime, configUpdateTask, clock)
}

func NewModuleWithConfigTask(client *http.Client, scope, endpoint string, maxEventCount int, maxByteSize, maxTime string, configTask ConfigUpdateTask, clock clock.Clock) (analytics.PBSAnalyticsModule, error) {
func NewModuleWithConfigTask(client *http.Client, scope, endpoint string, maxEventCount int, maxByteSize, maxTime string, configTask ConfigUpdateTask, clock clock.Clock) (analytics.Module, error) {
glog.Infof("[pubstack] Initializing module scope=%s endpoint=%s\n", scope, endpoint)

// parse args
Expand Down
14 changes: 7 additions & 7 deletions analytics/pubstack/pubstack_module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,47 +50,47 @@ func TestNewModuleSuccess(t *testing.T) {
tests := []struct {
description string
feature string
logObject func(analytics.PBSAnalyticsModule)
logObject func(analytics.Module)
}{
{
description: "auction events are only published when logging an auction object with auction feature on",
feature: auction,
logObject: func(module analytics.PBSAnalyticsModule) {
logObject: func(module analytics.Module) {
module.LogAuctionObject(&analytics.AuctionObject{Status: http.StatusOK})
},
},
{
description: "AMP events are only published when logging an AMP object with AMP feature on",
feature: amp,
logObject: func(module analytics.PBSAnalyticsModule) {
logObject: func(module analytics.Module) {
module.LogAmpObject(&analytics.AmpObject{Status: http.StatusOK})
},
},
{
description: "video events are only published when logging a video object with video feature on",
feature: video,
logObject: func(module analytics.PBSAnalyticsModule) {
logObject: func(module analytics.Module) {
module.LogVideoObject(&analytics.VideoObject{Status: http.StatusOK})
},
},
{
description: "cookie events are only published when logging a cookie object with cookie feature on",
feature: cookieSync,
logObject: func(module analytics.PBSAnalyticsModule) {
logObject: func(module analytics.Module) {
module.LogCookieSyncObject(&analytics.CookieSyncObject{Status: http.StatusOK})
},
},
{
description: "setUID events are only published when logging a setUID object with setUID feature on",
feature: setUID,
logObject: func(module analytics.PBSAnalyticsModule) {
logObject: func(module analytics.Module) {
module.LogSetUIDObject(&analytics.SetUIDObject{Status: http.StatusOK})
},
},
{
description: "Ignore excluded fields from marshal",
feature: auction,
logObject: func(module analytics.PBSAnalyticsModule) {
logObject: func(module analytics.Module) {
module.LogAuctionObject(&analytics.AuctionObject{
RequestWrapper: &openrtb_ext.RequestWrapper{},
SeatNonBid: []openrtb_ext.SeatNonBid{
Expand Down
14 changes: 14 additions & 0 deletions analytics/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package analytics

import (
"github.com/prebid/prebid-server/privacy"
)

type Runner interface {
LogAuctionObject(*AuctionObject, privacy.ActivityControl)
LogVideoObject(*VideoObject, privacy.ActivityControl)
LogCookieSyncObject(*CookieSyncObject)
LogSetUIDObject(*SetUIDObject)
LogAmpObject(*AmpObject, privacy.ActivityControl)
LogNotificationEventObject(*NotificationEvent, privacy.ActivityControl)
}
Loading

0 comments on commit 894e9a4

Please sign in to comment.