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 }