Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/main/java/org/prebid/server/auction/BidsAdjuster.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ public List<AuctionParticipation> validateAndAdjustBids(List<AuctionParticipatio
AuctionContext auctionContext,
BidderAliases aliases) {

final BidRequest bidRequest = auctionContext.getBidRequest();
return auctionParticipations.stream()
.map(auctionParticipation -> validBidderResponse(auctionParticipation, auctionContext, aliases))
.map(auctionParticipation -> bidAdjustmentsProcessor.enrichWithAdjustedBids(
auctionParticipation,
auctionContext.getBidRequest(),
auctionContext.getBidAdjustments()))
bidRequest))

.map(auctionParticipation -> priceFloorEnforcer.enforce(
auctionContext.getBidRequest(),
bidRequest,
auctionParticipation,
auctionContext.getAccount(),
auctionContext.getBidRejectionTrackers().get(auctionParticipation.getBidder())))

.map(auctionParticipation -> dsaEnforcer.enforce(
auctionContext.getBidRequest(),
bidRequest,
auctionParticipation,
auctionContext.getBidRejectionTrackers().get(auctionParticipation.getBidder())))
.toList();
Expand Down
25 changes: 17 additions & 8 deletions src/main/java/org/prebid/server/auction/ExchangeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.AccountAuctionConfig;
import org.prebid.server.settings.model.AccountCacheConfig;
import org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;
import org.prebid.server.util.ListUtil;
import org.prebid.server.util.PbsUtil;
Expand Down Expand Up @@ -739,20 +740,34 @@ private AuctionParticipation createAuctionParticipation(
final String storedBidResponse = impBidderToStoredBidResponse.size() == 1
? impBidderToStoredBidResponse.get(imps.getFirst().getId()).get(bidder)
: null;

final BidRequest enrichedWithPriceFloors = priceFloorProcessor.enrichWithPriceFloors(
context.getBidRequest().toBuilder().imp(imps).build(),
context.getAccount(),
bidder,
context.getPrebidErrors(),
context.getDebugWarnings());

final BidRequest preparedBidRequest = prepareBidRequest(
bidderPrivacyResult,
imps,
enrichedWithPriceFloors,
bidderToMultiBid,
biddersToConfigs,
bidderToPrebidBidders,
bidderAliases,
context);

final Map<String, Price> originalPriceFloors = enrichedWithPriceFloors.getImp().stream()
.filter(imp -> BidderUtil.isValidPrice(imp.getBidfloor())
&& StringUtils.isNotBlank(imp.getBidfloorcur()))
.collect(Collectors.toMap(Imp::getId, imp -> Price.of(imp.getBidfloorcur(), imp.getBidfloor())));

final BidderRequest bidderRequest = BidderRequest.builder()
.bidder(bidder)
.ortbVersion(ortbVersion)
.storedResponse(storedBidResponse)
.bidRequest(preparedBidRequest)
.originalPriceFloors(originalPriceFloors)
.build();

return AuctionParticipation.builder()
Expand All @@ -768,20 +783,14 @@ private OrtbVersion bidderSupportedOrtbVersion(String bidder, BidderAliases alia
}

private BidRequest prepareBidRequest(BidderPrivacyResult bidderPrivacyResult,
List<Imp> imps,
BidRequest bidRequest,
Map<String, MultiBidConfig> bidderToMultiBid,
Map<String, ExtBidderConfigOrtb> biddersToConfigs,
Map<String, JsonNode> bidderToPrebidBidders,
BidderAliases bidderAliases,
AuctionContext context) {

final String bidder = bidderPrivacyResult.getRequestBidder();
final BidRequest bidRequest = priceFloorProcessor.enrichWithPriceFloors(
context.getBidRequest().toBuilder().imp(imps).build(),
context.getAccount(),
bidder,
context.getPrebidErrors(),
context.getDebugWarnings());
final boolean transmitTid = transmitTransactionId(bidder, context);
final List<String> firstPartyDataBidders = firstPartyDataBidders(bidRequest.getExt());
final boolean useFirstPartyData = firstPartyDataBidders == null || firstPartyDataBidders.stream()
Expand Down
12 changes: 0 additions & 12 deletions src/main/java/org/prebid/server/auction/model/AuctionContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.prebid.server.activity.infrastructure.ActivityInfrastructure;
import org.prebid.server.auction.gpp.model.GppContext;
import org.prebid.server.auction.model.debug.DebugContext;
import org.prebid.server.bidadjustments.model.BidAdjustments;
import org.prebid.server.cache.model.DebugHttpCall;
import org.prebid.server.cookie.UidsCookie;
import org.prebid.server.geolocation.model.GeoInfo;
Expand All @@ -18,7 +17,6 @@
import org.prebid.server.privacy.model.PrivacyContext;
import org.prebid.server.settings.model.Account;

import java.util.Collections;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -73,10 +71,6 @@ public class AuctionContext {

CachedDebugLog cachedDebugLog;

@JsonIgnore
@Builder.Default
BidAdjustments bidAdjustments = BidAdjustments.of(Collections.emptyMap());

public AuctionContext with(Account account) {
return this.toBuilder().account(account).build();
}
Expand Down Expand Up @@ -130,12 +124,6 @@ public AuctionContext with(GeoInfo geoInfo) {
.build();
}

public AuctionContext with(BidAdjustments bidAdjustments) {
return this.toBuilder()
.bidAdjustments(bidAdjustments)
.build();
}

public AuctionContext withRequestRejected() {
return this.toBuilder()
.requestRejected(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import lombok.Builder;
import lombok.Value;
import org.prebid.server.auction.versionconverter.OrtbVersion;
import org.prebid.server.bidder.model.Price;

import java.util.Map;

@Builder(toBuilder = true)
@Value
Expand All @@ -17,6 +20,8 @@ public class BidderRequest {

BidRequest bidRequest;

Map<String, Price> originalPriceFloors;

public BidderRequest with(BidRequest bidRequest) {
return toBuilder().bidRequest(bidRequest).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.prebid.server.auction.model.AuctionStoredResult;
import org.prebid.server.auction.privacy.contextfactory.AuctionPrivacyContextFactory;
import org.prebid.server.auction.versionconverter.BidRequestOrtbVersionConversionManager;
import org.prebid.server.bidadjustments.BidAdjustmentsRetriever;
import org.prebid.server.bidadjustments.BidAdjustmentsEnricher;
import org.prebid.server.cookie.CookieDeprecationService;
import org.prebid.server.exception.InvalidRequestException;
import org.prebid.server.json.JacksonMapper;
Expand Down Expand Up @@ -51,7 +51,7 @@ public class AuctionRequestFactory {
private final JacksonMapper mapper;
private final OrtbTypesResolver ortbTypesResolver;
private final GeoLocationServiceWrapper geoLocationServiceWrapper;
private final BidAdjustmentsRetriever bidAdjustmentsRetriever;
private final BidAdjustmentsEnricher bidAdjustmentsEnricher;

private static final String ENDPOINT = Endpoint.openrtb2_auction.value();

Expand All @@ -69,7 +69,7 @@ public AuctionRequestFactory(long maxRequestSize,
DebugResolver debugResolver,
JacksonMapper mapper,
GeoLocationServiceWrapper geoLocationServiceWrapper,
BidAdjustmentsRetriever bidAdjustmentsRetriever) {
BidAdjustmentsEnricher bidAdjustmentsEnricher) {

this.maxRequestSize = maxRequestSize;
this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory);
Expand All @@ -85,7 +85,7 @@ public AuctionRequestFactory(long maxRequestSize,
this.debugResolver = Objects.requireNonNull(debugResolver);
this.mapper = Objects.requireNonNull(mapper);
this.geoLocationServiceWrapper = Objects.requireNonNull(geoLocationServiceWrapper);
this.bidAdjustmentsRetriever = Objects.requireNonNull(bidAdjustmentsRetriever);
this.bidAdjustmentsEnricher = Objects.requireNonNull(bidAdjustmentsEnricher);
}

/**
Expand Down Expand Up @@ -146,7 +146,7 @@ public Future<AuctionContext> enrichAuctionContext(AuctionContext initialContext
.compose(auctionContext -> ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(auctionContext)
.map(auctionContext::with))

.map(auctionContext -> auctionContext.with(bidAdjustmentsRetriever.retrieve(auctionContext)))
.map(auctionContext -> auctionContext.with(bidAdjustmentsEnricher.enrichBidRequest(auctionContext)))

.compose(auctionContext -> ortb2RequestFactory.executeProcessedAuctionRequestHooks(auctionContext)
.map(auctionContext::with))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.prebid.server.auction.adjustment;
package org.prebid.server.bidadjustments;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -38,6 +38,7 @@ private static Optional<BigDecimal> resolveFromMediaTypes(
}

return Optional.ofNullable(mediaType)
.map(type -> type == ImpMediaType.video_instream ? ImpMediaType.video : type)
.map(adjustmentFactors::get)
.flatMap(factors -> factors.entrySet().stream()
.filter(entry -> StringUtils.equalsIgnoreCase(entry.getKey(), bidderCode))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.bidadjustments.model.BidAdjustmentType;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidAdjustments;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidAdjustmentsRule;
import org.prebid.server.bidadjustments.model.BidAdjustments;
import org.prebid.server.bidadjustments.model.BidAdjustmentsRule;
import org.prebid.server.proto.openrtb.ext.request.ImpMediaType;
import org.prebid.server.validation.ValidationException;

Expand All @@ -16,7 +16,7 @@
public class BidAdjustmentRulesValidator {

public static final Set<String> SUPPORTED_MEDIA_TYPES = Set.of(
BidAdjustmentsResolver.WILDCARD,
BidAdjustmentsRulesResolver.WILDCARD,
ImpMediaType.banner.toString(),
ImpMediaType.audio.toString(),
ImpMediaType.video_instream.toString(),
Expand All @@ -27,26 +27,26 @@ private BidAdjustmentRulesValidator() {

}

public static void validate(ExtRequestBidAdjustments bidAdjustments) throws ValidationException {
public static void validate(BidAdjustments bidAdjustments) throws ValidationException {
if (bidAdjustments == null) {
return;
}

final Map<String, Map<String, Map<String, List<ExtRequestBidAdjustmentsRule>>>> mediatypes =
bidAdjustments.getMediatype();
final Map<String, Map<String, Map<String, List<BidAdjustmentsRule>>>> mediatypes =
bidAdjustments.getRules();

if (MapUtils.isEmpty(mediatypes)) {
return;
}

for (String mediatype : mediatypes.keySet()) {
if (SUPPORTED_MEDIA_TYPES.contains(mediatype)) {
final Map<String, Map<String, List<ExtRequestBidAdjustmentsRule>>> bidders = mediatypes.get(mediatype);
final Map<String, Map<String, List<BidAdjustmentsRule>>> bidders = mediatypes.get(mediatype);
if (MapUtils.isEmpty(bidders)) {
throw new ValidationException("no bidders found in %s".formatted(mediatype));
}
for (String bidder : bidders.keySet()) {
final Map<String, List<ExtRequestBidAdjustmentsRule>> deals = bidders.get(bidder);
final Map<String, List<BidAdjustmentsRule>> deals = bidders.get(bidder);

if (MapUtils.isEmpty(deals)) {
throw new ValidationException("no deals found in %s.%s".formatted(mediatype, bidder));
Expand All @@ -61,14 +61,14 @@ public static void validate(ExtRequestBidAdjustments bidAdjustments) throws Vali
}
}

private static void validateRules(List<ExtRequestBidAdjustmentsRule> rules,
private static void validateRules(List<BidAdjustmentsRule> rules,
String path) throws ValidationException {

if (rules == null) {
throw new ValidationException("no bid adjustment rules found in %s".formatted(path));
}

for (ExtRequestBidAdjustmentsRule rule : rules) {
for (BidAdjustmentsRule rule : rules) {
final BidAdjustmentType type = rule.getAdjType();
final String currency = rule.getCurrency();
final BigDecimal value = rule.getValue();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.prebid.server.bidadjustments;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iab.openrtb.request.BidRequest;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.json.JsonMerger;
import org.prebid.server.log.ConditionalLogger;
import org.prebid.server.log.Logger;
import org.prebid.server.log.LoggerFactory;
import org.prebid.server.proto.openrtb.ext.request.ExtRequest;
import org.prebid.server.bidadjustments.model.BidAdjustments;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid;
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.AccountAuctionConfig;
import org.prebid.server.validation.ValidationException;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

public class BidAdjustmentsEnricher {

private static final Logger logger = LoggerFactory.getLogger(BidAdjustmentsEnricher.class);
private static final ConditionalLogger conditionalLogger = new ConditionalLogger(logger);

private final ObjectMapper mapper;
private final JacksonMapper jacksonMapper;
private final JsonMerger jsonMerger;
private final double samplingRate;

public BidAdjustmentsEnricher(JacksonMapper mapper, JsonMerger jsonMerger, double samplingRate) {
this.jacksonMapper = Objects.requireNonNull(mapper);
this.mapper = mapper.mapper();
this.jsonMerger = Objects.requireNonNull(jsonMerger);
this.samplingRate = samplingRate;
}

public BidRequest enrichBidRequest(AuctionContext auctionContext) {
final BidRequest bidRequest = auctionContext.getBidRequest();
final List<String> debugWarnings = auctionContext.getDebugWarnings();
final boolean debugEnabled = auctionContext.getDebugContext().isDebugEnabled();

final JsonNode requestNode = Optional.ofNullable(bidRequest.getExt())
.map(ExtRequest::getPrebid)
.map(ExtRequestPrebid::getBidadjustments)
.orElseGet(mapper::createObjectNode);

final JsonNode accountNode = Optional.ofNullable(auctionContext.getAccount())
.map(Account::getAuction)
.map(AccountAuctionConfig::getBidAdjustments)
.orElseGet(mapper::createObjectNode);

final JsonNode mergedNode = jsonMerger.merge(requestNode, accountNode);

final List<String> resolvedWarnings = debugEnabled ? debugWarnings : null;
final JsonNode resolvedBidAdjustments = convertAndValidate(mergedNode, resolvedWarnings, "request")
.or(() -> convertAndValidate(accountNode, resolvedWarnings, "account"))
.orElse(null);

return bidRequest.toBuilder()
.ext(updateExtRequestWithBidAdjustments(bidRequest, resolvedBidAdjustments))
.build();
}

private Optional<JsonNode> convertAndValidate(JsonNode bidAdjustmentsNode,
List<String> debugWarnings,
String errorLocation) {

if (bidAdjustmentsNode.isEmpty()) {
return Optional.empty();
}

try {
final BidAdjustments bidAdjustments = mapper.convertValue(bidAdjustmentsNode, BidAdjustments.class);

BidAdjustmentRulesValidator.validate(bidAdjustments);
return Optional.of(bidAdjustmentsNode);
} catch (IllegalArgumentException | ValidationException e) {
final String message = "bid adjustment from " + errorLocation + " was invalid: " + e.getMessage();
if (debugWarnings != null) {
debugWarnings.add(message);
}
conditionalLogger.error(message, samplingRate);
return Optional.empty();
}
}

private ExtRequest updateExtRequestWithBidAdjustments(BidRequest bidRequest, JsonNode bidAdjustments) {
final ExtRequest extRequest = bidRequest.getExt();
final ExtRequestPrebid updatedPrebid = Optional.ofNullable(extRequest)
.map(ExtRequest::getPrebid)
.map(ExtRequestPrebid::toBuilder)
.orElse(ExtRequestPrebid.builder())
.bidadjustments((ObjectNode) bidAdjustments)
.build();

final ExtRequest updatedExtRequest = ExtRequest.of(updatedPrebid);
return extRequest == null
? updatedExtRequest
: jacksonMapper.fillExtension(updatedExtRequest, extRequest.getProperties());
}
}
Loading
Loading