From d9152481fbd703f0105fafc6da7d65492aaf6b33 Mon Sep 17 00:00:00 2001 From: Xu Yang <58192524+clarkxuyang@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:32:25 -0800 Subject: [PATCH] Xuy UI d2 2578 add site name to metrics (#351) * Add site name to metrics, add default handler constructor and mark as deprecated --- .../shared/vertx/RequestCapturingHandler.java | 31 +++++++++++++-- .../vertx/RequestCapturingHandlerTest.java | 38 ++++++++++++++----- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/uid2/shared/vertx/RequestCapturingHandler.java b/src/main/java/com/uid2/shared/vertx/RequestCapturingHandler.java index 6be82bc1..d837a8bb 100644 --- a/src/main/java/com/uid2/shared/vertx/RequestCapturingHandler.java +++ b/src/main/java/com/uid2/shared/vertx/RequestCapturingHandler.java @@ -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; @@ -32,11 +34,22 @@ public class RequestCapturingHandler implements Handler { private Queue _capturedRequests = null; private final Map _apiMetricCounters = new HashMap<>(); private final Map _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()) { @@ -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)); @@ -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); } diff --git a/src/test/java/com/uid2/shared/vertx/RequestCapturingHandlerTest.java b/src/test/java/com/uid2/shared/vertx/RequestCapturingHandlerTest.java index e274a319..b3f6b089 100644 --- a/src/test/java/com/uid2/shared/vertx/RequestCapturingHandlerTest.java +++ b/src/test/java/com/uid2/shared/vertx/RequestCapturingHandlerTest.java @@ -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; @@ -14,6 +16,7 @@ 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; @@ -21,11 +24,17 @@ 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; @@ -33,16 +42,24 @@ public class RequestCapturingHandlerTest { 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 -> { @@ -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); @@ -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); @@ -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); @@ -158,13 +176,13 @@ public void getSiteIdFromRoutingContextData(String key, Object value, String sit } private static Stream 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") ); } }