Skip to content

Commit 3c2bb27

Browse files
Add a warning for when targeting attributes are truncated (prebid#4188)
1 parent 19e3285 commit 3c2bb27

7 files changed

Lines changed: 224 additions & 179 deletions

File tree

src/main/java/org/prebid/server/auction/BidResponseCreator.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,15 @@ private Bid toBid(BidInfo bidInfo,
15661566
final String categoryDuration = bidInfo.getCategory();
15671567
targetingKeywords = keywordsCreator != null
15681568
? keywordsCreator.makeFor(
1569-
bid, seat, isWinningBid, cacheId, bidType.getName(), videoCacheId, categoryDuration, account)
1569+
bid,
1570+
seat,
1571+
isWinningBid,
1572+
cacheId,
1573+
bidType.getName(),
1574+
videoCacheId,
1575+
categoryDuration,
1576+
account,
1577+
bidWarnings)
15701578
: null;
15711579
} else {
15721580
targetingKeywords = null;

src/main/java/org/prebid/server/auction/TargetingKeywordsCreator.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import com.iab.openrtb.response.Bid;
44
import org.apache.commons.lang3.StringUtils;
5+
import org.prebid.server.bidder.model.BidderError;
56
import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity;
7+
import org.prebid.server.proto.openrtb.ext.response.ExtBidderError;
68
import org.prebid.server.settings.model.Account;
79

810
import java.math.BigDecimal;
@@ -12,7 +14,6 @@
1214
import java.util.List;
1315
import java.util.Map;
1416
import java.util.Set;
15-
import java.util.stream.Collectors;
1617

1718
/**
1819
* Used throughout Prebid to create targeting keys as keys which can be used in an ad server like DFP.
@@ -154,7 +155,8 @@ Map<String, String> makeFor(Bid bid,
154155
String format,
155156
String vastCacheId,
156157
String categoryDuration,
157-
Account account) {
158+
Account account,
159+
Map<String, List<ExtBidderError>> bidWarnings) {
158160

159161
final Map<String, String> keywords = makeFor(
160162
bidder,
@@ -170,13 +172,13 @@ Map<String, String> makeFor(Bid bid,
170172
account);
171173

172174
if (resolver == null) {
173-
return truncateKeys(keywords);
175+
return truncateKeys(keywords, bidWarnings);
174176
}
175177

176178
final Map<String, String> augmentedKeywords = new HashMap<>(keywords);
177179
augmentedKeywords.putAll(resolver.resolve(bid, bidder));
178180

179-
return truncateKeys(augmentedKeywords);
181+
return truncateKeys(augmentedKeywords, bidWarnings);
180182
}
181183

182184
/**
@@ -261,12 +263,33 @@ private static String sizeFrom(Integer width, Integer height) {
261263
: null;
262264
}
263265

264-
private Map<String, String> truncateKeys(Map<String, String> keyValues) {
265-
return truncateAttrChars > 0
266-
? keyValues.entrySet().stream()
267-
.collect(Collectors
268-
.toMap(keyValue -> truncateKey(keyValue.getKey()), Map.Entry::getValue, (key1, key2) -> key1))
269-
: keyValues;
266+
private Map<String, String> truncateKeys(Map<String, String> keyValues,
267+
Map<String, List<ExtBidderError>> bidWarnings) {
268+
269+
if (truncateAttrChars <= 0) {
270+
return keyValues;
271+
}
272+
273+
final Map<String, String> keys = new HashMap<>();
274+
final List<String> truncatedKeys = new ArrayList<>();
275+
for (Map.Entry<String, String> entry : keyValues.entrySet()) {
276+
final String key = entry.getKey();
277+
final String truncatedKey = truncateKey(key);
278+
keys.putIfAbsent(truncatedKey, entry.getValue());
279+
280+
if (truncatedKey.length() != key.length()) {
281+
truncatedKeys.add(key);
282+
}
283+
}
284+
285+
if (!truncatedKeys.isEmpty()) {
286+
final String errorMessage = "The following keys have been truncated: %s"
287+
.formatted(String.join(", ", truncatedKeys));
288+
bidWarnings.computeIfAbsent("targeting", ignored -> new ArrayList<>())
289+
.add(ExtBidderError.of(BidderError.Type.bad_input.getCode(), errorMessage));
290+
}
291+
292+
return keys;
270293
}
271294

272295
private String truncateKey(String key) {

src/test/groovy/org/prebid/server/functional/testcontainers/PbsConfig.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,9 @@ LIMIT 1
145145
"currency-converter.external-rates.refresh-period-ms" : "900000"]
146146
}
147147

148+
static Map<String,String> getTargetingConfig() {
149+
["settings.targeting.truncate-attr-chars": '255']
150+
}
151+
148152
private PbsConfig() {}
149153
}

src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class PrebidServerContainer extends GenericContainer<PrebidServerContainer> {
4242
<< PbsConfig.bidderAliasConfig
4343
<< PbsConfig.prebidCacheConfig
4444
<< PbsConfig.mySqlConfig
45+
<< PbsConfig.targetingConfig
4546
withConfig(commonConfig)
4647
withConfig(customConfig)
4748
}

src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ class CacheSpec extends BaseSpec {
2727
private static final String PBS_API_HEADER = 'x-pbc-api-key'
2828
private static final Integer MAX_DATACENTER_REGION_LENGTH = 4
2929
private static final Integer DEFAULT_UUID_LENGTH = 36
30-
private static final Integer TARGETING_PARAM_NAME_MAX_LENGTH = 20
3130

3231
private static final String XML_CREATIVE_SIZE_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_size.xml"
3332
private static final String JSON_CREATIVE_SIZE_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_size.json"
@@ -612,8 +611,8 @@ class CacheSpec extends BaseSpec {
612611
it.get("hb_cache_id_generic")
613612
it.get("hb_cache_path") == CACHE_PATH
614613
it.get("hb_cache_host") == CACHE_HOST
615-
it.get("hb_cache_path_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == CACHE_PATH
616-
it.get("hb_cache_host_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == CACHE_HOST
614+
it.get("hb_cache_path_generic") == CACHE_PATH
615+
it.get("hb_cache_host_generic") == CACHE_HOST
617616
}
618617

619618
and: "Debug should contain http call"
@@ -648,8 +647,8 @@ class CacheSpec extends BaseSpec {
648647
it.get("hb_cache_id_generic")
649648
it.get("hb_cache_path") == INTERNAL_CACHE_PATH
650649
it.get("hb_cache_host") == networkServiceContainer.hostAndPort.toString()
651-
it.get("hb_cache_path_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == INTERNAL_CACHE_PATH
652-
it.get("hb_cache_host_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == networkServiceContainer.hostAndPort.toString()
650+
it.get("hb_cache_path_generic") == INTERNAL_CACHE_PATH
651+
it.get("hb_cache_host_generic") == networkServiceContainer.hostAndPort.toString()
653652
}
654653

655654
and: "Debug should contain http call"

0 commit comments

Comments
 (0)