github.com/prebid/prebid-server/v2@v2.18.0/analytics/build/build.go (about)

     1  package build
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/benbjohnson/clock"
     7  	"github.com/golang/glog"
     8  	"github.com/prebid/prebid-server/v2/analytics"
     9  	"github.com/prebid/prebid-server/v2/analytics/agma"
    10  	"github.com/prebid/prebid-server/v2/analytics/clients"
    11  	"github.com/prebid/prebid-server/v2/analytics/filesystem"
    12  	"github.com/prebid/prebid-server/v2/analytics/pubstack"
    13  	"github.com/prebid/prebid-server/v2/config"
    14  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    15  	"github.com/prebid/prebid-server/v2/ortb"
    16  	"github.com/prebid/prebid-server/v2/privacy"
    17  )
    18  
    19  // Modules that need to be logged to need to be initialized here
    20  func New(analytics *config.Analytics) analytics.Runner {
    21  	modules := make(enabledAnalytics, 0)
    22  	if len(analytics.File.Filename) > 0 {
    23  		if mod, err := filesystem.NewFileLogger(analytics.File.Filename); err == nil {
    24  			modules["filelogger"] = mod
    25  		} else {
    26  			glog.Fatalf("Could not initialize FileLogger for file %v :%v", analytics.File.Filename, err)
    27  		}
    28  	}
    29  
    30  	if analytics.Pubstack.Enabled {
    31  		pubstackModule, err := pubstack.NewModule(
    32  			clients.GetDefaultHttpInstance(),
    33  			analytics.Pubstack.ScopeId,
    34  			analytics.Pubstack.IntakeUrl,
    35  			analytics.Pubstack.ConfRefresh,
    36  			analytics.Pubstack.Buffers.EventCount,
    37  			analytics.Pubstack.Buffers.BufferSize,
    38  			analytics.Pubstack.Buffers.Timeout,
    39  			clock.New())
    40  		if err == nil {
    41  			modules["pubstack"] = pubstackModule
    42  		} else {
    43  			glog.Errorf("Could not initialize PubstackModule: %v", err)
    44  		}
    45  	}
    46  
    47  	if analytics.Agma.Enabled {
    48  		agmaModule, err := agma.NewModule(
    49  			clients.GetDefaultHttpInstance(),
    50  			analytics.Agma,
    51  			clock.New())
    52  		if err == nil {
    53  			modules["agma"] = agmaModule
    54  		} else {
    55  			glog.Errorf("Could not initialize Agma Anayltics: %v", err)
    56  		}
    57  	}
    58  
    59  	return modules
    60  }
    61  
    62  // Collection of all the correctly configured analytics modules - implements the PBSAnalyticsModule interface
    63  type enabledAnalytics map[string]analytics.Module
    64  
    65  func (ea enabledAnalytics) LogAuctionObject(ao *analytics.AuctionObject, ac privacy.ActivityControl) {
    66  	for name, module := range ea {
    67  		if isAllowed, cloneBidderReq := evaluateActivities(ao.RequestWrapper, ac, name); isAllowed {
    68  			if cloneBidderReq != nil {
    69  				ao.RequestWrapper = cloneBidderReq
    70  			}
    71  			cloneReq := updateReqWrapperForAnalytics(ao.RequestWrapper, name, cloneBidderReq != nil)
    72  			module.LogAuctionObject(ao)
    73  			if cloneReq != nil {
    74  				ao.RequestWrapper = cloneReq
    75  			}
    76  		}
    77  	}
    78  }
    79  
    80  func (ea enabledAnalytics) LogVideoObject(vo *analytics.VideoObject, ac privacy.ActivityControl) {
    81  	for name, module := range ea {
    82  		if isAllowed, cloneBidderReq := evaluateActivities(vo.RequestWrapper, ac, name); isAllowed {
    83  			if cloneBidderReq != nil {
    84  				vo.RequestWrapper = cloneBidderReq
    85  			}
    86  			cloneReq := updateReqWrapperForAnalytics(vo.RequestWrapper, name, cloneBidderReq != nil)
    87  			module.LogVideoObject(vo)
    88  			if cloneReq != nil {
    89  				vo.RequestWrapper = cloneReq
    90  			}
    91  		}
    92  
    93  	}
    94  }
    95  
    96  func (ea enabledAnalytics) LogCookieSyncObject(cso *analytics.CookieSyncObject) {
    97  	for _, module := range ea {
    98  		module.LogCookieSyncObject(cso)
    99  	}
   100  }
   101  
   102  func (ea enabledAnalytics) LogSetUIDObject(so *analytics.SetUIDObject) {
   103  	for _, module := range ea {
   104  		module.LogSetUIDObject(so)
   105  	}
   106  }
   107  
   108  func (ea enabledAnalytics) LogAmpObject(ao *analytics.AmpObject, ac privacy.ActivityControl) {
   109  	for name, module := range ea {
   110  		if isAllowed, cloneBidderReq := evaluateActivities(ao.RequestWrapper, ac, name); isAllowed {
   111  			if cloneBidderReq != nil {
   112  				ao.RequestWrapper = cloneBidderReq
   113  			}
   114  			cloneReq := updateReqWrapperForAnalytics(ao.RequestWrapper, name, cloneBidderReq != nil)
   115  			module.LogAmpObject(ao)
   116  			if cloneReq != nil {
   117  				ao.RequestWrapper = cloneReq
   118  			}
   119  		}
   120  	}
   121  }
   122  
   123  func (ea enabledAnalytics) LogNotificationEventObject(ne *analytics.NotificationEvent, ac privacy.ActivityControl) {
   124  	for name, module := range ea {
   125  		component := privacy.Component{Type: privacy.ComponentTypeAnalytics, Name: name}
   126  		if ac.Allow(privacy.ActivityReportAnalytics, component, privacy.ActivityRequest{}) {
   127  			module.LogNotificationEventObject(ne)
   128  		}
   129  	}
   130  }
   131  
   132  func evaluateActivities(rw *openrtb_ext.RequestWrapper, ac privacy.ActivityControl, componentName string) (bool, *openrtb_ext.RequestWrapper) {
   133  	// returned nil request wrapper means that request wrapper was not modified by activities and doesn't have to be changed in analytics object
   134  	// it is needed in order to use one function for all analytics objects with RequestWrapper
   135  	component := privacy.Component{Type: privacy.ComponentTypeAnalytics, Name: componentName}
   136  	if !ac.Allow(privacy.ActivityReportAnalytics, component, privacy.ActivityRequest{}) {
   137  		return false, nil
   138  	}
   139  	blockUserFPD := !ac.Allow(privacy.ActivityTransmitUserFPD, component, privacy.ActivityRequest{})
   140  	blockPreciseGeo := !ac.Allow(privacy.ActivityTransmitPreciseGeo, component, privacy.ActivityRequest{})
   141  
   142  	if !blockUserFPD && !blockPreciseGeo {
   143  		return true, nil
   144  	}
   145  
   146  	cloneReq := &openrtb_ext.RequestWrapper{
   147  		BidRequest: ortb.CloneBidRequestPartial(rw.BidRequest),
   148  	}
   149  
   150  	if blockUserFPD {
   151  		privacy.ScrubUserFPD(cloneReq)
   152  	}
   153  	if blockPreciseGeo {
   154  		ipConf := privacy.IPConf{IPV6: ac.IPv6Config, IPV4: ac.IPv4Config}
   155  		privacy.ScrubGeoAndDeviceIP(cloneReq, ipConf)
   156  	}
   157  
   158  	cloneReq.RebuildRequest()
   159  	return true, cloneReq
   160  }
   161  
   162  func updateReqWrapperForAnalytics(rw *openrtb_ext.RequestWrapper, adapterName string, isCloned bool) *openrtb_ext.RequestWrapper {
   163  	if rw == nil {
   164  		return nil
   165  	}
   166  	reqExt, _ := rw.GetRequestExt()
   167  	reqExtPrebid := reqExt.GetPrebid()
   168  	if reqExtPrebid == nil {
   169  		return nil
   170  	}
   171  
   172  	var cloneReq *openrtb_ext.RequestWrapper
   173  	if !isCloned {
   174  		cloneReq = &openrtb_ext.RequestWrapper{BidRequest: ortb.CloneBidRequestPartial(rw.BidRequest)}
   175  	} else {
   176  		cloneReq = nil
   177  	}
   178  
   179  	if len(reqExtPrebid.Analytics) == 0 {
   180  		return cloneReq
   181  	}
   182  
   183  	// Remove the entire analytics object if the adapter module is not present
   184  	if _, ok := reqExtPrebid.Analytics[adapterName]; !ok {
   185  		reqExtPrebid.Analytics = nil
   186  	} else {
   187  		reqExtPrebid.Analytics = updatePrebidAnalyticsMap(reqExtPrebid.Analytics, adapterName)
   188  	}
   189  	reqExt.SetPrebid(reqExtPrebid)
   190  	rw.RebuildRequest()
   191  
   192  	if cloneReq != nil {
   193  		cloneReq.RebuildRequest()
   194  	}
   195  
   196  	return cloneReq
   197  }
   198  
   199  func updatePrebidAnalyticsMap(extPrebidAnalytics map[string]json.RawMessage, adapterName string) map[string]json.RawMessage {
   200  	newMap := make(map[string]json.RawMessage)
   201  	if val, ok := extPrebidAnalytics[adapterName]; ok {
   202  		newMap[adapterName] = val
   203  	}
   204  	return newMap
   205  }