diff --git a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/config/DatabaseReaderFactory.java b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/config/DatabaseReaderFactory.java index a40c98ebb25..371e94e7c9c 100644 --- a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/config/DatabaseReaderFactory.java +++ b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/config/DatabaseReaderFactory.java @@ -36,7 +36,7 @@ public void initialize(Promise initializePromise) { final Path databasePath = Files.createTempFile("GeoLite2-Country", ".mmdb"); try (InputStream inputStream = url.openStream(); - FileOutputStream outputStream = new FileOutputStream(databasePath.toFile())) { + FileOutputStream outputStream = new FileOutputStream(databasePath.toFile())) { inputStream.transferTo(outputStream); } diff --git a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationService.java b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationService.java index 67d42d47bc2..2b2e615d693 100644 --- a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationService.java +++ b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationService.java @@ -7,7 +7,7 @@ import org.apache.commons.lang3.StringUtils; import org.prebid.server.analytics.reporter.greenbids.model.ExplorationResult; import org.prebid.server.analytics.reporter.greenbids.model.Ortb2ImpExtResult; -import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.Partner; +import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.GreenbidsConfig; import org.prebid.server.hooks.modules.greenbids.real.time.data.model.result.AnalyticsResult; import org.prebid.server.hooks.modules.greenbids.real.time.data.model.result.GreenbidsInvocationResult; import org.prebid.server.hooks.v1.InvocationAction; @@ -23,12 +23,12 @@ public class GreenbidsInvocationService { private static final int RANGE_16_BIT_INTEGER_DIVISION_BASIS = 0x10000; public GreenbidsInvocationResult createGreenbidsInvocationResult( - Partner partner, + GreenbidsConfig greenbidsConfig, BidRequest bidRequest, Map> impsBiddersFilterMap) { final String greenbidsId = UUID.randomUUID().toString(); - final boolean isExploration = isExploration(partner, greenbidsId); + final boolean isExploration = isExploration(greenbidsConfig, greenbidsId); final BidRequest updatedBidRequest = isExploration ? bidRequest @@ -49,10 +49,10 @@ public GreenbidsInvocationResult createGreenbidsInvocationResult( return GreenbidsInvocationResult.of(updatedBidRequest, invocationAction, analyticsResult); } - private Boolean isExploration(Partner partner, String greenbidsId) { + private Boolean isExploration(GreenbidsConfig greenbidsConfig, String greenbidsId) { final int hashInt = Integer.parseInt( greenbidsId.substring(greenbidsId.length() - 4), 16); - return hashInt < partner.getExplorationRate() * RANGE_16_BIT_INTEGER_DIVISION_BASIS; + return hashInt < greenbidsConfig.getExplorationRate() * RANGE_16_BIT_INTEGER_DIVISION_BASIS; } private List updateImps(BidRequest bidRequest, Map> impsBiddersFilterMap) { diff --git a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerWithThresholds.java b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerWithThresholds.java index adbc1e17b2c..eaa184f7574 100644 --- a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerWithThresholds.java +++ b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerWithThresholds.java @@ -1,7 +1,7 @@ package org.prebid.server.hooks.modules.greenbids.real.time.data.core; import io.vertx.core.Future; -import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.Partner; +import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.GreenbidsConfig; import java.util.Objects; @@ -18,14 +18,14 @@ public OnnxModelRunnerWithThresholds( this.thresholdCache = Objects.requireNonNull(thresholdCache); } - public Future retrieveOnnxModelRunner(Partner partner) { - final String onnxModelPath = "models_pbuid=" + partner.getPbuid() + ".onnx"; - return modelCache.get(onnxModelPath, partner.getPbuid()); + public Future retrieveOnnxModelRunner(GreenbidsConfig greenbidsConfig) { + final String onnxModelPath = "models_pbuid=" + greenbidsConfig.getPbuid() + ".onnx"; + return modelCache.get(onnxModelPath, greenbidsConfig.getPbuid()); } - public Future retrieveThreshold(Partner partner) { - final String thresholdJsonPath = "thresholds_pbuid=" + partner.getPbuid() + ".json"; - return thresholdCache.get(thresholdJsonPath, partner.getPbuid()) - .map(partner::getThreshold); + public Future retrieveThreshold(GreenbidsConfig greenbidsConfig) { + final String thresholdJsonPath = "thresholds_pbuid=" + greenbidsConfig.getPbuid() + ".json"; + return thresholdCache.get(thresholdJsonPath, greenbidsConfig.getPbuid()) + .map(greenbidsConfig::getThreshold); } } diff --git a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/data/Partner.java b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/data/GreenbidsConfig.java similarity index 97% rename from extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/data/Partner.java rename to extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/data/GreenbidsConfig.java index 2be7c1887e8..babb0f1f930 100644 --- a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/data/Partner.java +++ b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/data/GreenbidsConfig.java @@ -9,7 +9,7 @@ import java.util.stream.IntStream; @Value(staticConstructor = "of") -public class Partner { +public class GreenbidsConfig { String pbuid; diff --git a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHook.java b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHook.java index 3b677a78a18..90b8744529f 100644 --- a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHook.java +++ b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHook.java @@ -21,7 +21,7 @@ import org.prebid.server.hooks.modules.greenbids.real.time.data.core.GreenbidsInvocationService; import org.prebid.server.hooks.modules.greenbids.real.time.data.core.OnnxModelRunner; import org.prebid.server.hooks.modules.greenbids.real.time.data.core.OnnxModelRunnerWithThresholds; -import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.Partner; +import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.GreenbidsConfig; import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.ThrottlingMessage; import org.prebid.server.hooks.modules.greenbids.real.time.data.model.result.AnalyticsResult; import org.prebid.server.hooks.modules.greenbids.real.time.data.model.result.GreenbidsInvocationResult; @@ -35,6 +35,8 @@ import org.prebid.server.hooks.v1.auction.ProcessedAuctionRequestHook; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountHooksConfiguration; import java.util.Collections; import java.util.List; @@ -44,10 +46,10 @@ public class GreenbidsRealTimeDataProcessedAuctionRequestHook implements ProcessedAuctionRequestHook { + private static final String BID_REQUEST_ANALYTICS_EXTENSION_NAME = "greenbids-rtd"; private static final String CODE = "greenbids-real-time-data-processed-auction-request"; private static final String ACTIVITY = "greenbids-filter"; private static final String SUCCESS_STATUS = "success"; - private static final String BID_REQUEST_ANALYTICS_EXTENSION_NAME = "greenbids-rtd"; private final ObjectMapper mapper; private final FilterService filterService; @@ -75,33 +77,30 @@ public Future> call( final AuctionContext auctionContext = invocationContext.auctionContext(); final BidRequest bidRequest = auctionContext.getBidRequest(); - final Partner partner = parseBidRequestExt(bidRequest); - - if (partner == null) { - return Future.succeededFuture(toInvocationResult( - bidRequest, null, InvocationAction.no_action)); - } + final GreenbidsConfig greenbidsConfig = Optional.ofNullable(parseBidRequestExt(auctionContext)) + .orElse(parseAccountConfig(auctionContext.getAccount())); return Future.all( - onnxModelRunnerWithThresholds.retrieveOnnxModelRunner(partner), - onnxModelRunnerWithThresholds.retrieveThreshold(partner)) + onnxModelRunnerWithThresholds.retrieveOnnxModelRunner(greenbidsConfig), + onnxModelRunnerWithThresholds.retrieveThreshold(greenbidsConfig)) .compose(compositeFuture -> toInvocationResult( bidRequest, - partner, + greenbidsConfig, compositeFuture.resultAt(0), compositeFuture.resultAt(1))) .recover(throwable -> Future.succeededFuture(toInvocationResult( bidRequest, null, InvocationAction.no_action))); } - private Partner parseBidRequestExt(BidRequest bidRequest) { - return Optional.ofNullable(bidRequest) + private GreenbidsConfig parseBidRequestExt(AuctionContext auctionContext) { + return Optional.ofNullable(auctionContext) + .map(AuctionContext::getBidRequest) .map(BidRequest::getExt) .map(ExtRequest::getPrebid) .map(ExtRequestPrebid::getAnalytics) .filter(this::isNotEmptyObjectNode) .map(analytics -> (ObjectNode) analytics.get(BID_REQUEST_ANALYTICS_EXTENSION_NAME)) - .map(this::toPartner) + .map(this::toGreenbidsConfig) .orElse(null); } @@ -109,9 +108,18 @@ private boolean isNotEmptyObjectNode(JsonNode analytics) { return analytics != null && analytics.isObject() && !analytics.isEmpty(); } - private Partner toPartner(ObjectNode adapterNode) { + private GreenbidsConfig parseAccountConfig(Account account) { + return Optional.ofNullable(account) + .map(Account::getHooks) + .map(AccountHooksConfiguration::getModules) + .map(modules -> modules.get(name())) + .map(this::toGreenbidsConfig) + .orElse(null); + } + + private GreenbidsConfig toGreenbidsConfig(ObjectNode adapterNode) { try { - return mapper.treeToValue(adapterNode, Partner.class); + return mapper.treeToValue(adapterNode, GreenbidsConfig.class); } catch (JsonProcessingException e) { return null; } @@ -119,7 +127,7 @@ private Partner toPartner(ObjectNode adapterNode) { private Future> toInvocationResult( BidRequest bidRequest, - Partner partner, + GreenbidsConfig greenbidsConfig, OnnxModelRunner onnxModelRunner, Double threshold) { @@ -138,7 +146,7 @@ private Future> toInvocationResult( } final GreenbidsInvocationResult greenbidsInvocationResult = greenbidsInvocationService - .createGreenbidsInvocationResult(partner, bidRequest, impsBiddersFilterMap); + .createGreenbidsInvocationResult(greenbidsConfig, bidRequest, impsBiddersFilterMap); return Future.succeededFuture(toInvocationResult( greenbidsInvocationResult.getUpdatedBidRequest(), @@ -207,4 +215,8 @@ private ObjectNode toObjectNode(Map values) { public String code() { return CODE; } + + public String name() { + return "greenbids"; + } } diff --git a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInferenceDataServiceTest.java b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInferenceDataServiceTest.java index 1ac1bcc5cb1..a53079046be 100644 --- a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInferenceDataServiceTest.java +++ b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInferenceDataServiceTest.java @@ -69,7 +69,7 @@ public void extractThrottlingMessagesFromBidRequestShouldReturnValidThrottlingMe .banner(banner) .build(); final Device device = givenDevice(identity()); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, null); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); final CountryResponse countryResponse = mock(CountryResponse.class); @@ -110,7 +110,7 @@ public void extractThrottlingMessagesFromBidRequestShouldHandleMissingIp() { .banner(banner) .build(); final Device device = givenDeviceWithoutIp(identity()); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, null); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); final ZonedDateTime timestamp = ZonedDateTime.now(ZoneId.of("UTC")); final Integer expectedHourBucket = timestamp.getHour(); @@ -147,7 +147,7 @@ public void extractThrottlingMessagesFromBidRequestShouldThrowPreBidExceptionWhe .banner(banner) .build(); final Device device = givenDevice(identity()); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, null); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); when(databaseReader.country(any(InetAddress.class))).thenThrow(new GeoIp2Exception("GeoIP failure")); diff --git a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationServiceTest.java b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationServiceTest.java index 1bf0f5409e4..8af8b6e2a03 100644 --- a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationServiceTest.java +++ b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationServiceTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.analytics.reporter.greenbids.model.Ortb2ImpExtResult; -import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.Partner; +import org.prebid.server.hooks.modules.greenbids.real.time.data.model.data.GreenbidsConfig; import org.prebid.server.hooks.modules.greenbids.real.time.data.model.result.GreenbidsInvocationResult; import org.prebid.server.hooks.v1.InvocationAction; @@ -45,13 +45,13 @@ public void createGreenbidsInvocationResultShouldReturnUpdateBidRequestWhenNotEx .banner(banner) .build(); final Device device = givenDevice(identity()); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, null); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); final Map> impsBiddersFilterMap = givenImpsBiddersFilterMap(); - final Partner partner = givenPartner(0.0); + final GreenbidsConfig greenbidsConfig = givenPartner(0.0); // when final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult( - partner, bidRequest, impsBiddersFilterMap); + greenbidsConfig, bidRequest, impsBiddersFilterMap); // then final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt() @@ -82,13 +82,13 @@ public void createGreenbidsInvocationResultShouldReturnNoActionWhenExploration() .banner(banner) .build(); final Device device = givenDevice(identity()); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, null); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); final Map> impsBiddersFilterMap = givenImpsBiddersFilterMap(); - final Partner partner = givenPartner(1.0); + final GreenbidsConfig greenbidsConfig = givenPartner(1.0); // when final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult( - partner, bidRequest, impsBiddersFilterMap); + greenbidsConfig, bidRequest, impsBiddersFilterMap); // then final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt() @@ -120,7 +120,7 @@ private Map> givenImpsBiddersFilterMap() { return impsBiddersFilterMap; } - private Partner givenPartner(Double explorationRate) { - return Partner.of("test-pbuid", 0.60, explorationRate); + private GreenbidsConfig givenPartner(Double explorationRate) { + return GreenbidsConfig.of("test-pbuid", 0.60, explorationRate); } } diff --git a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerTest.java b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerTest.java index 4a18b0a0fc0..51c4b34ff91 100644 --- a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerTest.java +++ b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/OnnxModelRunnerTest.java @@ -29,7 +29,7 @@ public void setUp() throws OrtException, IOException { public void runModelShouldReturnProbabilitiesWhenValidThrottlingInferenceRow() throws OrtException { // given final String[][] throttlingInferenceRow = {{ - "Chrome 59", "rubicon", "adunitcodevalue", "US", "www.leparisien.fr", "PC", "10", "1"}}; + "Chrome 59", "rubicon", "adunitcodevalue", "US", "www.leparisien.fr", "PC", "10", "1"}}; // when final OrtSession.Result actualResult = target.runModel(throttlingInferenceRow); @@ -58,7 +58,7 @@ public void runModelShouldReturnProbabilitiesWhenValidThrottlingInferenceRow() t public void runModelShouldThrowOrtExceptionWhenNonValidThrottlingInferenceRow() { // given final String[][] throttlingInferenceRowWithMissingColumn = {{ - "Chrome 59", "adunitcodevalue", "US", "www.leparisien.fr", "PC", "10", "1"}}; + "Chrome 59", "adunitcodevalue", "US", "www.leparisien.fr", "PC", "10", "1"}}; // when & then assertThatThrownBy(() -> target.runModel(throttlingInferenceRowWithMissingColumn)) diff --git a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/util/TestBidRequestProvider.java b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/util/TestBidRequestProvider.java index 11ca069e447..24ab14065f9 100644 --- a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/util/TestBidRequestProvider.java +++ b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/util/TestBidRequestProvider.java @@ -11,6 +11,7 @@ import com.iab.openrtb.request.Site; import org.prebid.server.json.ObjectMapperProvider; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import java.util.Collections; import java.util.List; @@ -25,15 +26,41 @@ private TestBidRequestProvider() { } public static BidRequest givenBidRequest( UnaryOperator bidRequestCustomizer, List imps, - Device device, - ExtRequest extRequest) { + Device device) { return bidRequestCustomizer.apply(BidRequest.builder() .id("request") .imp(imps) .site(givenSite(site -> site)) - .device(device) - .ext(extRequest)).build(); + .device(device)).build(); + } + + public static BidRequest givenBidRequestWithExtension( + UnaryOperator bidRequestCustomizer, + List imps) { + final BidRequest.BidRequestBuilder bidRequestBuilder = BidRequest.builder() + .id("request") + .imp(imps) + .site(givenSite(site -> site)) + .device(givenDevice(device -> device)) + .ext(givenExtRequest()); + + return bidRequestCustomizer.apply(bidRequestBuilder).build(); + } + + public static ExtRequest givenExtRequest() { + final ObjectNode greenbidsNode = new ObjectMapper().createObjectNode(); + greenbidsNode.put("pbuid", "leparisien"); + greenbidsNode.put("greenbidsSampling", 1.0); + + final ObjectNode analyticsNode = new ObjectMapper().createObjectNode(); + analyticsNode.set("greenbids", greenbidsNode); + + return ExtRequest.of( + ExtRequestPrebid + .builder() + .analytics(analyticsNode) + .build()); } public static Site givenSite(UnaryOperator siteCustomizer) { diff --git a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHookTest.java b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHookTest.java index e1bde277c06..6f3007e6a3b 100644 --- a/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHookTest.java +++ b/extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHookTest.java @@ -48,8 +48,8 @@ import org.prebid.server.hooks.v1.auction.AuctionInvocationContext; import org.prebid.server.hooks.v1.auction.AuctionRequestPayload; import org.prebid.server.model.HttpRequestContext; -import org.prebid.server.proto.openrtb.ext.request.ExtRequest; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountHooksConfiguration; import java.io.FileOutputStream; import java.io.IOException; @@ -70,8 +70,10 @@ import static org.mockito.Mockito.when; import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenBanner; import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenBidRequest; +import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenBidRequestWithExtension; import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenDevice; import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenDeviceWithoutUserAgent; +import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenExtRequest; import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenImpExt; import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenSite; @@ -129,7 +131,8 @@ public void setUp() throws IOException { } @Test - public void callShouldExitEarlyWhenPartnerNotActivatedInBidRequest() { + public void callShouldFilterBiddersWhenPartnerActivatedInBidRequest() + throws IOException, OrtException { // given final Banner banner = givenBanner(); @@ -139,24 +142,57 @@ public void callShouldExitEarlyWhenPartnerNotActivatedInBidRequest() { .banner(banner) .build(); + final Double explorationRate = 0.0001; final Device device = givenDevice(identity()); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, null); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, context -> context); + final BidRequest bidRequest = givenBidRequestWithExtension(identity(), List.of(imp)); + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + context -> context, + explorationRate); final AuctionInvocationContext invocationContext = givenAuctionInvocationContext(auctionContext); when(invocationContext.auctionContext()).thenReturn(auctionContext); + when(modelCacheWithExpiration.getIfPresent("onnxModelRunner_test-pbuid")) + .thenReturn(givenOnnxModelRunner()); + when(thresholdsCacheWithExpiration.getIfPresent("throttlingThresholds_test-pbuid")) + .thenReturn(givenThrottlingThresholds()); + + final BidRequest expectedBidRequest = expectedUpdatedBidRequest( + request -> request, device, true); + final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, false); // when final Future> future = target .call(null, invocationContext); final InvocationResult result = future.result(); + final BidRequest resultBidRequest = result + .payloadUpdate() + .apply(AuctionRequestPayloadImpl.of(bidRequest)) + .bidRequest(); // then + final ActivityImpl activityImpl = (ActivityImpl) result.analyticsTags().activities().getFirst(); + final ResultImpl resultImpl = (ResultImpl) activityImpl.results().getFirst(); + final String fingerprint = resultImpl.values() + .get("adunitcodevalue") + .get("greenbids") + .get("fingerprint").asText(); + assertThat(future).isNotNull(); assertThat(future.succeeded()).isTrue(); assertThat(result).isNotNull(); assertThat(result.status()).isEqualTo(InvocationStatus.success); - assertThat(result.action()).isEqualTo(InvocationAction.no_action); - assertThat(result.analyticsTags()).isNull(); + assertThat(result.action()).isEqualTo(InvocationAction.update); + assertThat(result.analyticsTags()).isNotNull(); + assertThat(result.analyticsTags()).usingRecursiveComparison() + .ignoringFields( + "activities.results" + + ".values._children" + + ".adunitcodevalue._children" + + ".greenbids._children.fingerprint") + .isEqualTo(toAnalyticsTags(List.of(expectedAnalyticsResult))); + assertThat(fingerprint).isNotNull(); + assertThat(resultBidRequest).usingRecursiveComparison() + .isEqualTo(expectedBidRequest); } @Test @@ -172,9 +208,8 @@ public void callShouldNotFilterBiddersAndReturnAnalyticsTagWhenExploration() thr final Double explorationRate = 1.0; final Device device = givenDevice(identity()); - final ExtRequest extRequest = givenExtRequest(explorationRate); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, extRequest); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, context -> context); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); + final AuctionContext auctionContext = givenAuctionContext(bidRequest, context -> context, explorationRate); final AuctionInvocationContext invocationContext = givenAuctionInvocationContext(auctionContext); when(invocationContext.auctionContext()).thenReturn(auctionContext); when(modelCacheWithExpiration.getIfPresent("onnxModelRunner_test-pbuid")) @@ -226,9 +261,8 @@ public void callShouldFilterBiddersBasedOnModelWhenAnyFeatureNotAvailable() thro final Double explorationRate = 0.0001; final Device device = givenDeviceWithoutUserAgent(identity()); - final ExtRequest extRequest = givenExtRequest(explorationRate); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, extRequest); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, context -> context); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); + final AuctionContext auctionContext = givenAuctionContext(bidRequest, context -> context, explorationRate); final AuctionInvocationContext invocationContext = givenAuctionInvocationContext(auctionContext); when(invocationContext.auctionContext()).thenReturn(auctionContext); when(modelCacheWithExpiration.getIfPresent("onnxModelRunner_test-pbuid")) @@ -236,7 +270,8 @@ public void callShouldFilterBiddersBasedOnModelWhenAnyFeatureNotAvailable() thro when(thresholdsCacheWithExpiration.getIfPresent("throttlingThresholds_test-pbuid")) .thenReturn(givenThrottlingThresholds()); - final BidRequest expectedBidRequest = expectedUpdatedBidRequest(request -> request, explorationRate, device); + final BidRequest expectedBidRequest = expectedUpdatedBidRequest( + request -> request, device, false); final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, false); // when @@ -286,9 +321,8 @@ public void callShouldFilterBiddersBasedOnModelResults() throws OrtException, IO final Double explorationRate = 0.0001; final Device device = givenDevice(identity()); - final ExtRequest extRequest = givenExtRequest(explorationRate); - final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device, extRequest); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, context -> context); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); + final AuctionContext auctionContext = givenAuctionContext(bidRequest, context -> context, explorationRate); final AuctionInvocationContext invocationContext = givenAuctionInvocationContext(auctionContext); when(invocationContext.auctionContext()).thenReturn(auctionContext); when(modelCacheWithExpiration.getIfPresent("onnxModelRunner_test-pbuid")) @@ -297,7 +331,7 @@ public void callShouldFilterBiddersBasedOnModelResults() throws OrtException, IO .thenReturn(givenThrottlingThresholds()); final BidRequest expectedBidRequest = expectedUpdatedBidRequest( - request -> request, explorationRate, device); + request -> request, device, false); final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, false); // when @@ -348,28 +382,15 @@ static DatabaseReader givenDatabaseReader() throws IOException { return new DatabaseReader.Builder(databasePath.toFile()).build(); } - static ExtRequest givenExtRequest(Double explorationRate) { - final ObjectNode greenbidsNode = TestBidRequestProvider.MAPPER.createObjectNode(); - greenbidsNode.put("pbuid", "test-pbuid"); - greenbidsNode.put("targetTpr", 0.60); - greenbidsNode.put("explorationRate", explorationRate); - - final ObjectNode analyticsNode = TestBidRequestProvider.MAPPER.createObjectNode(); - analyticsNode.set("greenbids-rtd", greenbidsNode); - - return ExtRequest.of(ExtRequestPrebid - .builder() - .analytics(analyticsNode) - .build()); - } - private AuctionContext givenAuctionContext( BidRequest bidRequest, - UnaryOperator auctionContextCustomizer) { + UnaryOperator auctionContextCustomizer, + Double explorationRate) { final AuctionContext.AuctionContextBuilder auctionContextBuilder = AuctionContext.builder() .httpRequest(HttpRequestContext.builder().build()) - .bidRequest(bidRequest); + .bidRequest(bidRequest) + .account(givenAccount(explorationRate)); return auctionContextCustomizer.apply(auctionContextBuilder).build(); } @@ -380,6 +401,23 @@ private AuctionInvocationContext givenAuctionInvocationContext(AuctionContext au return invocationContext; } + private Account givenAccount(Double explorationRate) { + return Account.builder() + .id("test-account") + .hooks(givenAccountHooksConfiguration(explorationRate)) + .build(); + } + + private AccountHooksConfiguration givenAccountHooksConfiguration(Double explorationRate) { + final ObjectNode greenbidsNode = TestBidRequestProvider.MAPPER.createObjectNode(); + greenbidsNode.put("enabled", true); + greenbidsNode.put("pbuid", "test-pbuid"); + greenbidsNode.put("targetTpr", 0.60); + greenbidsNode.put("explorationRate", explorationRate); + final Map modules = Map.of("greenbids", greenbidsNode); + return AccountHooksConfiguration.of(null, modules, null); + } + private OnnxModelRunner givenOnnxModelRunner() throws OrtException, IOException { final byte[] onnxModelBytes = Files.readAllBytes(Paths.get( "src/test/resources/models_pbuid=test-pbuid.onnx")); @@ -396,8 +434,8 @@ private ThrottlingThresholds givenThrottlingThresholds() throws IOException { private BidRequest expectedUpdatedBidRequest( UnaryOperator bidRequestCustomizer, - Double explorationRate, - Device device) { + Device device, + Boolean isExtRequest) { final Banner banner = givenBanner(); @@ -415,12 +453,17 @@ private BidRequest expectedUpdatedBidRequest( .banner(banner) .build(); - return bidRequestCustomizer.apply(BidRequest.builder() + final BidRequest.BidRequestBuilder bidRequestBuilder = BidRequest.builder() .id("request") .imp(List.of(imp)) .site(givenSite(site -> site)) - .device(device) - .ext(givenExtRequest(explorationRate))).build(); + .device(device); + + if (isExtRequest) { + bidRequestBuilder.ext(givenExtRequest()); + } + + return bidRequestCustomizer.apply(bidRequestBuilder).build(); } private AnalyticsResult expectedAnalyticsResult(Boolean isExploration, Boolean isKeptInAuction) { diff --git a/src/main/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporter.java b/src/main/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporter.java index 51196d0c2e9..4f1dadb25af 100644 --- a/src/main/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporter.java +++ b/src/main/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporter.java @@ -26,7 +26,7 @@ import org.prebid.server.analytics.reporter.greenbids.model.GreenbidsAdUnit; import org.prebid.server.analytics.reporter.greenbids.model.GreenbidsAnalyticsProperties; import org.prebid.server.analytics.reporter.greenbids.model.GreenbidsBid; -import org.prebid.server.analytics.reporter.greenbids.model.GreenbidsPrebidExt; +import org.prebid.server.analytics.reporter.greenbids.model.GreenbidsConfig; import org.prebid.server.analytics.reporter.greenbids.model.GreenbidsSource; import org.prebid.server.analytics.reporter.greenbids.model.GreenbidsUnifiedCode; import org.prebid.server.analytics.reporter.greenbids.model.MediaTypes; @@ -53,6 +53,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtStoredRequest; import org.prebid.server.proto.openrtb.ext.response.seatnonbid.NonBid; import org.prebid.server.proto.openrtb.ext.response.seatnonbid.SeatNonBid; +import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountAnalyticsConfig; import org.prebid.server.util.HttpUtil; import org.prebid.server.version.PrebidVersionProvider; import org.prebid.server.vertx.httpclient.HttpClient; @@ -117,9 +119,10 @@ public Future processEvent(T event) { return Future.failedFuture(new PreBidException("Bid response or auction context cannot be null")); } - final GreenbidsPrebidExt greenbidsBidRequestExt = parseBidRequestExt(auctionContext.getBidRequest()); + final GreenbidsConfig greenbidsConfig = Optional.ofNullable(parseBidRequestExt(auctionContext)) + .orElse(parseAccountConfig(auctionContext.getAccount())); - if (greenbidsBidRequestExt == null) { + if (greenbidsConfig == null) { return Future.succeededFuture(); } @@ -130,7 +133,7 @@ public Future processEvent(T event) { final String greenbidsId = greenbidsId(analyticsResultFromAnalyticsTag); - if (!isSampled(greenbidsBidRequestExt.getGreenbidsSampling(), greenbidsId)) { + if (!isSampled(greenbidsConfig.getGreenbidsSampling(), greenbidsId)) { return Future.succeededFuture(); } @@ -141,7 +144,7 @@ public Future processEvent(T event) { bidResponse, greenbidsId, billingId, - greenbidsBidRequestExt, + greenbidsConfig, analyticsResultFromAnalyticsTag); commonMessageJson = jacksonMapper.encodeToString(commonMessage); } catch (PreBidException e) { @@ -169,14 +172,15 @@ public Future processEvent(T event) { return responseFuture.compose(this::processAnalyticServerResponse); } - private GreenbidsPrebidExt parseBidRequestExt(BidRequest bidRequest) { - return Optional.ofNullable(bidRequest) + private GreenbidsConfig parseBidRequestExt(AuctionContext auctionContext) { + return Optional.ofNullable(auctionContext) + .map(AuctionContext::getBidRequest) .map(BidRequest::getExt) .map(ExtRequest::getPrebid) .map(ExtRequestPrebid::getAnalytics) .filter(this::isNotEmptyObjectNode) .map(analytics -> (ObjectNode) analytics.get(BID_REQUEST_ANALYTICS_EXTENSION_NAME)) - .map(this::toGreenbidsPrebidExt) + .map(this::toGreenbidsConfig) .orElse(null); } @@ -184,9 +188,18 @@ private boolean isNotEmptyObjectNode(JsonNode analytics) { return analytics != null && analytics.isObject() && !analytics.isEmpty(); } - private GreenbidsPrebidExt toGreenbidsPrebidExt(ObjectNode adapterNode) { + private GreenbidsConfig parseAccountConfig(Account account) { + return Optional.ofNullable(account) + .map(Account::getAnalytics) + .map(AccountAnalyticsConfig::getModules) + .map(analyticsModules -> analyticsModules.get(name())) + .map(this::toGreenbidsConfig) + .orElse(null); + } + + private GreenbidsConfig toGreenbidsConfig(ObjectNode adapterNode) { try { - return jacksonMapper.mapper().treeToValue(adapterNode, GreenbidsPrebidExt.class); + return jacksonMapper.mapper().treeToValue(adapterNode, GreenbidsConfig.class); } catch (JsonProcessingException e) { throw new PreBidException("Error decoding bid request analytics extension: " + e.getMessage(), e); } @@ -289,7 +302,7 @@ private CommonMessage createBidMessage( BidResponse bidResponse, String greenbidsId, String billingId, - GreenbidsPrebidExt greenbidsImpExt, + GreenbidsConfig greenbidsImpExt, Map analyticsResultFromAnalyticsTag) { final Optional bidRequest = Optional.ofNullable(auctionContext.getBidRequest()); diff --git a/src/main/java/org/prebid/server/analytics/reporter/greenbids/model/GreenbidsPrebidExt.java b/src/main/java/org/prebid/server/analytics/reporter/greenbids/model/GreenbidsConfig.java similarity index 88% rename from src/main/java/org/prebid/server/analytics/reporter/greenbids/model/GreenbidsPrebidExt.java rename to src/main/java/org/prebid/server/analytics/reporter/greenbids/model/GreenbidsConfig.java index d5983205898..b666fb83552 100644 --- a/src/main/java/org/prebid/server/analytics/reporter/greenbids/model/GreenbidsPrebidExt.java +++ b/src/main/java/org/prebid/server/analytics/reporter/greenbids/model/GreenbidsConfig.java @@ -4,7 +4,7 @@ import lombok.Value; @Value(staticConstructor = "of") -public class GreenbidsPrebidExt { +public class GreenbidsConfig { String pbuid; diff --git a/src/test/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporterTest.java b/src/test/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporterTest.java index ab16f5a1b40..bf179f7452b 100644 --- a/src/test/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporterTest.java +++ b/src/test/java/org/prebid/server/analytics/reporter/greenbids/GreenbidsAnalyticsReporterTest.java @@ -53,17 +53,8 @@ import org.prebid.server.model.HttpRequestContext; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; -import org.prebid.server.proto.openrtb.ext.response.ExtBidResponse; -import org.prebid.server.proto.openrtb.ext.response.ExtBidResponsePrebid; -import org.prebid.server.proto.openrtb.ext.response.ExtModules; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTrace; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceAnalyticsActivity; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceAnalyticsResult; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceAnalyticsTags; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceGroup; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceInvocationResult; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceStage; -import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceStageOutcome; +import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountAnalyticsConfig; import org.prebid.server.util.HttpUtil; import org.prebid.server.version.PrebidVersionProvider; import org.prebid.server.vertx.httpclient.HttpClient; @@ -138,6 +129,58 @@ public void setUp() { prebidVersionProvider); } + @Test + public void shouldReceiveValidResponseOnAuctionContextForBannerWhenPartnerActivatedInBidRequest() + throws IOException { + // given + final Banner banner = givenBanner(); + + final ObjectNode impExtNode = mapper.createObjectNode(); + impExtNode.set("gpid", TextNode.valueOf("gpidvalue")); + impExtNode.set("prebid", givenPrebidBidderParamsNode()); + + final Imp imp = Imp.builder() + .id("adunitcodevalue") + .ext(impExtNode) + .banner(banner) + .build(); + + final AuctionContext auctionContext = givenAuctionContext( + builder -> builder.bidRequest(givenBidRequestWithExtension(identity(), List.of(imp))), + List.of(imp), + true); + final AuctionEvent event = AuctionEvent.builder() + .auctionContext(auctionContext) + .bidResponse(auctionContext.getBidResponse()) + .build(); + + final HttpClientResponse mockResponse = mock(HttpClientResponse.class); + when(mockResponse.getStatusCode()).thenReturn(202); + when(httpClient.post(anyString(), any(MultiMap.class), anyString(), anyLong())) + .thenReturn(Future.succeededFuture(mockResponse)); + final CommonMessage expectedCommonMessage = expectedCommonMessageForBanner(); + + // when + target.processEvent(event); + + // then + verify(httpClient).post( + eq(greenbidsAnalyticsProperties.getAnalyticsServerUrl()), + any(MultiMap.class), + jsonCaptor.capture(), + eq(greenbidsAnalyticsProperties.getTimeoutMs())); + + final String capturedJson = jsonCaptor.getValue(); + final CommonMessage capturedCommonMessage = jacksonMapper.mapper() + .readValue(capturedJson, CommonMessage.class); + + assertThat(capturedCommonMessage).usingRecursiveComparison() + .ignoringFields("billingId", "greenbidsId") + .isEqualTo(expectedCommonMessage); + assertThat(capturedCommonMessage.getGreenbidsId()).isNotNull(); + assertThat(capturedCommonMessage.getBillingId()).isNotNull(); + } + @Test public void shouldReceiveValidResponseOnAuctionContextWithAnalyticsTagForBanner() throws IOException { // given @@ -154,7 +197,7 @@ public void shouldReceiveValidResponseOnAuctionContextWithAnalyticsTagForBanner( .build(); final AuctionContext auctionContext = givenAuctionContextWithAnalyticsTag( - context -> context, List.of(imp), true, true); + context -> context, List.of(imp), true); final AuctionEvent event = AuctionEvent.builder() .auctionContext(auctionContext) .bidResponse(auctionContext.getBidResponse()) @@ -520,8 +563,9 @@ public void shouldFailWhenAdUnitsListIsEmpty() { when(auctionContext.getBidRequest()) .thenReturn(BidRequest.builder() .id("request1") - .ext(givenExtRequest()) + .imp(Collections.emptyList()) .build()); + when(auctionContext.getAccount()).thenReturn(givenAccount()); final AuctionEvent event = mock(AuctionEvent.class); when(event.getAuctionContext()).thenReturn(auctionContext); @@ -583,7 +627,8 @@ private static AuctionContext givenAuctionContext( final AuctionContext.AuctionContextBuilder auctionContextBuilder = AuctionContext.builder() .httpRequest(HttpRequestContext.builder().build()) .bidRequest(givenBidRequest(request -> request, imps)) - .bidRejectionTrackers(Map.of("seat3", givenBidRejectionTracker())); + .bidRejectionTrackers(Map.of("seat3", givenBidRejectionTracker())) + .account(givenAccount()); if (includeBidResponse) { auctionContextBuilder.bidResponse(givenBidResponse(response -> response)); @@ -595,17 +640,15 @@ private static AuctionContext givenAuctionContext( private static AuctionContext givenAuctionContextWithAnalyticsTag( UnaryOperator auctionContextCustomizer, List imps, - boolean includeBidResponse, - boolean includeHookExecutionContextWithAnalyticsTag) { + boolean includeBidResponse) { final AuctionContext.AuctionContextBuilder auctionContextBuilder = AuctionContext.builder() .httpRequest(HttpRequestContext.builder().build()) .bidRequest(givenBidRequest(request -> request, imps)) - .bidRejectionTrackers(Map.of("seat3", givenBidRejectionTracker())); + .bidRejectionTrackers(Map.of("seat3", givenBidRejectionTracker())) + .account(givenAccount()); - if (includeHookExecutionContextWithAnalyticsTag) { - final HookExecutionContext hookExecutionContext = givenHookExecutionContextWithAnalyticsTag(); - auctionContextBuilder.hookExecutionContext(hookExecutionContext); - } + final HookExecutionContext hookExecutionContext = givenHookExecutionContextWithAnalyticsTag(); + auctionContextBuilder.hookExecutionContext(hookExecutionContext); if (includeBidResponse) { auctionContextBuilder.bidResponse(givenBidResponse(response -> response)); @@ -614,15 +657,59 @@ private static AuctionContext givenAuctionContextWithAnalyticsTag( return auctionContextCustomizer.apply(auctionContextBuilder).build(); } + private static Account givenAccount() { + return Account.builder() + .id("test-account") + .analytics(givenAccountHooksConfiguration()) + .build(); + } + + private static AccountAnalyticsConfig givenAccountHooksConfiguration() { + final ObjectNode greenbidsNode = mapper.createObjectNode(); + greenbidsNode.put("pbuid", "leparisien"); + greenbidsNode.put("greenbidsSampling", 1.0); + final Map modules = Map.of("greenbids", greenbidsNode); + return AccountAnalyticsConfig.of(true, null, modules); + } + private static BidRequest givenBidRequest( UnaryOperator bidRequestCustomizer, List imps) { - return bidRequestCustomizer.apply(BidRequest.builder() + final BidRequest.BidRequestBuilder bidRequestBuilder = BidRequest.builder() + .id("request1") + .imp(imps) + .site(givenSite(site -> site)) + .device(givenDevice(device -> device)); + + return bidRequestCustomizer.apply(bidRequestBuilder).build(); + } + + private static BidRequest givenBidRequestWithExtension( + UnaryOperator bidRequestCustomizer, + List imps) { + final BidRequest.BidRequestBuilder bidRequestBuilder = BidRequest.builder() .id("request1") .imp(imps) .site(givenSite(site -> site)) .device(givenDevice(device -> device)) - .ext(givenExtRequest())).build(); + .ext(givenExtRequest()); + + return bidRequestCustomizer.apply(bidRequestBuilder).build(); + } + + private static ExtRequest givenExtRequest() { + final ObjectNode greenbidsNode = new ObjectMapper().createObjectNode(); + greenbidsNode.put("pbuid", "leparisien"); + greenbidsNode.put("greenbidsSampling", 1.0); + + final ObjectNode analyticsNode = new ObjectMapper().createObjectNode(); + analyticsNode.set("greenbids", greenbidsNode); + + return ExtRequest.of( + ExtRequestPrebid + .builder() + .analytics(analyticsNode) + .build()); } private static Site givenSite(UnaryOperator siteCustomizer) { @@ -683,55 +770,6 @@ private static BidResponse givenBidResponse(UnaryOperator bidResponseCustomizer) { - final ObjectNode analyticsResultNode = mapper.valueToTree( - singletonMap( - "adunitcodevalue", - createAnalyticsResultNode())); - - final ExtModulesTraceAnalyticsTags analyticsTags = ExtModulesTraceAnalyticsTags.of( - Collections.singletonList( - ExtModulesTraceAnalyticsActivity.of( - null, null, Collections.singletonList( - ExtModulesTraceAnalyticsResult.of( - null, analyticsResultNode, null))))); - - final ExtModulesTraceInvocationResult invocationResult = ExtModulesTraceInvocationResult.builder() - .hookId(HookId.of("greenbids-real-time-data", null)) - .analyticsTags(analyticsTags) - .build(); - - final ExtModulesTraceStageOutcome outcome = ExtModulesTraceStageOutcome.of( - "auction-request", null, - Collections.singletonList(ExtModulesTraceGroup.of( - null, Collections.singletonList(invocationResult)))); - - final ExtModulesTraceStage stage = ExtModulesTraceStage.of( - Stage.processed_auction_request, null, - Collections.singletonList(outcome)); - - final ExtModulesTrace modulesTrace = ExtModulesTrace.of(null, Collections.singletonList(stage)); - - final ExtModules modules = ExtModules.of(null, null, modulesTrace); - - final ExtBidResponsePrebid prebid = ExtBidResponsePrebid.builder().modules(modules).build(); - - final ExtBidResponse extBidResponse = ExtBidResponse.builder().prebid(prebid).build(); - - return bidResponseCustomizer.apply(BidResponse.builder() - .id("response2") - .seatbid(List.of( - givenSeatBid( - seatBid -> seatBid.seat("seat1"), - bid -> bid.id("bid1").price(BigDecimal.valueOf(1.5))), - givenSeatBid( - seatBid -> seatBid.seat("seat2"), - bid -> bid.id("bid2").price(BigDecimal.valueOf(0.5))))) - .cur("USD") - .ext(extBidResponse)).build(); - } - private static ObjectNode createAnalyticsResultNode() { final ObjectNode keptInAuctionNode = new ObjectNode(JsonNodeFactory.instance); keptInAuctionNode.put("seat1", true); @@ -801,21 +839,6 @@ private static ObjectNode givenPrebidBidderParamsNode() { return prebidNode; } - private static ExtRequest givenExtRequest() { - final ObjectNode greenbidsNode = new ObjectMapper().createObjectNode(); - greenbidsNode.put("pbuid", "leparisien"); - greenbidsNode.put("greenbidsSampling", 1.0); - - final ObjectNode analyticsNode = new ObjectMapper().createObjectNode(); - analyticsNode.set("greenbids", greenbidsNode); - - return ExtRequest.of( - ExtRequestPrebid - .builder() - .analytics(analyticsNode) - .build()); - } - private static CommonMessage expectedCommonMessageForBanner() { return expectedCommonMessage( adUnit -> adUnit