Skip to content

Commit

Permalink
Add account level metrics control (#1462)
Browse files Browse the repository at this point in the history
  • Loading branch information
And1sS authored Feb 9, 2022
1 parent ad1b447 commit 6c62fb8
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 170 deletions.
11 changes: 11 additions & 0 deletions docs/application-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ There are two ways to configure application settings: database and file. This do
to `sfN.enforce` value.
- `privacy.gdpr.purpose-one-treatment-interpretation` - option that allows to skip the Purpose one enforcement workflow.
Values: ignore, no-access-allowed, access-allowed.
- `metrics.verbosity-level` - defines verbosity level of metrics for this account, overrides `metrics.accounts` application settings configuration.
- `analytics.auction-events.<channel>` - defines which channels are supported by analytics for this account
- `analytics.modules.<module-name>.*` - space for `module-name` analytics module specific configuration, may be of any shape
- `cookie-sync.default-limit` - if the "limit" isn't specified in the `/cookie_sync` request, this is what to use
Expand Down Expand Up @@ -102,6 +103,8 @@ Here's an example YAML file containing account-specific settings:
banner-creative-max-size: enforce
events:
enabled: true
metrics:
verbosity-level: basic
privacy:
ccpa:
enabled: true
Expand Down Expand Up @@ -261,6 +264,9 @@ example:
"enabled": true
}
},
"metrics": {
"verbosity-level": "basic"
},
"privacy": {
"ccpa": {
"enabled": true,
Expand Down Expand Up @@ -430,6 +436,8 @@ Let's assume following table schema for example:
`updated_by` int(11) DEFAULT NULL,
`updated_by_user` varchar(64) DEFAULT NULL,
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`verbosity_level` varchar(64) DEFAULT NULL,

PRIMARY KEY (`id`),
UNIQUE KEY `uuid` (`uuid`))
ENGINE=InnoDB DEFAULT CHARSET=utf8'
Expand All @@ -451,6 +459,9 @@ SELECT JSON_MERGE_PATCH(
'bid-validations', bid_validations,
'events', JSON_OBJECT('enabled', NOT NOT (events_enabled))
),
'metrics', JSON_OBJECT(
'verbosity-level', verbosity_level
),
'privacy', JSON_OBJECT(
'ccpa', JSON_OBJECT('enabled', NOT NOT (enforce_ccpa)),
'gdpr', tcf_config
Expand Down
26 changes: 11 additions & 15 deletions src/main/java/org/prebid/server/auction/ExchangeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ private Future<AuctionContext> runAuction(AuctionContext receivedContext) {

final List<SeatBid> storedAuctionResponses = new ArrayList<>();
final BidderAliases aliases = aliases(bidRequest);
final String publisherId = account.getId();
final BidRequestCacheInfo cacheInfo = bidRequestCacheInfo(bidRequest);
final Map<String, MultiBidConfig> bidderToMultiBid = bidderToMultiBids(bidRequest, debugWarnings);

Expand All @@ -252,7 +251,7 @@ private Future<AuctionContext> runAuction(AuctionContext receivedContext) {
receivedContext, storedResponseResult, aliases, bidderToMultiBid))

.map(auctionParticipation -> updateRequestMetric(
auctionParticipation, uidsCookie, aliases, publisherId, requestTypeMetric))
auctionParticipation, uidsCookie, aliases, account, requestTypeMetric))
.map(bidderRequests -> maybeLogBidderInteraction(receivedContext, bidderRequests))
.compose(auctionParticipations -> CompositeFuture.join(
auctionParticipations.stream()
Expand All @@ -270,10 +269,9 @@ private Future<AuctionContext> runAuction(AuctionContext receivedContext) {
auctionParticipations, storedAuctionResponses, bidRequest.getImp()))
.map(auctionParticipations -> dropZeroNonDealBids(auctionParticipations, debugWarnings))
.map(auctionParticipations -> validateAndAdjustBids(auctionParticipations, receivedContext, aliases))
.map(auctionParticipations -> updateMetricsFromResponses(auctionParticipations, publisherId, aliases))
.map(auctionParticipations -> updateMetricsFromResponses(auctionParticipations, account, aliases))

.map(receivedContext::with)

// produce response from bidder results
.compose(context -> bidResponseCreator.create(
context.getAuctionParticipations(),
Expand Down Expand Up @@ -1120,14 +1118,14 @@ private ObjectNode prepareBidderParameters(ExtRequestPrebid prebid, String bidde
private List<AuctionParticipation> updateRequestMetric(List<AuctionParticipation> auctionParticipations,
UidsCookie uidsCookie,
BidderAliases aliases,
String publisherId,
Account account,
MetricName requestTypeMetric) {
auctionParticipations = auctionParticipations.stream()
.filter(auctionParticipation -> !auctionParticipation.isRequestBlocked())
.collect(Collectors.toList());

metrics.updateRequestBidderCardinalityMetric(auctionParticipations.size());
metrics.updateAccountRequestMetrics(publisherId, requestTypeMetric);
metrics.updateAccountRequestMetrics(account, requestTypeMetric);

for (AuctionParticipation auctionParticipation : auctionParticipations) {
if (auctionParticipation.isRequestBlocked()) {
Expand Down Expand Up @@ -1521,7 +1519,7 @@ private List<AuctionParticipation> maybeLogBidderInteraction(AuctionContext cont
* {@link Bid#getPrice()} is not empty.
*/
private List<AuctionParticipation> updateMetricsFromResponses(List<AuctionParticipation> auctionParticipations,
String publisherId,
Account account,
BidderAliases aliases) {
final List<BidderResponse> bidderResponses = auctionParticipations.stream()
.filter(auctionParticipation -> !auctionParticipation.isRequestBlocked())
Expand All @@ -1531,19 +1529,19 @@ private List<AuctionParticipation> updateMetricsFromResponses(List<AuctionPartic
for (BidderResponse bidderResponse : bidderResponses) {
final String bidder = aliases.resolveBidder(bidderResponse.getBidder());

metrics.updateAdapterResponseTime(bidder, publisherId, bidderResponse.getResponseTime());
metrics.updateAdapterResponseTime(bidder, account, bidderResponse.getResponseTime());

final List<BidderBid> bidderBids = bidderResponse.getSeatBid().getBids();
if (CollectionUtils.isEmpty(bidderBids)) {
metrics.updateAdapterRequestNobidMetrics(bidder, publisherId);
metrics.updateAdapterRequestNobidMetrics(bidder, account);
} else {
metrics.updateAdapterRequestGotbidsMetrics(bidder, publisherId);
metrics.updateAdapterRequestGotbidsMetrics(bidder, account);

for (final BidderBid bidderBid : bidderBids) {
final Bid bid = bidderBid.getBid();

final long cpm = bid.getPrice().multiply(THOUSAND).longValue();
metrics.updateAdapterBidMetrics(bidder, publisherId, cpm, bid.getAdm() != null,
metrics.updateAdapterBidMetrics(bidder, account, cpm, bid.getAdm() != null,
bidderBid.getType().toString());
}
}
Expand Down Expand Up @@ -1796,8 +1794,6 @@ private AuctionContext updateHooksMetrics(AuctionContext context) {

// account might be null if request is rejected by the entrypoint hook
if (account != null) {
final String accountId = account.getId();

stageOutcomes.values().stream()
.flatMap(Collection::stream)
.map(StageExecutionOutcome::getGroups)
Expand All @@ -1808,7 +1804,7 @@ private AuctionContext updateHooksMetrics(AuctionContext context) {
outcome -> outcome.getHookId().getModuleCode(),
Collectors.summingLong(HookExecutionOutcome::getExecutionTime)))
.forEach((moduleCode, executionTime) ->
metrics.updateAccountModuleDurationMetric(accountId, moduleCode, executionTime));
metrics.updateAccountModuleDurationMetric(account, moduleCode, executionTime));
}

return context;
Expand Down Expand Up @@ -1837,7 +1833,7 @@ private void updateHookInvocationMetrics(Account account, Stage stage, HookExecu

// account might be null if request is rejected by the entrypoint hook
if (account != null) {
metrics.updateAccountHooksMetrics(account.getId(), moduleCode, status, action);
metrics.updateAccountHooksMetrics(account, moduleCode, status, action);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ private void handleResult(AsyncResult<AuctionContext> responseResult,
errorMessages = Collections.singletonList(message);

status = HttpResponseStatus.UNAUTHORIZED;

body = message;
final String accountId = ((UnauthorizedAccountException) exception).getAccountId();
metrics.updateAccountRequestRejectedMetrics(accountId);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.prebid.server.metric;

import org.prebid.server.metric.model.AccountMetricsVerbosityLevel;
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.AccountMetricsConfig;

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

public class AccountMetricsVerbosityResolver {

private final AccountMetricsVerbosityLevel defaultVerbosity;
private final Map<String, AccountMetricsVerbosityLevel> accountVerbosityLevels;

public AccountMetricsVerbosityResolver(AccountMetricsVerbosityLevel defaultVerbosity,
List<String> basicVerbosity,
List<String> detailedVerbosity) {

this.defaultVerbosity = Objects.requireNonNull(defaultVerbosity);

this.accountVerbosityLevels = new HashMap<>();
Objects.requireNonNull(basicVerbosity)
.forEach(accountId -> accountVerbosityLevels.put(accountId, AccountMetricsVerbosityLevel.basic));
Objects.requireNonNull(detailedVerbosity)
.forEach(accountId -> accountVerbosityLevels.put(accountId, AccountMetricsVerbosityLevel.detailed));
}

public AccountMetricsVerbosityLevel forAccount(Account account) {
final AccountMetricsConfig metricsConfig = account.getMetrics();
final AccountMetricsVerbosityLevel accountVerbosity = metricsConfig != null
? metricsConfig.getVerbosityLevel()
: null;
return accountVerbosity != null
? accountVerbosity
: accountVerbosityLevels.getOrDefault(account.getId(), defaultVerbosity);
}
}
Loading

0 comments on commit 6c62fb8

Please sign in to comment.