diff --git a/src/main/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporter.java b/src/main/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporter.java index 93665840a21..9c3252d4116 100644 --- a/src/main/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporter.java +++ b/src/main/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporter.java @@ -16,6 +16,7 @@ import io.vertx.core.Vertx; import io.vertx.core.http.HttpHeaders; import io.vertx.core.http.HttpMethod; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.prebid.server.analytics.AnalyticsReporter; import org.prebid.server.analytics.model.AmpEvent; @@ -146,11 +147,7 @@ public Future processEvent(T event) { final String eventString = jacksonMapper.encodeToString(agmaEvent); buffer.put(eventString, eventString.length()); - final List toFlush = buffer.pollToFlush(); - if (!toFlush.isEmpty()) { - sendEvents(toFlush); - } - + sendEvents(buffer.pollToFlush()); return Future.succeededFuture(); } @@ -200,10 +197,15 @@ private static String getPublisherId(BidRequest bidRequest) { return null; } - return publisherId; + return StringUtils.isNotBlank(appSiteId) + ? String.format("%s_%s", StringUtils.defaultString(publisherId), appSiteId) + : publisherId; } private void sendEvents(List events) { + if (events.isEmpty()) { + return; + } final String payload = preparePayload(events); final Future responseFuture = compressToGzip ? httpClient.request(HttpMethod.POST, url, headers, gzip(payload), httpTimeoutMs) diff --git a/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java b/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java index 01153008824..d618c36fa36 100644 --- a/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java @@ -5,6 +5,7 @@ import lombok.NoArgsConstructor; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.prebid.server.analytics.AnalyticsReporter; import org.prebid.server.analytics.reporter.AnalyticsReporterDelegator; import org.prebid.server.analytics.reporter.agma.AgmaAnalyticsReporter; @@ -111,8 +112,9 @@ private static class AgmaAnalyticsConfigurationProperties { public AgmaAnalyticsProperties toComponentProperties() { final Map accountsByPublisherId = accounts.stream() .collect(Collectors.toMap( - AgmaAnalyticsAccountProperties::getPublisherId, - AgmaAnalyticsAccountProperties::getCode)); + this::buildPublisherSiteAppIdKey, + AgmaAnalyticsAccountProperties::getCode + )); return AgmaAnalyticsProperties.builder() .url(endpoint.getUrl()) @@ -125,6 +127,14 @@ public AgmaAnalyticsProperties toComponentProperties() { .build(); } + private String buildPublisherSiteAppIdKey(AgmaAnalyticsAccountProperties account) { + final String publisherId = account.getPublisherId(); + final String siteAppId = account.getSiteAppId(); + return StringUtils.isNotBlank(siteAppId) + ? String.format("%s_%s", publisherId, siteAppId) + : publisherId; + } + @Validated @NoArgsConstructor @Data diff --git a/src/test/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporterTest.java b/src/test/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporterTest.java index 2427942605e..3de67e31b93 100644 --- a/src/test/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporterTest.java +++ b/src/test/java/org/prebid/server/analytics/reporter/agma/AgmaAnalyticsReporterTest.java @@ -408,6 +408,124 @@ public void processEventShouldNotSendAnythingWhenAccountsDoesNotHaveConfiguredPu assertThat(result.succeeded()).isTrue(); } + @Test + public void processEventShouldSendWhenAccountsHasConfiguredAppsOrSites() { + // given + final AgmaAnalyticsProperties properties = AgmaAnalyticsProperties.builder() + .url("http://endpoint.com") + .gzip(false) + .bufferSize(100000) + .bufferTimeoutMs(10000L) + .maxEventsCount(0) + .httpTimeoutMs(1000L) + .accounts(Map.of("publisherId_bundleId", "accountCode")) + .build(); + + target = new AgmaAnalyticsReporter(properties, versionProvider, jacksonMapper, clock, httpClient, vertx); + + // given + final App givenApp = App.builder().bundle("bundleId") + .publisher(Publisher.builder().id("publisherId").build()).build(); + final Device givenDevice = Device.builder().build(); + final User givenUser = User.builder().build(); + + final AuctionEvent auctionEvent = AuctionEvent.builder() + .auctionContext(AuctionContext.builder() + .privacyContext(PrivacyContext.of( + null, TcfContext.builder().consent(PARSED_VALID_CONSENT).build())) + .timeoutContext(TimeoutContext.of(clock.millis(), null, 1)) + .bidRequest(BidRequest.builder() + .id("requestId") + .app(givenApp) + .app(givenApp) + .device(givenDevice) + .user(givenUser) + .build()) + .build()) + .build(); + + // when + final Future result = target.processEvent(auctionEvent); + + // then + final AgmaEvent expectedEvent = AgmaEvent.builder() + .eventType("auction") + .accountCode("accountCode") + .requestId("requestId") + .app(givenApp) + .device(givenDevice) + .user(givenUser) + .startTime(ZonedDateTime.parse("2024-09-03T15:00:00+05:00")) + .build(); + + final String expectedEventPayload = "[" + jacksonMapper.encodeToString(expectedEvent) + "]"; + + verify(httpClient).request( + eq(POST), + eq("http://endpoint.com"), + any(), + eq(expectedEventPayload), + eq(1000L)); + } + + @Test + public void processEventShouldSendWhenAccountsHasConfiguredAppsOrSitesOnly() { + // given + final AgmaAnalyticsProperties properties = AgmaAnalyticsProperties.builder() + .url("http://endpoint.com") + .gzip(false) + .bufferSize(100000) + .bufferTimeoutMs(10000L) + .maxEventsCount(0) + .httpTimeoutMs(1000L) + .accounts(Map.of("_mySite", "accountCode")) + .build(); + + target = new AgmaAnalyticsReporter(properties, versionProvider, jacksonMapper, clock, httpClient, vertx); + + // given + final Site givenSite = Site.builder().id("mySite").build(); + final Device givenDevice = Device.builder().build(); + final User givenUser = User.builder().build(); + + final AuctionEvent auctionEvent = AuctionEvent.builder() + .auctionContext(AuctionContext.builder() + .privacyContext(PrivacyContext.of( + null, TcfContext.builder().consent(PARSED_VALID_CONSENT).build())) + .timeoutContext(TimeoutContext.of(clock.millis(), null, 1)) + .bidRequest(BidRequest.builder() + .id("requestId") + .site(givenSite) + .device(givenDevice) + .user(givenUser) + .build()) + .build()) + .build(); + + // when + final Future result = target.processEvent(auctionEvent); + + // then + final AgmaEvent expectedEvent = AgmaEvent.builder() + .eventType("auction") + .accountCode("accountCode") + .requestId("requestId") + .site(givenSite) + .device(givenDevice) + .user(givenUser) + .startTime(ZonedDateTime.parse("2024-09-03T15:00:00+05:00")) + .build(); + + final String expectedEventPayload = "[" + jacksonMapper.encodeToString(expectedEvent) + "]"; + + verify(httpClient).request( + eq(POST), + eq("http://endpoint.com"), + any(), + eq(expectedEventPayload), + eq(1000L)); + } + @Test public void processEventShouldSendEncodingGzipHeaderAndCompressedPayload() { // given