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
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import org.prebid.server.activity.ComponentType;
import org.prebid.server.activity.infrastructure.debug.ActivityInfrastructureDebug;
import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload;
import org.prebid.server.activity.infrastructure.privacy.PrivacyModuleQualifier;
import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInfrastructure;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class ActivityInfrastructure {

Expand Down Expand Up @@ -48,4 +50,8 @@ public void updateActivityMetrics(Activity activity, ComponentType componentType
public List<ExtTraceActivityInfrastructure> debugTrace() {
return debug.trace();
}

public Set<PrivacyModuleQualifier> skippedPrivacyModules() {
return debug.skippedPrivacyModules();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import org.prebid.server.activity.infrastructure.creator.ActivityControllerCreationContext;
import org.prebid.server.activity.infrastructure.creator.PrivacyModuleCreationContext;
import org.prebid.server.activity.infrastructure.creator.privacy.PrivacyModuleCreator;
import org.prebid.server.activity.infrastructure.privacy.AbstainPrivacyModule;
import org.prebid.server.activity.infrastructure.privacy.SkippedPrivacyModule;
import org.prebid.server.activity.infrastructure.privacy.PrivacyModule;
import org.prebid.server.activity.infrastructure.privacy.PrivacyModuleQualifier;
import org.prebid.server.activity.infrastructure.rule.AndRule;
Expand Down Expand Up @@ -84,7 +84,7 @@ private PrivacyModule createPrivacyModule(PrivacyModuleQualifier privacyModuleQu
ActivityControllerCreationContext creationContext) {

if (creationContext.getSkipPrivacyModules().contains(privacyModuleQualifier)) {
return new AbstainPrivacyModule(privacyModuleQualifier);
return new SkippedPrivacyModule(privacyModuleQualifier);
}

return privacyModulesCreators.get(privacyModuleQualifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import org.prebid.server.activity.Activity;
import org.prebid.server.activity.ComponentType;
import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload;
import org.prebid.server.activity.infrastructure.privacy.SkippedPrivacyModule;
import org.prebid.server.activity.infrastructure.privacy.PrivacyModuleQualifier;
import org.prebid.server.activity.infrastructure.rule.AndRule;
import org.prebid.server.activity.infrastructure.rule.Rule;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.metric.Metrics;
Expand All @@ -15,14 +18,17 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

public class ActivityInfrastructureDebug {

private final String accountId;
private final TraceLevel traceLevel;
private final List<ExtTraceActivityInfrastructure> traceLog;
private final Set<PrivacyModuleQualifier> skippedPrivacyModules;
private final Metrics metrics;
private final JacksonMapper jacksonMapper;

Expand All @@ -34,6 +40,7 @@ public ActivityInfrastructureDebug(String accountId,
this.accountId = accountId;
this.traceLevel = traceLevel;
this.traceLog = new ArrayList<>();
this.skippedPrivacyModules = EnumSet.noneOf(PrivacyModuleQualifier.class);
this.metrics = Objects.requireNonNull(metrics);
this.jacksonMapper = Objects.requireNonNull(jacksonMapper);
}
Expand All @@ -56,6 +63,8 @@ public void emitActivityInvocationDefaultResult(boolean defaultResult) {
}

public void emitProcessedRule(Rule rule, Rule.Result result) {
collectSkippedPrivacyModules(rule);

if (atLeast(TraceLevel.basic)) {
traceLog.add(ExtTraceActivityRule.of(
"Processing rule.",
Expand All @@ -69,6 +78,17 @@ public void emitProcessedRule(Rule rule, Rule.Result result) {
}
}

private void collectSkippedPrivacyModules(Rule rule) {
if (rule instanceof SkippedPrivacyModule module) {
skippedPrivacyModules.add(module.skippedModule());
} else if (rule instanceof AndRule andRule) {
andRule.rules().stream()
.filter(SkippedPrivacyModule.class::isInstance)
.map(SkippedPrivacyModule.class::cast)
.forEach(module -> skippedPrivacyModules.add(module.skippedModule()));
}
}

public void emitActivityInvocationResult(Activity activity,
ActivityInvocationPayload activityInvocationPayload,
boolean result) {
Expand Down Expand Up @@ -102,6 +122,10 @@ public List<ExtTraceActivityInfrastructure> trace() {
return Collections.unmodifiableList(traceLog);
}

public Set<PrivacyModuleQualifier> skippedPrivacyModules() {
return Collections.unmodifiableSet(skippedPrivacyModules);
}

private boolean atLeast(TraceLevel minTraceLevel) {
return traceLevel != null && traceLevel.ordinal() >= minTraceLevel.ordinal();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

import java.util.Objects;

public class AbstainPrivacyModule implements PrivacyModule, Loggable {
public class SkippedPrivacyModule implements PrivacyModule, Loggable {

private final PrivacyModuleQualifier privacyModuleQualifier;

public AbstainPrivacyModule(PrivacyModuleQualifier privacyModuleQualifier) {
public SkippedPrivacyModule(PrivacyModuleQualifier privacyModuleQualifier) {
this.privacyModuleQualifier = Objects.requireNonNull(privacyModuleQualifier);
}

Expand All @@ -27,4 +27,8 @@ public JsonNode asLogEntry(ObjectMapper mapper) {
.put("skipped", true)
.put("result", Result.ABSTAIN.name());
}

public PrivacyModuleQualifier skippedModule() {
return privacyModuleQualifier;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.prebid.server.activity.infrastructure.debug.Loggable;
import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -45,4 +46,8 @@ public JsonNode asLogEntry(ObjectMapper mapper) {

return andNode;
}

public List<Rule> rules() {
return Collections.unmodifiableList(rules);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -509,11 +509,7 @@ class ActivityTraceLogSpec extends PrivacyBaseSpec {
}

where:
code | defaultAction
IAB_US_GENERAL | false
IAB_US_GENERAL | true
IAB_US_CUSTOM_LOGIC | false
IAB_US_CUSTOM_LOGIC | true
code << [IAB_US_GENERAL, IAB_US_CUSTOM_LOGIC]
}

def "PBS auction should log consistently for each activity about skips modules in response"() {
Expand Down Expand Up @@ -675,6 +671,81 @@ class ActivityTraceLogSpec extends PrivacyBaseSpec {
assert genericBidderRequest.user.eids[0].source == bidRequest.user.eids[0].source
}

def "PBS auction shouldn't log info about module skip in response when ext.prebid.trace=basic and skipRate is max"() {
given: "Default bid request"
def accountId = PBSUtils.randomNumber as String
def bidRequest = getBidRequestWithPersonalData(accountId).tap {
ext.prebid.trace = BASIC
regs.gpp = SIMPLE_GPC_DISALLOW_LOGIC
regs.gppSid = [US_NAT_V1.intValue]
}

and: "Set up activities"
def condition = Condition.baseCondition.tap {
it.gppSid = [US_NAT_V1.intValue]
}
def activityRule = ActivityRule.getDefaultActivityRule(condition).tap {
it.privacyRegulation = [ALL]
}
def activity = Activity.getDefaultActivity([activityRule])
def activities = AllowActivities.getDefaultAllowActivities(TRANSMIT_EIDS, activity)

and: "Account gpp configuration"
def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true, skipRate: MAX_PERCENT_AB)

and: "Save account with allow activities setup"
def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig])
accountDao.save(account)

when: "PBS processes auction requests"
def bidResponse = activityPbsService.sendAuctionRequest(bidRequest)

then: "Generic bidder request should have data in EIDS fields"
def genericBidderRequest = bidder.getBidderRequest(bidRequest.id)
assert genericBidderRequest.user.eids[0].source == bidRequest.user.eids[0].source

and: "Bid response should not contain info about rule configuration in debug"
def infrastructure = bidResponse.ext.debug.trace.activityInfrastructure
assert !findProcessingRule(infrastructure, TRANSMIT_EIDS).ruleConfiguration
}

def "PBS auction shouldn't log info about module skip in response when ext.prebid.trace=null and skipRate is max"() {
given: "Default bid request"
def accountId = PBSUtils.randomNumber as String
def bidRequest = getBidRequestWithPersonalData(accountId).tap {
ext.prebid.trace = null
regs.gpp = SIMPLE_GPC_DISALLOW_LOGIC
regs.gppSid = [US_NAT_V1.intValue]
}

and: "Set up activities"
def condition = Condition.baseCondition.tap {
it.gppSid = [US_NAT_V1.intValue]
}
def activityRule = ActivityRule.getDefaultActivityRule(condition).tap {
it.privacyRegulation = [ALL]
}
def activity = Activity.getDefaultActivity([activityRule])
def activities = AllowActivities.getDefaultAllowActivities(TRANSMIT_EIDS, activity)

and: "Account gpp configuration"
def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true, skipRate: MAX_PERCENT_AB)

and: "Save account with allow activities setup"
def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig])
accountDao.save(account)

when: "PBS processes auction requests"
def bidResponse = activityPbsService.sendAuctionRequest(bidRequest)

then: "Generic bidder request should have data in EIDS fields"
def genericBidderRequest = bidder.getBidderRequest(bidRequest.id)
assert genericBidderRequest.user.eids[0].source == bidRequest.user.eids[0].source

and: "Bid response should not contain info about trace"
assert !bidResponse.ext.debug.trace
}

private static List<ActivityInfrastructure> getActivityByName(List<ActivityInfrastructure> activityInfrastructures,
ActivityType activity) {
def firstIndex = activityInfrastructures.findLastIndexOf { it -> it.activity == activity }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import org.prebid.server.activity.Activity;
import org.prebid.server.activity.ComponentType;
import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload;
import org.prebid.server.activity.infrastructure.privacy.PrivacyModuleQualifier;
import org.prebid.server.activity.infrastructure.privacy.SkippedPrivacyModule;
import org.prebid.server.activity.infrastructure.rule.AndRule;
import org.prebid.server.activity.infrastructure.rule.Rule;
import org.prebid.server.activity.infrastructure.rule.TestRule;
import org.prebid.server.metric.Metrics;
Expand All @@ -18,6 +21,8 @@
import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInvocationResult;
import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityRule;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
Expand Down Expand Up @@ -156,6 +161,69 @@ public void emitProcessedRuleShouldReturnExpectedResultIfTraceLevelIsVerbose() {
verifyNoMoreInteractions(metrics);
}

@Test
public void emitProcessedRuleShouldLogModuleWhenModuleIsSkipped() {
// given
final ActivityInfrastructureDebug debug = debug(TraceLevel.verbose);

// when
debug.emitProcessedRule(new SkippedPrivacyModule(PrivacyModuleQualifier.US_NAT), Rule.Result.ABSTAIN);

// then
assertThat(debug.skippedPrivacyModules()).containsExactly(PrivacyModuleQualifier.US_NAT);
assertThat(debug.trace()).containsExactly(ExtTraceActivityRule.of(
"Processing rule.",
mapper.createObjectNode()
.put("privacy_module", "iab.usgeneral")
.put("skipped", true)
.put("result", "ABSTAIN"),
Rule.Result.ABSTAIN));
verify(metrics).updateRequestsActivityProcessedRulesCount();
verify(metrics).updateAccountActivityProcessedRulesCount(eq("accountId"));
verifyNoMoreInteractions(metrics);
}

@Test
public void emitProcessedRuleShouldLogSkippedModuleWhenAndRuleHasAbstainModule() {
// given
final ActivityInfrastructureDebug debug = debug(TraceLevel.verbose);

// when
debug.emitProcessedRule(
new AndRule(List.of(new SkippedPrivacyModule(PrivacyModuleQualifier.US_NAT))),
Rule.Result.ABSTAIN);

// then
assertThat(debug.skippedPrivacyModules()).containsExactly(PrivacyModuleQualifier.US_NAT);
assertThat(debug.trace()).containsExactly(ExtTraceActivityRule.of(
"Processing rule.",
mapper.createObjectNode().set("and", mapper.createArrayNode().add(mapper.createObjectNode()
.put("privacy_module", "iab.usgeneral")
.put("skipped", true)
.put("result", "ABSTAIN"))),
Rule.Result.ABSTAIN));
verify(metrics).updateRequestsActivityProcessedRulesCount();
verify(metrics).updateAccountActivityProcessedRulesCount(eq("accountId"));
verifyNoMoreInteractions(metrics);
}

@Test
public void emitProcessedRuleShouldLogSkippedModuleWhenTraceLevelIsNull() {
// given
final ActivityInfrastructureDebug debug = debug(null);

// when
debug.emitProcessedRule(
new AndRule(List.of(new SkippedPrivacyModule(PrivacyModuleQualifier.US_NAT))),
Rule.Result.ABSTAIN);

// then
assertThat(debug.skippedPrivacyModules()).containsExactly(PrivacyModuleQualifier.US_NAT);
assertThat(debug.trace()).isEmpty();
verify(metrics).updateRequestsActivityProcessedRulesCount();
verifyNoMoreInteractions(metrics);
}

@Test
public void emitActivityInvocationResultShouldDoNothingIfTraceLevelIsNullAndActivityAllowed() {
// given
Expand Down
Loading