Skip to content

Commit

Permalink
Xuy UI d2 2578 add site name to metrics (#351)
Browse files Browse the repository at this point in the history
* Add site name to metrics, add default handler constructor and mark as deprecated
  • Loading branch information
clarkxuyang authored Dec 2, 2024
1 parent 3a7056c commit d915248
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 14 deletions.
31 changes: 27 additions & 4 deletions src/main/java/com/uid2/shared/vertx/RequestCapturingHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.uid2.shared.auth.IAuthorizable;
import com.uid2.shared.jmx.AdminApi;
import com.uid2.shared.middleware.AuthMiddleware;
import com.uid2.shared.model.Site;
import com.uid2.shared.store.ISiteStore;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Metrics;
import io.vertx.core.Handler;
Expand Down Expand Up @@ -32,11 +34,22 @@ public class RequestCapturingHandler implements Handler<RoutingContext> {
private Queue<String> _capturedRequests = null;
private final Map<String, Counter> _apiMetricCounters = new HashMap<>();
private final Map<String, Counter> _clientAppVersionCounters = new HashMap<>();
private ISiteStore siteStore;

private static String formatRFC1123DateTime(long time) {
return DateTimeFormatter.RFC_1123_DATE_TIME.format(Instant.ofEpochMilli(time).atZone(ZONE_GMT));
}

@Deprecated
public RequestCapturingHandler()
{
}

public RequestCapturingHandler(ISiteStore siteStore)
{
this.siteStore = siteStore;
}

@Override
public void handle(RoutingContext context) {
if (!AdminApi.instance.getCaptureRequests() && !AdminApi.instance.getPublishApiMetrics()) {
Expand Down Expand Up @@ -105,7 +118,17 @@ private void capture(RoutingContext context, long timestamp, String remoteClient
}

final Integer siteId = getSiteId(context);
incrementMetricCounter(apiContact, siteId, host, status, method, path);

String siteName = "unknown";
if (siteId != null && siteStore != null) {
Site site = siteStore.getSite(siteId);
if (site != null)
{
siteName = site.getName();
}
}

incrementMetricCounter(apiContact, siteId, siteName, host, status, method, path);

if (request.headers().contains(Const.Http.AppVersionHeader)) {
incrementAppVersionCounter(apiContact, request.headers().get(Const.Http.AppVersionHeader));
Expand Down Expand Up @@ -196,14 +219,14 @@ private static Integer getSiteId(RoutingContext context) {
return null;
}

private void incrementMetricCounter(String apiContact, Integer siteId, String host, int status, HttpMethod method, String path) {
private void incrementMetricCounter(String apiContact, Integer siteId, String siteName, String host, int status, HttpMethod method, String path) {
assert apiContact != null;
String key = apiContact + "|" + siteId + "|" + host + "|" + status + "|" + method.name() + "|" + path;
String key = apiContact + "|" + siteId + "|" + siteName + "|" + host + "|" + status + "|" + method.name() + "|" + path;
if (!_apiMetricCounters.containsKey(key)) {
Counter counter = Counter
.builder("uid2.http_requests")
.description("counter for how many http requests are processed per each api contact and status code")
.tags("api_contact", apiContact, "site_id", String.valueOf(siteId), "host", host, "status", String.valueOf(status), "method", method.name(), "path", path)
.tags("api_contact", apiContact, "site_id", String.valueOf(siteId), "site_name", siteName, "host", host, "status", String.valueOf(status), "method", method.name(), "path", path)
.register(Metrics.globalRegistry);
_apiMetricCounters.put(key, counter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.uid2.shared.auth.ClientKey;
import com.uid2.shared.auth.OperatorKey;
import com.uid2.shared.middleware.AuthMiddleware;
import com.uid2.shared.model.Site;
import com.uid2.shared.store.ISiteStore;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.vertx.core.Handler;
Expand All @@ -14,35 +16,50 @@
import io.vertx.ext.web.client.WebClient;
import io.vertx.junit5.VertxExtension;
import io.vertx.junit5.VertxTestContext;
import org.assertj.core.condition.AnyOf;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.time.Instant;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.when;

@ExtendWith(VertxExtension.class)
public class RequestCapturingHandlerTest {
private static final int Port = 8080;
private static final Handler<RoutingContext> dummyResponseHandler = routingContext -> {
routingContext.response().setStatusCode(200).end();
};

private ISiteStore siteStore;

@BeforeEach
public void before() {
Metrics.globalRegistry.forEachMeter(Metrics.globalRegistry::remove);
Metrics.globalRegistry.add(new SimpleMeterRegistry());

Site site100 = new Site(100, "test-100", true);
Site site200 = new Site(200, "test-200", true);
siteStore = Mockito.mock(ISiteStore.class);
when(siteStore.getSite(100)).thenReturn(site100);
when(siteStore.getSite(200)).thenReturn(site200);
}

@Test
public void captureSimplePath(Vertx vertx, VertxTestContext testContext) {
Router router = Router.router(vertx);
router.route().handler(new RequestCapturingHandler());
router.route().handler(new RequestCapturingHandler(siteStore));
router.get("/v1/token/generate").handler(dummyResponseHandler);

vertx.createHttpServer().requestHandler(router).listen(Port, testContext.succeeding(id -> {
Expand Down Expand Up @@ -112,7 +129,7 @@ public void captureStaticPath(Vertx vertx, VertxTestContext testContext) {
@Test
public void captureUnknownPath(Vertx vertx, VertxTestContext testContext) {
Router router = Router.router(vertx);
router.route().handler(new RequestCapturingHandler());
router.route().handler(new RequestCapturingHandler(siteStore));

vertx.createHttpServer().requestHandler(router).listen(Port, testContext.succeeding(id -> {
WebClient client = WebClient.create(vertx);
Expand All @@ -132,9 +149,9 @@ public void captureUnknownPath(Vertx vertx, VertxTestContext testContext) {

@ParameterizedTest
@MethodSource("siteIdRoutingContextData")
public void getSiteIdFromRoutingContextData(String key, Object value, String siteId, Vertx vertx, VertxTestContext testContext) {
public void getSiteIdFromRoutingContextData(String key, Object value, String siteId, String siteName, Vertx vertx, VertxTestContext testContext) {
Router router = Router.router(vertx);
router.route().handler(new RequestCapturingHandler());
router.route().handler(new RequestCapturingHandler(siteStore));
router.get("/test").handler(ctx -> {
if (key != null) {
ctx.put(key, value);
Expand All @@ -149,6 +166,7 @@ public void getSiteIdFromRoutingContextData(String key, Object value, String sit
double actual = Metrics.globalRegistry
.get("uid2.http_requests")
.tag("site_id", siteId)
.tag("site_name", siteName)
.counter()
.count();
Assertions.assertEquals(1, actual);
Expand All @@ -158,13 +176,13 @@ public void getSiteIdFromRoutingContextData(String key, Object value, String sit
}

private static Stream<Arguments> siteIdRoutingContextData() {
// Arguments are: routing context data key, routing context data value, site ID tag.
// Arguments are: routing context data key, routing context data value, site ID tag, site Name
return Stream.of(
Arguments.of(Const.RoutingContextData.SiteId, 100, "100"),
Arguments.of(AuthMiddleware.API_CLIENT_PROP, new ClientKey("keyHash", "keySalt", "secret", "", Instant.MIN, Set.of(), 200, "test-key-id-1"), "200"),
Arguments.of(AuthMiddleware.API_CLIENT_PROP, new OperatorKey("test-keyHash", "test-keySalt", "name", "contact", "protocol", 0, false, "test-key-id-2"), "null"),
Arguments.of(AuthMiddleware.API_CLIENT_PROP, new OperatorKey("test-keyHash", "test-keySalt", "name", "contact", "protocol", 0, false, 300, "test-key-id-3"), "300"),
Arguments.of(null, null, "null")
Arguments.of(Const.RoutingContextData.SiteId, 100, "100", "test-100"),
Arguments.of(AuthMiddleware.API_CLIENT_PROP, new ClientKey("keyHash", "keySalt", "secret", "", Instant.MIN, Set.of(), 200, "test-key-id-1"), "200", "test-200"),
Arguments.of(AuthMiddleware.API_CLIENT_PROP, new OperatorKey("test-keyHash", "test-keySalt", "name", "contact", "protocol", 0, false, "test-key-id-2"), "null", "unknown"),
Arguments.of(AuthMiddleware.API_CLIENT_PROP, new OperatorKey("test-keyHash", "test-keySalt", "name", "contact", "protocol", 0, false, 300, "test-key-id-3"), "300", "unknown"),
Arguments.of(null, null, "null", "unknown")
);
}
}

0 comments on commit d915248

Please sign in to comment.