Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geo Lookup Updates #3057

Merged
merged 3 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
@@ -0,0 +1,86 @@
package org.prebid.server.auction;

import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.Geo;
import io.vertx.core.Future;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.execution.Timeout;
import org.prebid.server.geolocation.GeoLocationService;
import org.prebid.server.geolocation.model.GeoInfo;
import org.prebid.server.metric.Metrics;
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.AccountSettings;

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

public class GeoLocationServiceWrapper {

private static final Logger logger = LoggerFactory.getLogger(GeoLocationServiceWrapper.class);

private final GeoLocationService geoLocationService;
private final Metrics metrics;

public GeoLocationServiceWrapper(GeoLocationService geoLocationService, Metrics metrics) {
this.geoLocationService = geoLocationService;
this.metrics = Objects.requireNonNull(metrics);
}

//todo: account settings will work as expected if the default account resolving refactoring is done
public Future<GeoInfo> lookup(AuctionContext auctionContext) {
final Account account = auctionContext.getAccount();
final BidRequest bidRequest = auctionContext.getBidRequest();
final Timeout timeout = auctionContext.getTimeoutContext().getTimeout();

final Boolean isGeoLookupEnabled = Optional.ofNullable(account.getSettings())
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
.map(AccountSettings::getGeoLookup)
.map(BooleanUtils::isTrue)
.orElse(false);

final Device device = bidRequest.getDevice();

return isGeoLookupEnabled
? doLookup(getIpAddress(device), getCountry(device), timeout).otherwiseEmpty()
: Future.succeededFuture();
}

public Future<GeoInfo> doLookup(String ipAddress, String requestCountry, Timeout timeout) {
if (geoLocationService == null || StringUtils.isNotBlank(requestCountry) || ipAddress == null) {
return Future.failedFuture("Geolocation lookup is skipped");
}
return geoLocationService.lookup(ipAddress, timeout)
.onSuccess(geoInfo -> metrics.updateGeoLocationMetric(true))
.onFailure(this::logError);
}

private String getCountry(Device device) {
return Optional.ofNullable(device)
.map(Device::getGeo)
.map(Geo::getCountry)
.filter(StringUtils::isNotBlank)
.orElse(null);
}

private String getIpAddress(Device device) {
final Optional<Device> optionalDevice = Optional.ofNullable(device);
return optionalDevice.map(Device::getIp)
.filter(StringUtils::isNotBlank)
.or(() -> optionalDevice
.map(Device::getIpv6)
.filter(StringUtils::isNotBlank))
.orElse(null);
}

private void logError(Throwable error) {
final String message = "Geolocation lookup failed: " + error.getMessage();
logger.warn(message);
logger.debug(message, error);

metrics.updateGeoLocationMetric(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class AuctionContext {

ActivityInfrastructure activityInfrastructure;

@JsonIgnore
GeoInfo geoInfo;

HookExecutionContext hookExecutionContext;
Expand Down Expand Up @@ -123,6 +124,12 @@ public AuctionContext with(DebugContext debugContext) {
.build();
}

public AuctionContext with(GeoInfo geoInfo) {
return this.toBuilder()
.geoInfo(geoInfo)
.build();
}

public AuctionContext withRequestRejected() {
return this.toBuilder()
.requestRejected(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,16 @@ public Future<PrivacyContext> contextFrom(AuctionContext auctionContext) {
final Privacy strippedPrivacy = stripPrivacy(initialPrivacy, auctionContext);
final Device device = bidRequest.getDevice();

//todo: pass geo info here as well
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
return tcfDefinerService.resolveTcfContext(
strippedPrivacy,
resolveAlpha2CountryCode(device),
resolveIpAddress(device, strippedPrivacy),
accountGdprConfig(account),
requestType,
requestLogInfo(requestType, bidRequest, account.getId()),
auctionContext.getTimeoutContext().getTimeout())
auctionContext.getTimeoutContext().getTimeout(),
auctionContext.getGeoInfo())
.map(tcfContext -> logWarnings(auctionContext.getDebugWarnings(), tcfContext))
.map(tcfContext -> PrivacyContext.of(strippedPrivacy, tcfContext, tcfContext.getIpAddress()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public Future<PrivacyContext> contextFrom(AuctionContext auctionContext) {
accountGdprConfig(account),
requestType,
requestLogInfo(requestType, bidRequest, account.getId()),
auctionContext.getTimeoutContext().getTimeout())
auctionContext.getTimeoutContext().getTimeout(),
auctionContext.getGeoInfo())
.map(tcfContext -> logWarnings(auctionContext.getDebugWarnings(), tcfContext))
.map(tcfContext -> PrivacyContext.of(privacy, tcfContext, tcfContext.getIpAddress()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.auction.DebugResolver;
import org.prebid.server.auction.FpdResolver;
import org.prebid.server.auction.GeoLocationServiceWrapper;
import org.prebid.server.auction.ImplicitParametersExtractor;
import org.prebid.server.auction.OrtbTypesResolver;
import org.prebid.server.auction.PriceGranularity;
Expand Down Expand Up @@ -96,6 +97,7 @@ public class AmpRequestFactory {
private final AmpPrivacyContextFactory ampPrivacyContextFactory;
private final DebugResolver debugResolver;
private final JacksonMapper mapper;
private final GeoLocationServiceWrapper geoLocationServiceWrapper;

public AmpRequestFactory(Ortb2RequestFactory ortb2RequestFactory,
StoredRequestProcessor storedRequestProcessor,
Expand All @@ -107,7 +109,8 @@ public AmpRequestFactory(Ortb2RequestFactory ortb2RequestFactory,
FpdResolver fpdResolver,
AmpPrivacyContextFactory ampPrivacyContextFactory,
DebugResolver debugResolver,
JacksonMapper mapper) {
JacksonMapper mapper,
GeoLocationServiceWrapper geoLocationServiceWrapper) {

this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory);
this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor);
Expand All @@ -120,6 +123,7 @@ public AmpRequestFactory(Ortb2RequestFactory ortb2RequestFactory,
this.debugResolver = Objects.requireNonNull(debugResolver);
this.ampPrivacyContextFactory = Objects.requireNonNull(ampPrivacyContextFactory);
this.mapper = Objects.requireNonNull(mapper);
this.geoLocationServiceWrapper = Objects.requireNonNull(geoLocationServiceWrapper);
}

/**
Expand All @@ -142,6 +146,12 @@ public Future<AuctionContext> fromRequest(RoutingContext routingContext, long st

.map(auctionContext -> auctionContext.with(debugResolver.debugContextFrom(auctionContext)))

.compose(auctionContext -> geoLocationServiceWrapper.lookup(auctionContext)
.map(auctionContext::with))

.map(auctionContext -> auctionContext.with(
ortb2RequestFactory.enrichBidRequestWithGeolocationData(auctionContext)))
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved

.compose(auctionContext -> gppService.contextFrom(auctionContext)
.map(auctionContext::with))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.vertx.core.Future;
import io.vertx.ext.web.RoutingContext;
import org.prebid.server.auction.DebugResolver;
import org.prebid.server.auction.GeoLocationServiceWrapper;
import org.prebid.server.auction.ImplicitParametersExtractor;
import org.prebid.server.auction.InterstitialProcessor;
import org.prebid.server.auction.OrtbTypesResolver;
Expand Down Expand Up @@ -48,6 +49,7 @@ public class AuctionRequestFactory {
private final DebugResolver debugResolver;
private final JacksonMapper mapper;
private final OrtbTypesResolver ortbTypesResolver;
private final GeoLocationServiceWrapper geoLocationServiceWrapper;

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

Expand All @@ -63,7 +65,8 @@ public AuctionRequestFactory(long maxRequestSize,
OrtbTypesResolver ortbTypesResolver,
AuctionPrivacyContextFactory auctionPrivacyContextFactory,
DebugResolver debugResolver,
JacksonMapper mapper) {
JacksonMapper mapper,
GeoLocationServiceWrapper geoLocationServiceWrapper) {

this.maxRequestSize = maxRequestSize;
this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory);
Expand All @@ -78,6 +81,7 @@ public AuctionRequestFactory(long maxRequestSize,
this.auctionPrivacyContextFactory = Objects.requireNonNull(auctionPrivacyContextFactory);
this.debugResolver = Objects.requireNonNull(debugResolver);
this.mapper = Objects.requireNonNull(mapper);
this.geoLocationServiceWrapper = Objects.requireNonNull(geoLocationServiceWrapper);
}

/**
Expand Down Expand Up @@ -106,6 +110,12 @@ public Future<AuctionContext> fromRequest(RoutingContext routingContext, long st

.map(auctionContext -> auctionContext.with(debugResolver.debugContextFrom(auctionContext)))

.compose(auctionContext -> geoLocationServiceWrapper.lookup(auctionContext)
.map(auctionContext::with))

.map(auctionContext -> auctionContext.with(
ortb2RequestFactory.enrichBidRequestWithGeolocationData(auctionContext)))

.compose(auctionContext -> gppService.contextFrom(auctionContext)
.map(auctionContext::with))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,33 @@ public Future<BidRequest> validateRequest(BidRequest bidRequest,
: Future.succeededFuture(bidRequest);
}

public BidRequest enrichBidRequestWithGeolocationData(AuctionContext auctionContext) {
final BidRequest bidRequest = auctionContext.getBidRequest();
final Device device = bidRequest.getDevice();
final GeoInfo geoInfo = auctionContext.getGeoInfo();
final Geo geo = ObjectUtil.getIfNotNull(device, Device::getGeo);

final UpdateResult<String> resolvedCountry = resolveCountry(geo, geoInfo);
final UpdateResult<String> resolvedRegion = resolveRegion(geo, geoInfo);

if (resolvedCountry.isUpdated() || resolvedRegion.isUpdated()) {
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
final Geo updatedGeo = Optional.ofNullable(geo)
.map(Geo::toBuilder)
.orElseGet(Geo::builder)
.country(resolvedCountry.getValue())
.region(resolvedRegion.getValue())
.build();

final Device updatedDevice = ObjectUtil.getIfNotNullOrDefault(device, Device::toBuilder, Device::builder)
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
.geo(updatedGeo)
.build();

return bidRequest.toBuilder().device(updatedDevice).build();
}

return bidRequest;
}

public BidRequest enrichBidRequestWithAccountAndPrivacyData(AuctionContext auctionContext) {
final BidRequest bidRequest = auctionContext.getBidRequest();
final Account account = auctionContext.getAccount();
Expand Down Expand Up @@ -613,9 +640,10 @@ private Device enrichDevice(Device device, PrivacyContext privacyContext) {
final boolean shouldUpdateIpV6 = ipV6 != null && !Objects.equals(ipV6InRequest, ipV6);

final Geo geo = ObjectUtil.getIfNotNull(device, Device::getGeo);
final GeoInfo geoInfo = privacyContext.getTcfContext().getGeoInfo();

final UpdateResult<String> resolvedCountry = resolveCountry(geo, privacyContext);
final UpdateResult<String> resolvedRegion = resolveRegion(geo, privacyContext);
final UpdateResult<String> resolvedCountry = resolveCountry(geo, geoInfo);
final UpdateResult<String> resolvedRegion = resolveRegion(geo, geoInfo);

if (shouldUpdateIpV4 || shouldUpdateIpV6 || resolvedCountry.isUpdated() || resolvedRegion.isUpdated()) {
final Device.DeviceBuilder deviceBuilder = device != null ? device.toBuilder() : Device.builder();
Expand Down Expand Up @@ -645,10 +673,9 @@ private Device enrichDevice(Device device, PrivacyContext privacyContext) {
return null;
}

private UpdateResult<String> resolveCountry(Geo geo, PrivacyContext privacyContext) {
final String countryInRequest = geo != null ? geo.getCountry() : null;
private UpdateResult<String> resolveCountry(Geo originalGeo, GeoInfo geoInfo) {
final String countryInRequest = originalGeo != null ? originalGeo.getCountry() : null;

final GeoInfo geoInfo = privacyContext.getTcfContext().getGeoInfo();
final String alpha2CountryCode = geoInfo != null ? geoInfo.getCountry() : null;
final String alpha3CountryCode = countryCodeMapper.mapToAlpha3(alpha2CountryCode);

Expand All @@ -657,11 +684,10 @@ private UpdateResult<String> resolveCountry(Geo geo, PrivacyContext privacyConte
: UpdateResult.unaltered(countryInRequest);
}

private static UpdateResult<String> resolveRegion(Geo geo, PrivacyContext privacyContext) {
final String regionInRequest = geo != null ? geo.getRegion() : null;
private static UpdateResult<String> resolveRegion(Geo originalGeo, GeoInfo geoInfo) {
final String regionInRequest = originalGeo != null ? originalGeo.getRegion() : null;
final String upperCasedRegionInRequest = StringUtils.upperCase(regionInRequest);

final GeoInfo geoInfo = privacyContext.getTcfContext().getGeoInfo();
final String region = geoInfo != null ? geoInfo.getRegion() : null;
final String upperCasedRegion = StringUtils.upperCase(region);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.auction.DebugResolver;
import org.prebid.server.auction.GeoLocationServiceWrapper;
import org.prebid.server.auction.VideoStoredRequestProcessor;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.auction.model.CachedDebugLog;
Expand Down Expand Up @@ -60,6 +61,7 @@ public class VideoRequestFactory {
private final AuctionPrivacyContextFactory auctionPrivacyContextFactory;
private final DebugResolver debugResolver;
private final JacksonMapper mapper;
private final GeoLocationServiceWrapper geoLocationServiceWrapper;

public VideoRequestFactory(int maxRequestSize,
boolean enforceStoredRequest,
Expand All @@ -70,7 +72,8 @@ public VideoRequestFactory(int maxRequestSize,
Ortb2ImplicitParametersResolver paramsResolver,
AuctionPrivacyContextFactory auctionPrivacyContextFactory,
DebugResolver debugResolver,
JacksonMapper mapper) {
JacksonMapper mapper,
GeoLocationServiceWrapper geoLocationServiceWrapper) {

this.enforceStoredRequest = enforceStoredRequest;
this.maxRequestSize = maxRequestSize;
Expand All @@ -81,6 +84,7 @@ public VideoRequestFactory(int maxRequestSize,
this.auctionPrivacyContextFactory = Objects.requireNonNull(auctionPrivacyContextFactory);
this.debugResolver = Objects.requireNonNull(debugResolver);
this.mapper = Objects.requireNonNull(mapper);
this.geoLocationServiceWrapper = Objects.requireNonNull(geoLocationServiceWrapper);

this.escapeLogCacheRegexPattern = StringUtils.isNotBlank(escapeLogCacheRegex)
? Pattern.compile(escapeLogCacheRegex)
Expand Down Expand Up @@ -123,6 +127,12 @@ public Future<WithPodErrors<AuctionContext>> fromRequest(RoutingContext routingC

.map(auctionContext -> auctionContext.with(debugResolver.debugContextFrom(auctionContext)))

.compose(auctionContext -> geoLocationServiceWrapper.lookup(auctionContext)
.map(auctionContext::with))

.map(auctionContext -> auctionContext.with(
ortb2RequestFactory.enrichBidRequestWithGeolocationData(auctionContext)))

.compose(auctionContext -> ortb2RequestFactory.activityInfrastructureFrom(auctionContext)
.map(auctionContext::with))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ private Future<DeviceInfo> lookupDeviceInfo(Device device) {
: Future.failedFuture("Device info is disabled by configuration");
}

//todo: to be removed
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
private Future<GeoInfo> lookupGeoInfo(Device device, Timeout timeout) {
return geoLocationService != null
? geoLocationService.lookup(ObjectUtils.defaultIfNull(device.getIp(), device.getIpv6()), timeout)
Expand Down
Loading
Loading