diff --git a/docs/endpoints/admin.md b/docs/endpoints/admin.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 6d7f52b3bb2..74a176bddf8 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -64,6 +64,7 @@ import org.prebid.server.hooks.v1.bidder.BidderResponsePayload; import org.prebid.server.json.JacksonMapper; import org.prebid.server.log.CriteriaLogManager; +import org.prebid.server.log.HttpInteractionLogger; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.model.CaseInsensitiveMultiMap; @@ -157,6 +158,7 @@ public class ExchangeService { private final ApplicationEventService applicationEventService; private final BidResponsePostProcessor bidResponsePostProcessor; private final HookStageExecutor hookStageExecutor; + private final HttpInteractionLogger httpInteractionLogger; private final Metrics metrics; private final Clock clock; private final JacksonMapper mapper; @@ -175,6 +177,7 @@ public ExchangeService(long expectedCacheTime, BidResponsePostProcessor bidResponsePostProcessor, HookStageExecutor hookStageExecutor, ApplicationEventService applicationEventService, + HttpInteractionLogger httpInteractionLogger, Metrics metrics, Clock clock, JacksonMapper mapper, @@ -196,6 +199,7 @@ public ExchangeService(long expectedCacheTime, this.bidResponsePostProcessor = Objects.requireNonNull(bidResponsePostProcessor); this.hookStageExecutor = Objects.requireNonNull(hookStageExecutor); this.applicationEventService = applicationEventService; + this.httpInteractionLogger = Objects.requireNonNull(httpInteractionLogger); this.metrics = Objects.requireNonNull(metrics); this.clock = Objects.requireNonNull(clock); this.mapper = Objects.requireNonNull(mapper); @@ -243,6 +247,7 @@ private Future runAuction(AuctionContext context) { context, storedResponseResult, aliases, bidderToMultiBid)) .map(bidderRequests -> updateRequestMetric( bidderRequests, uidsCookie, aliases, publisherId, context.getRequestTypeMetric())) + .map(bidderRequests -> maybeLogBidderInteraction(context, bidderRequests)) .compose(bidderRequests -> CompositeFuture.join( bidderRequests.stream() .map(bidderRequest -> invokeHooksAndRequestBids( @@ -1391,6 +1396,11 @@ private Timeout auctionTimeout(Timeout timeout, boolean shouldCacheBids) { return shouldCacheBids ? timeout.minus(expectedCacheTime) : timeout; } + private List maybeLogBidderInteraction(AuctionContext context, List bidderRequests) { + bidderRequests.forEach(bidderRequest -> httpInteractionLogger.maybeLogBidderRequest(context, bidderRequest)); + return bidderRequests; + } + /** * Updates 'request_time', 'responseTime', 'timeout_request', 'error_requests', 'no_bid_requests', * 'prices' metrics for each {@link BidderResponse}. diff --git a/src/main/java/org/prebid/server/handler/HttpInteractionLogHandler.java b/src/main/java/org/prebid/server/handler/HttpInteractionLogHandler.java index 0ceca420cd2..84e92b76141 100644 --- a/src/main/java/org/prebid/server/handler/HttpInteractionLogHandler.java +++ b/src/main/java/org/prebid/server/handler/HttpInteractionLogHandler.java @@ -18,6 +18,7 @@ public class HttpInteractionLogHandler implements Handler { private static final String ENDPOINT_PARAMETER = "endpoint"; private static final String STATUS_CODE_PARAMETER = "statusCode"; private static final String ACCOUNT_PARAMETER = "account"; + private static final String BIDDER_PARAMETER = "bidder"; private static final String LIMIT_PARAMETER = "limit"; private final int maxLimit; @@ -39,6 +40,7 @@ public void handle(RoutingContext routingContext) { readEndpoint(parameters), readStatusCode(parameters), readAccount(parameters), + readBidder(parameters), readLimit(parameters))); HttpUtil.executeSafely(routingContext, endpoint, @@ -78,6 +80,10 @@ private String readAccount(MultiMap parameters) { return parameters.get(ACCOUNT_PARAMETER); } + private String readBidder(MultiMap parameters) { + return parameters.get(BIDDER_PARAMETER); + } + private int readLimit(MultiMap parameters) { final Integer limit = getIntParameter(LIMIT_PARAMETER, parameters); diff --git a/src/main/java/org/prebid/server/log/HttpInteractionLogger.java b/src/main/java/org/prebid/server/log/HttpInteractionLogger.java index 85373797e61..585b5a45268 100644 --- a/src/main/java/org/prebid/server/log/HttpInteractionLogger.java +++ b/src/main/java/org/prebid/server/log/HttpInteractionLogger.java @@ -1,18 +1,27 @@ package org.prebid.server.log; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.RoutingContext; import lombok.Value; +import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.auction.model.BidderRequest; import org.prebid.server.json.JacksonMapper; import org.prebid.server.log.model.HttpLogSpec; +import org.prebid.server.metric.MetricName; import org.prebid.server.settings.model.Account; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; public class HttpInteractionLogger { @@ -72,9 +81,21 @@ public void maybeLogOpenrtb2Amp(AuctionContext auctionContext, } } - public boolean interactionSatisfiesSpec(HttpLogSpec.Endpoint requestEndpoint, - int requestStatusCode, - AuctionContext auctionContext) { + public void maybeLogBidderRequest(AuctionContext context, BidderRequest bidderRequest) { + final String bidder = bidderRequest.getBidder(); + if (interactionSatisfiesSpec(context, bidder)) { + final BidRequest bidRequest = bidderRequest.getBidRequest(); + final BidRequest updatedBidRequest = bidRequestWithBidderName(bidder, bidRequest); + final String jsonBidRequest = mapper.encode(updatedBidRequest); + logger.info("Request body to {0}: \"{1}\"", bidder, jsonBidRequest); + + incLoggedInteractions(); + } + } + + private boolean interactionSatisfiesSpec(HttpLogSpec.Endpoint requestEndpoint, + int requestStatusCode, + AuctionContext auctionContext) { final SpecWithCounter specWithCounter = this.specWithCounter.get(); if (specWithCounter == null) { @@ -94,6 +115,39 @@ public boolean interactionSatisfiesSpec(HttpLogSpec.Endpoint requestEndpoint, && (account == null || account.equals(requestAccountId)); } + private boolean interactionSatisfiesSpec(AuctionContext auctionContext, + String requestBidder) { + final SpecWithCounter specWithCounter = this.specWithCounter.get(); + if (specWithCounter == null) { + return false; + } + + final HttpLogSpec.Endpoint requestEndpoint = parseHttpLogEndpoint(auctionContext.getRequestTypeMetric()); + final Account requestAccount = auctionContext != null ? auctionContext.getAccount() : null; + final String requestAccountId = requestAccount != null ? requestAccount.getId() : null; + + final HttpLogSpec spec = specWithCounter.getSpec(); + final HttpLogSpec.Endpoint endpoint = spec.getEndpoint(); + final String account = spec.getAccount(); + final String bidder = spec.getBidder(); + + return (endpoint == null || endpoint == requestEndpoint) + && (account == null || account.equals(requestAccountId) + && (bidder != null && bidder.equals(requestBidder))); + } + + private HttpLogSpec.Endpoint parseHttpLogEndpoint(MetricName requestTypeMetric) { + if (requestTypeMetric != null) { + if (requestTypeMetric == MetricName.amp) { + return HttpLogSpec.Endpoint.amp; + } + if (requestTypeMetric == MetricName.openrtb2app || requestTypeMetric == MetricName.openrtb2web) { + return HttpLogSpec.Endpoint.auction; + } + } + return null; + } + private void incLoggedInteractions() { final SpecWithCounter specWithCounter = this.specWithCounter.get(); if (specWithCounter != null @@ -102,6 +156,35 @@ private void incLoggedInteractions() { } } + private BidRequest bidRequestWithBidderName(String bidder, BidRequest bidRequest) { + final List imps = bidRequest.getImp(); + if (CollectionUtils.isEmpty(imps)) { + return bidRequest; + } + + final List updatedImps = imps.stream() + .map(imp -> makeImpExtBidderName(bidder, imp)) + .collect(Collectors.toList()); + + return bidRequest.toBuilder().imp(updatedImps).build(); + } + + private Imp makeImpExtBidderName(String bidder, Imp imp) { + final ObjectNode originalImpExt = imp.getExt(); + if (originalImpExt == null) { + return imp; + } + + final ObjectNode impExt = originalImpExt.deepCopy(); + final Imp updatedImp = imp.toBuilder().ext(impExt).build(); + + final JsonNode impExtBidder = impExt.remove("bidder"); + if (impExtBidder != null) { + impExt.set(bidder, impExtBidder); + } + return updatedImp; + } + @Value(staticConstructor = "of") private static class SpecWithCounter { diff --git a/src/main/java/org/prebid/server/log/model/HttpLogSpec.java b/src/main/java/org/prebid/server/log/model/HttpLogSpec.java index 5ced697512c..75ba4fcfbc6 100644 --- a/src/main/java/org/prebid/server/log/model/HttpLogSpec.java +++ b/src/main/java/org/prebid/server/log/model/HttpLogSpec.java @@ -11,6 +11,8 @@ public class HttpLogSpec { String account; + String bidder; + int limit; public enum Endpoint { diff --git a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java index 58880dda38c..88d3924dd26 100644 --- a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java @@ -552,6 +552,7 @@ ExchangeService exchangeService( BidResponsePostProcessor bidResponsePostProcessor, HookStageExecutor hookStageExecutor, @Autowired(required = false) ApplicationEventService applicationEventService, + HttpInteractionLogger httpInteractionLogger, Metrics metrics, Clock clock, JacksonMapper mapper, @@ -571,6 +572,7 @@ ExchangeService exchangeService( bidResponsePostProcessor, hookStageExecutor, applicationEventService, + httpInteractionLogger, metrics, clock, mapper, diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 23cb407703b..138105d1dc2 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -78,6 +78,7 @@ import org.prebid.server.hooks.v1.analytics.ResultImpl; import org.prebid.server.hooks.v1.analytics.TagsImpl; import org.prebid.server.log.CriteriaLogManager; +import org.prebid.server.log.HttpInteractionLogger; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.model.CaseInsensitiveMultiMap; @@ -214,6 +215,8 @@ public class ExchangeServiceTest extends VertxTest { @Mock private ApplicationEventService applicationEventService; @Mock + private HttpInteractionLogger httpInteractionLogger; + @Mock private Metrics metrics; @Mock private UidsCookie uidsCookie; @@ -300,6 +303,7 @@ public void setUp() { bidResponsePostProcessor, hookStageExecutor, applicationEventService, + httpInteractionLogger, metrics, clock, jacksonMapper, @@ -323,6 +327,7 @@ public void creationShouldFailOnNegativeExpectedCacheTime() { bidResponsePostProcessor, hookStageExecutor, applicationEventService, + httpInteractionLogger, metrics, clock, jacksonMapper, @@ -589,6 +594,7 @@ public void shouldExtractRequestsWithoutFilteredDealsOnlyBidders() { bidResponsePostProcessor, hookStageExecutor, applicationEventService, + httpInteractionLogger, metrics, clock, jacksonMapper, @@ -2368,6 +2374,7 @@ public void shouldPassReducedGlobalTimeoutToConnectorAndOriginalToBidResponseCre bidResponsePostProcessor, hookStageExecutor, applicationEventService, + httpInteractionLogger, metrics, clock, jacksonMapper, diff --git a/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java b/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java index eda6e4407ce..0720b9e0b2e 100644 --- a/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java @@ -52,13 +52,14 @@ public void shouldSetSpecWhenAllParametersPresent() { .add("endpoint", "auction") .add("statusCode", "400") .add("account", "123") + .add("bidder", "ix") .add("limit", "2")); // when handler.handle(routingContext); // then - verify(httpInteractionLogger).setSpec(HttpLogSpec.of(HttpLogSpec.Endpoint.auction, 400, "123", 2)); + verify(httpInteractionLogger).setSpec(HttpLogSpec.of(HttpLogSpec.Endpoint.auction, 400, "123", "ix", 2)); } @Test @@ -71,7 +72,7 @@ public void shouldSetSpecWhenOptionalParametersAbsent() { handler.handle(routingContext); // then - verify(httpInteractionLogger).setSpec(eq(HttpLogSpec.of(null, null, null, 2))); + verify(httpInteractionLogger).setSpec(eq(HttpLogSpec.of(null, null, null, null, 2))); } @Test