Skip to content

Commit 18074a2

Browse files
Merge pull request #140 from IABTechLab/vse-UID2-797-track-advertiser-token-expiry
Track advertiser token expiry
2 parents c02f438 + 5d12a50 commit 18074a2

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

src/main/java/com/uid2/operator/service/IUIDOperatorService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.vertx.core.AsyncResult;
66
import io.vertx.core.Handler;
77

8+
import java.time.Duration;
89
import java.time.Instant;
910
import java.util.List;
1011

@@ -27,4 +28,5 @@ public interface IUIDOperatorService {
2728

2829
Instant getLatestOptoutEntry(UserIdentity userIdentity, Instant asOf);
2930

31+
Duration getIdentityExpiryDuration();
3032
}

src/main/java/com/uid2/operator/service/UIDOperatorService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ public Instant getLatestOptoutEntry(UserIdentity userIdentity, Instant asOf) {
175175
return this.optOutStore.getLatestEntry(firstLevelHashIdentity);
176176
}
177177

178+
@Override
179+
public Duration getIdentityExpiryDuration() {
180+
return this.identityExpiresAfter;
181+
}
182+
178183
private UserIdentity getFirstLevelHashIdentity(UserIdentity userIdentity, Instant asOf) {
179184
return getFirstLevelHashIdentity(userIdentity.identityScope, userIdentity.identityType, userIdentity.id, asOf);
180185
}

src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public class UIDOperatorVerticle extends AbstractVerticle{
7171
private final Clock clock;
7272
private IUIDOperatorService idService;
7373
private final Map<String, DistributionSummary> _identityMapMetricSummaries = new HashMap<>();
74-
private final Map<String, DistributionSummary> _refreshDurationMetricSummaries = new HashMap<>();
74+
private final Map<Tuple.Tuple2<String, Boolean>, DistributionSummary> _refreshDurationMetricSummaries = new HashMap<>();
75+
private final Map<Tuple.Tuple3<String, Boolean, Boolean>, Counter> _advertisingTokenExpiryStatus = new HashMap<>();
7576
private final Map<Tuple.Tuple2<String, TokenGeneratePolicy>, Counter> _tokenGeneratePolicyCounters = new HashMap<>();
7677
private final Map<Tuple.Tuple2<String, IdentityMapPolicy>, Counter> _identityMapPolicyCounters = new HashMap<>();
7778
private final Map<String, Tuple.Tuple2<Counter, Counter>> _identityMapUnmappedIdentifiers = new HashMap<>();
@@ -372,7 +373,7 @@ private void handleTokenRefreshV1(RoutingContext rc) {
372373
}
373374
} else {
374375
ResponseUtil.Success(rc, toJsonV1(r.getTokens()));
375-
this.recordRefreshDurationStats(siteId, getApiContact(rc), r.getDurationSinceLastRefresh());
376+
this.recordRefreshDurationStats(siteId, getApiContact(rc), r.getDurationSinceLastRefresh(), rc.request().headers().contains("Origin"));
376377
}
377378

378379
TokenResponseStatsCollector.record(siteId, TokenResponseStatsCollector.Endpoint.RefreshV1, r);
@@ -402,7 +403,7 @@ private void handleTokenRefreshV2(RoutingContext rc) {
402403
}
403404
} else {
404405
ResponseUtil.SuccessV2(rc, toJsonV1(r.getTokens()));
405-
this.recordRefreshDurationStats(siteId, getApiContact(rc), r.getDurationSinceLastRefresh());
406+
this.recordRefreshDurationStats(siteId, getApiContact(rc), r.getDurationSinceLastRefresh(), rc.request().headers().contains("Origin"));
406407
}
407408
TokenResponseStatsCollector.record(siteId, TokenResponseStatsCollector.Endpoint.RefreshV2, r);
408409
} catch (Exception e) {
@@ -589,7 +590,7 @@ private void handleTokenRefresh(RoutingContext rc) {
589590

590591
Integer siteId = rc.get(Const.RoutingContextData.SiteId);
591592
if (r.isRefreshed()) {
592-
this.recordRefreshDurationStats(siteId, getApiContact(rc), r.getDurationSinceLastRefresh());
593+
this.recordRefreshDurationStats(siteId, getApiContact(rc), r.getDurationSinceLastRefresh(), rc.request().headers().contains("Origin"));
593594
}
594595
TokenResponseStatsCollector.record(siteId, TokenResponseStatsCollector.Endpoint.RefreshV0, r);
595596
} catch (Exception e) {
@@ -1254,16 +1255,29 @@ private RefreshResponse refreshIdentity(RoutingContext rc, String tokenStr) {
12541255
return this.idService.refreshIdentity(refreshToken);
12551256
}
12561257

1257-
private void recordRefreshDurationStats(Integer siteId, String apiContact, Duration durationSinceLastRefresh) {
1258-
DistributionSummary ds = _refreshDurationMetricSummaries.computeIfAbsent(apiContact, k ->
1258+
private void recordRefreshDurationStats(Integer siteId, String apiContact, Duration durationSinceLastRefresh, boolean hasOriginHeader) {
1259+
DistributionSummary ds = _refreshDurationMetricSummaries.computeIfAbsent(new Tuple.Tuple2<>(apiContact, hasOriginHeader), k ->
12591260
DistributionSummary
12601261
.builder("uid2.token_refresh_duration_seconds")
12611262
.description("duration between token refreshes")
12621263
.tag("site_id", String.valueOf(siteId))
12631264
.tag("api_contact", apiContact)
1265+
.tag("has_origin_header", hasOriginHeader ? "true" : "false")
12641266
.register(Metrics.globalRegistry)
12651267
);
12661268
ds.record(durationSinceLastRefresh.getSeconds());
1269+
1270+
boolean isExpired = durationSinceLastRefresh.compareTo(this.idService.getIdentityExpiryDuration()) > 0;
1271+
Counter c = _advertisingTokenExpiryStatus.computeIfAbsent(new Tuple.Tuple3<>(String.valueOf(siteId), hasOriginHeader, isExpired), k ->
1272+
Counter
1273+
.builder("uid2.advertising_token_expired_on_refresh")
1274+
.description("status of advertiser token expiry")
1275+
.tag("site_id", String.valueOf(siteId))
1276+
.tag("has_origin_header", hasOriginHeader ? "true" : "false")
1277+
.tag("is_expired", isExpired ? "true" : "false")
1278+
.register(Metrics.globalRegistry)
1279+
);
1280+
c.increment();
12671281
}
12681282

12691283
private InputUtil.InputVal[] createInputList(JsonArray a, boolean inputAsHash) {
@@ -1458,6 +1472,4 @@ public static enum UserConsentStatus {
14581472
INSUFFICIENT,
14591473
INVALID,
14601474
}
1461-
1462-
14631475
}

src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,38 @@ void captureDurationsBetweenRefresh(String apiVersion, Vertx vertx, VertxTestCon
11021102
.tag("api_contact", "test-contact")
11031103
.tag("site_id", String.valueOf(clientSiteId))
11041104
.summary().mean());
1105+
1106+
assertEquals(1, Metrics.globalRegistry
1107+
.get("uid2.advertising_token_expired_on_refresh")
1108+
.tag("site_id", String.valueOf(clientSiteId))
1109+
.tag("is_expired", "false")
1110+
.counter().count());
1111+
1112+
testContext.completeNow();
1113+
});
1114+
});
1115+
}
1116+
1117+
@ParameterizedTest
1118+
@ValueSource(strings = {"v1", "v2"})
1119+
void captureExpiredAdvertisingTokenStatus(String apiVersion, Vertx vertx, VertxTestContext testContext) {
1120+
final int clientSiteId = 201;
1121+
fakeAuth(clientSiteId, Role.GENERATOR);
1122+
final String emailAddress = "[email protected]";
1123+
generateRefreshToken(apiVersion, vertx, "email", emailAddress, clientSiteId, genRespJson -> {
1124+
JsonObject bodyJson = genRespJson.getJsonObject("body");
1125+
String refreshToken = bodyJson.getString("refresh_token");
1126+
when(clock.instant()).thenAnswer(i -> Instant.now().plusSeconds(identityExpiresAfter.toSeconds() + 1));
1127+
1128+
sendTokenRefresh(apiVersion, vertx, refreshToken, bodyJson.getString("refresh_response_key"), 200, refreshRespJson-> {
1129+
assertEquals("success", refreshRespJson.getString("status"));
1130+
1131+
assertEquals(1, Metrics.globalRegistry
1132+
.get("uid2.advertising_token_expired_on_refresh")
1133+
.tag("site_id", String.valueOf(clientSiteId))
1134+
.tag("is_expired", "true")
1135+
.counter().count());
1136+
11051137
testContext.completeNow();
11061138
});
11071139
});

0 commit comments

Comments
 (0)