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 47da698c627..889945874fc 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 @@ -32,21 +32,24 @@ public GreenbidsInvocationResult createGreenbidsInvocationResult( final String greenbidsId = UUID.randomUUID().toString(); final boolean isExploration = isExploration(greenbidsConfig, greenbidsId); - final BidRequest updatedBidRequest = isExploration + final List updatedImps = updateImps(bidRequest, impsBiddersFilterMap); + + final BidRequest updatedBidRequest = (isExploration || updatedImps.isEmpty()) ? bidRequest : bidRequest.toBuilder() - .imp(updateImps(bidRequest, impsBiddersFilterMap)) + .imp(updatedImps) .build(); - final InvocationAction invocationAction = isExploration - ? InvocationAction.no_action - : InvocationAction.update; - final Map> impsBiddersFilterMapToAnalyticsTag = isExploration - ? keepAllBiddersForAnalyticsResult(impsBiddersFilterMap) - : impsBiddersFilterMap; + + final InvocationAction invocationAction = updatedImps.isEmpty() + ? InvocationAction.reject + : isExploration + ? InvocationAction.no_action + : InvocationAction.update; + final Map ort2ImpExtResultMap = createOrtb2ImpExtForImps( - bidRequest, impsBiddersFilterMapToAnalyticsTag, greenbidsId, isExploration); + bidRequest, impsBiddersFilterMap, greenbidsId, isExploration); final AnalyticsResult analyticsResult = AnalyticsResult.of( - "success", ort2ImpExtResultMap, null, null); + "success", ort2ImpExtResultMap); return GreenbidsInvocationResult.of(updatedBidRequest, invocationAction, analyticsResult); } @@ -61,10 +64,15 @@ private Boolean isExploration(GreenbidsConfig greenbidsConfig, String greenbidsI private List updateImps(BidRequest bidRequest, Map> impsBiddersFilterMap) { return bidRequest.getImp().stream() + .filter(imp -> isImpKept(imp, impsBiddersFilterMap)) .map(imp -> updateImp(imp, impsBiddersFilterMap.get(imp.getId()))) .toList(); } + private boolean isImpKept(Imp imp, Map> impsBiddersFilterMap) { + return impsBiddersFilterMap.get(imp.getId()).values().stream().anyMatch(isKept -> isKept); + } + private Imp updateImp(Imp imp, Map bidderFilterMap) { return imp.toBuilder() .ext(updateImpExt(imp.getExt(), bidderFilterMap)) @@ -83,16 +91,6 @@ private ObjectNode updateImpExt(ObjectNode impExt, Map bidderFi return updatedExt; } - private Map> keepAllBiddersForAnalyticsResult( - Map> impsBiddersFilterMap) { - - return impsBiddersFilterMap.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - entry -> entry.getValue().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> true)))); - } - private Map createOrtb2ImpExtForImps( 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/model/result/AnalyticsResult.java b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/result/AnalyticsResult.java index 9d175b5b4b3..f324ac195db 100644 --- a/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/result/AnalyticsResult.java +++ b/extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/result/AnalyticsResult.java @@ -11,8 +11,4 @@ public class AnalyticsResult { String status; Map values; - - String bidder; - - String impId; } 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 5188b756ddc..3ad8106e141 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 @@ -7,6 +7,8 @@ import com.iab.openrtb.request.BidRequest; import io.vertx.core.Future; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.prebid.server.analytics.reporter.greenbids.model.ExplorationResult; import org.prebid.server.analytics.reporter.greenbids.model.Ortb2ImpExtResult; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.exception.PreBidException; @@ -38,6 +40,7 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountHooksConfiguration; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -155,29 +158,25 @@ private InvocationResult toInvocationResult( AnalyticsResult analyticsResult, InvocationAction action) { - final List analyticsResults = analyticsResult != null - ? Collections.singletonList(analyticsResult) - : Collections.emptyList(); - return switch (action) { case InvocationAction.update -> InvocationResultImpl .builder() .status(InvocationStatus.success) .action(action) .payloadUpdate(payload -> AuctionRequestPayloadImpl.of(bidRequest)) - .analyticsTags(toAnalyticsTags(analyticsResults)) + .analyticsTags(toAnalyticsTags(analyticsResult)) .build(); default -> InvocationResultImpl .builder() .status(InvocationStatus.success) .action(action) - .analyticsTags(toAnalyticsTags(analyticsResults)) + .analyticsTags(toAnalyticsTags(analyticsResult)) .build(); }; } - private Tags toAnalyticsTags(List analyticsResults) { - if (CollectionUtils.isEmpty(analyticsResults)) { + private Tags toAnalyticsTags(AnalyticsResult analyticsResults) { + if (analyticsResults == null) { return null; } @@ -187,23 +186,35 @@ private Tags toAnalyticsTags(List analyticsResults) { toResults(analyticsResults)))); } - private List toResults(List analyticsResults) { - return analyticsResults.stream() - .map(this::toResult) + private List toResults(AnalyticsResult analyticsResult) { + return analyticsResult.getValues().entrySet().stream() + .map(entry -> toResult(analyticsResult.getStatus(), entry)) .toList(); } - private Result toResult(AnalyticsResult analyticsResult) { + private Result toResult(String status, Map.Entry entry) { + final String impId = entry.getKey(); + final Ortb2ImpExtResult ortb2ImpExtResult = entry.getValue(); + final List removedBidders = Optional.ofNullable(ortb2ImpExtResult) + .map(Ortb2ImpExtResult::getGreenbids) + .map(ExplorationResult::getKeptInAuction) + .map(Map::entrySet) + .stream() + .flatMap(Collection::stream) + .filter(e -> BooleanUtils.isFalse(e.getValue())) + .map(Map.Entry::getKey) + .toList(); + return ResultImpl.of( - analyticsResult.getStatus(), - toObjectNode(analyticsResult.getValues()), + status, + toObjectNode(entry), AppliedToImpl.builder() - .bidders(Collections.singletonList(analyticsResult.getBidder())) - .impIds(Collections.singletonList(analyticsResult.getImpId())) + .impIds(Collections.singletonList(impId)) + .bidders(removedBidders.isEmpty() ? null: removedBidders) .build()); } - private ObjectNode toObjectNode(Map values) { + private ObjectNode toObjectNode(Map.Entry values) { return values != null ? mapper.valueToTree(values) : null; } 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 8af8b6e2a03..0c137ffa403 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 @@ -24,6 +24,7 @@ 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.givenDevice; 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.givenImpExtToFilterAllBidders; @ExtendWith(MockitoExtension.class) public class GreenbidsInvocationServiceTest { @@ -69,7 +70,6 @@ public void createGreenbidsInvocationResultShouldReturnUpdateBidRequestWhenNotEx assertThat(keptInAuction.get("rubicon")).isTrue(); assertThat(keptInAuction.get("appnexus")).isFalse(); assertThat(keptInAuction.get("pubmatic")).isFalse(); - } @Test @@ -104,8 +104,87 @@ public void createGreenbidsInvocationResultShouldReturnNoActionWhenExploration() assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isTrue(); assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull(); assertThat(keptInAuction.get("rubicon")).isTrue(); - assertThat(keptInAuction.get("appnexus")).isTrue(); - assertThat(keptInAuction.get("pubmatic")).isTrue(); + assertThat(keptInAuction.get("appnexus")).isFalse(); + assertThat(keptInAuction.get("pubmatic")).isFalse(); + } + + @Test + public void createGreenbidsInvocationResultShouldReturnRejectWhenAllImpsFiltered() { + // given + final Banner banner = givenBanner(); + final Imp imp = Imp.builder() + .id("adunitcodevalue") + .ext(givenImpExt()) + .banner(banner) + .build(); + final Device device = givenDevice(identity()); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device); + final Map> impsBiddersFilterMap = givenFilterMapWithAllFilteredImps(); + final GreenbidsConfig greenbidsConfig = givenPartner(1.0); + + // when + final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult( + greenbidsConfig, bidRequest, impsBiddersFilterMap); + + // then + final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt() + .get("prebid").get("bidder"); + final Ortb2ImpExtResult ortb2ImpExtResult = result.getAnalyticsResult().getValues().get("adunitcodevalue"); + final Map keptInAuction = ortb2ImpExtResult.getGreenbids().getKeptInAuction(); + + assertThat(result.getInvocationAction()).isEqualTo(InvocationAction.reject); + assertThat(updatedBidRequestExtPrebidBidders.has("rubicon")).isTrue(); + assertThat(updatedBidRequestExtPrebidBidders.has("appnexus")).isTrue(); + assertThat(updatedBidRequestExtPrebidBidders.has("pubmatic")).isTrue(); + assertThat(ortb2ImpExtResult).isNotNull(); + assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isTrue(); + assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull(); + assertThat(keptInAuction.get("rubicon")).isFalse(); + assertThat(keptInAuction.get("appnexus")).isFalse(); + assertThat(keptInAuction.get("pubmatic")).isFalse(); + } + + @Test + public void createGreenbidsInvocationResultShouldRemoveImpFromUpdateBidRequestWhenAllBiddersFiltered() { + // given + final Banner banner = givenBanner(); + final Imp imp1 = Imp.builder() + .id("adunitcodevalue1") + .ext(givenImpExt()) + .banner(banner) + .build(); + final Imp imp2 = Imp.builder() + .id("adunitcodevalue2") + .ext(givenImpExtToFilterAllBidders()) + .banner(banner) + .build(); + final Device device = givenDevice(identity()); + final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp1, imp2), device); + final Map> impsBiddersFilterMap = givenFilterMapWithAllFilteredBiddersInImp(); + final GreenbidsConfig greenbidsConfig = givenPartner(0.0); + + // when + final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult( + greenbidsConfig, bidRequest, impsBiddersFilterMap); + + // then + final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt() + .get("prebid").get("bidder"); + final Ortb2ImpExtResult ortb2ImpExtResult = result.getAnalyticsResult().getValues().get("adunitcodevalue1"); + final Map keptInAuction = ortb2ImpExtResult.getGreenbids().getKeptInAuction(); + + assertThat(result.getInvocationAction()).isEqualTo(InvocationAction.update); + assertThat(result.getUpdatedBidRequest().getImp()).hasSize(1); + assertThat(updatedBidRequestExtPrebidBidders.has("rubicon")).isTrue(); + assertThat(updatedBidRequestExtPrebidBidders.has("appnexus")).isFalse(); + assertThat(updatedBidRequestExtPrebidBidders.has("pubmatic")).isFalse(); + assertThat(ortb2ImpExtResult).isNotNull(); + assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isFalse(); + assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull(); + assertThat(keptInAuction.get("rubicon")).isTrue(); + assertThat(keptInAuction.get("appnexus")).isFalse(); + assertThat(keptInAuction.get("pubmatic")).isFalse(); + } private Map> givenImpsBiddersFilterMap() { @@ -120,6 +199,34 @@ private Map> givenImpsBiddersFilterMap() { return impsBiddersFilterMap; } + private Map> givenFilterMapWithAllFilteredImps() { + final Map biddersFitlerMap = new HashMap<>(); + biddersFitlerMap.put("rubicon", false); + biddersFitlerMap.put("appnexus", false); + biddersFitlerMap.put("pubmatic", false); + + final Map> impsBiddersFilterMap = new HashMap<>(); + impsBiddersFilterMap.put("adunitcodevalue", biddersFitlerMap); + + return impsBiddersFilterMap; + } + + private Map> givenFilterMapWithAllFilteredBiddersInImp() { + final Map biddersFitlerMapForKeptImp = new HashMap<>(); + biddersFitlerMapForKeptImp.put("rubicon", true); + biddersFitlerMapForKeptImp.put("appnexus", false); + biddersFitlerMapForKeptImp.put("pubmatic", false); + + final Map biddersFitlerMapForRemovedImp = new HashMap<>(); + biddersFitlerMapForRemovedImp.put("appnexus", false); + + final Map> impsBiddersFilterMap = new HashMap<>(); + impsBiddersFilterMap.put("adunitcodevalue1", biddersFitlerMapForKeptImp); + impsBiddersFilterMap.put("adunitcodevalue2", biddersFitlerMapForRemovedImp); + + return impsBiddersFilterMap; + } + 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/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 7cb8e902dff..5e07f350869 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 @@ -96,6 +96,23 @@ public static ObjectNode givenImpExt() { return extNode; } + public static ObjectNode givenImpExtToFilterAllBidders() { + final ObjectNode bidderNode = MAPPER.createObjectNode(); + + final ObjectNode appnexusNode = MAPPER.createObjectNode(); + appnexusNode.put("placementId", 789); + bidderNode.set("appnexus", appnexusNode); + + final ObjectNode prebidNode = MAPPER.createObjectNode(); + prebidNode.set("bidder", bidderNode); + + final ObjectNode extNode = MAPPER.createObjectNode(); + extNode.set("prebid", prebidNode); + extNode.set("tid", TextNode.valueOf("af65045c-2774-44c2-a949-4f42d5c9e179")); + + return extNode; + } + public static Device givenDevice(UnaryOperator deviceCustomizer, String countryAlpha3) { final String userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36" + " (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"; 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 07f13d519f4..26b4fe37a31 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 @@ -52,8 +52,6 @@ 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.settings.model.Account; -import org.prebid.server.settings.model.AccountHooksConfiguration; import java.io.IOException; import java.net.InetAddress; @@ -178,7 +176,7 @@ public void callShouldFilterBiddersWhenPartnerActivatedInBidRequest() final BidRequest expectedBidRequest = expectedUpdatedBidRequest( request -> request, device, true); - final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, false); + final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, true); // when final Future> future = target @@ -216,7 +214,7 @@ public void callShouldFilterBiddersWhenPartnerActivatedInBidRequest() } @Test - public void callShouldNotFilterBiddersAndReturnAnalyticsTagWhenExploration() throws OrtException, IOException { + public void callShouldFilterBiddersAndReturnAnalyticsTagWhenExploration() throws OrtException, IOException { // given final Banner banner = givenBanner(); @@ -294,7 +292,7 @@ public void callShouldFilterBiddersBasedOnModelWhenAnyFeatureNotAvailable() thro final BidRequest expectedBidRequest = expectedUpdatedBidRequest( request -> request, device, false); - final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, false); + final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, true); // when final Future> future = target @@ -355,7 +353,7 @@ public void callShouldFilterBiddersBasedOnModelResults() throws OrtException, IO final BidRequest expectedBidRequest = expectedUpdatedBidRequest( request -> request, device, false); - final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, false); + final AnalyticsResult expectedAnalyticsResult = expectedAnalyticsResult(false, true); // when final Future> future = target @@ -415,7 +413,7 @@ private ObjectNode givenAccountConfig(Double explorationRate) { final ObjectNode greenbidsNode = TestBidRequestProvider.MAPPER.createObjectNode(); greenbidsNode.put("enabled", true); greenbidsNode.put("pbuid", "test-pbuid"); - greenbidsNode.put("target-tpr", 0.60); + greenbidsNode.put("target-tpr", 0.99); greenbidsNode.put("exploration-rate", explorationRate); return greenbidsNode; } @@ -442,6 +440,22 @@ private BidRequest expectedUpdatedBidRequest( final Banner banner = givenBanner(); final ObjectNode bidderNode = TestBidRequestProvider.MAPPER.createObjectNode(); + + final ObjectNode rubiconNode = TestBidRequestProvider.MAPPER.createObjectNode(); + rubiconNode.put("accountId", 1001); + rubiconNode.put("siteId", 267318); + rubiconNode.put("zoneId", 1861698); + bidderNode.set("rubicon", rubiconNode); + + final ObjectNode appnexusNode = TestBidRequestProvider.MAPPER.createObjectNode(); + appnexusNode.put("placementId", 123456); + bidderNode.set("appnexus", appnexusNode); + + final ObjectNode pubmaticNode = TestBidRequestProvider.MAPPER.createObjectNode(); + pubmaticNode.put("publisherId", "156209"); + pubmaticNode.put("adSlot", "slot1@300x250"); + bidderNode.set("pubmatic", pubmaticNode); + final ObjectNode prebidNode = TestBidRequestProvider.MAPPER.createObjectNode(); prebidNode.set("bidder", bidderNode); @@ -471,9 +485,7 @@ private BidRequest expectedUpdatedBidRequest( private AnalyticsResult expectedAnalyticsResult(Boolean isExploration, Boolean isKeptInAuction) { return AnalyticsResult.of( "success", - Map.of("adunitcodevalue", expectedOrtb2ImpExtResult(isExploration, isKeptInAuction)), - null, - null); + Map.of("adunitcodevalue", expectedOrtb2ImpExtResult(isExploration, isKeptInAuction))); } private Ortb2ImpExtResult expectedOrtb2ImpExtResult(Boolean isExploration, Boolean isKeptInAuction) { @@ -507,8 +519,7 @@ private Result toResult(AnalyticsResult analyticsResult) { analyticsResult.getStatus(), toObjectNode(analyticsResult.getValues()), AppliedToImpl.builder() - .bidders(Collections.singletonList(analyticsResult.getBidder())) - .impIds(Collections.singletonList(analyticsResult.getImpId())) + .impIds(Collections.singletonList("adunitcodevalue")) .build()); } 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 d4b0a4f8711..f8326efb81f 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 @@ -58,6 +58,7 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAnalyticsConfig; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.StreamUtil; import org.prebid.server.version.PrebidVersionProvider; import org.prebid.server.vertx.httpclient.HttpClient; import org.prebid.server.vertx.httpclient.model.HttpClientResponse; @@ -65,8 +66,6 @@ import java.time.Clock; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -229,8 +228,7 @@ private Map extractAnalyticsResultFromAnalyticsTag(Au .flatMap(Collection::stream) .filter(activity -> "greenbids-filter".equals(activity.name())) .map(Activity::results) - .map(List::getFirst) - .map(Result::values) + .flatMap(Collection::stream) .map(this::parseAnalyticsResult) .flatMap(map -> map.entrySet().stream()) .collect(Collectors.toMap( @@ -239,21 +237,20 @@ private Map extractAnalyticsResultFromAnalyticsTag(Au (existing, replacement) -> existing)); } - private Map parseAnalyticsResult(ObjectNode analyticsResult) { + private Map parseAnalyticsResult(Result result) { + return Optional.ofNullable(result) + .map(Result::values) + .stream() + .flatMap(valuesNode -> StreamUtil.asStream(valuesNode.fields())) + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> parseOrtb2ImpExtResult(entry.getValue()), + (existing, replacement) -> existing)); + } + + private Ortb2ImpExtResult parseOrtb2ImpExtResult(JsonNode node) { try { - final Map parsedAnalyticsResult = new HashMap<>(); - final Iterator> fields = analyticsResult.fields(); - - while (fields.hasNext()) { - final Map.Entry field = fields.next(); - final String impId = field.getKey(); - final JsonNode explorationResultNode = field.getValue(); - final Ortb2ImpExtResult ortb2ImpExtResult = jacksonMapper.mapper() - .treeToValue(explorationResultNode, Ortb2ImpExtResult.class); - parsedAnalyticsResult.put(impId, ortb2ImpExtResult); - } - - return parsedAnalyticsResult; + return jacksonMapper.mapper().treeToValue(node, Ortb2ImpExtResult.class); } catch (JsonProcessingException e) { throw new PreBidException("Analytics result parsing error", e); } 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 82cae87406e..4683dc5370e 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 @@ -47,8 +47,10 @@ import org.prebid.server.hooks.execution.model.Stage; import org.prebid.server.hooks.execution.model.StageExecutionOutcome; import org.prebid.server.hooks.execution.v1.analytics.ActivityImpl; +import org.prebid.server.hooks.execution.v1.analytics.AppliedToImpl; import org.prebid.server.hooks.execution.v1.analytics.ResultImpl; import org.prebid.server.hooks.execution.v1.analytics.TagsImpl; +import org.prebid.server.hooks.v1.analytics.AppliedTo; import org.prebid.server.json.EncodeException; import org.prebid.server.json.JacksonMapper; import org.prebid.server.model.HttpRequestContext; @@ -733,11 +735,16 @@ private static HookExecutionContext givenHookExecutionContextWithAnalyticsTag() "adunitcodevalue", createAnalyticsResultNode())); + final AppliedTo appliedTo = AppliedToImpl.builder() + .impIds(Collections.singletonList("adunitcodevalue")) + .bidders(Collections.singletonList("seat1")) + .build(); + final ActivityImpl activity = ActivityImpl.of( "greenbids-filter", "success", Collections.singletonList( - ResultImpl.of("success", analyticsResultNode, null))); + ResultImpl.of("success", analyticsResultNode, appliedTo))); final TagsImpl tags = TagsImpl.of(Collections.singletonList(activity));