From 03bf49df1ab5b52544cf45d3a7f1935cd739b74d Mon Sep 17 00:00:00 2001 From: Rafael Bey <24432403+rafaelbey@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:42:19 -0400 Subject: [PATCH] Add more metrics / observability (#2893) * adds metrics * adds metrics * adds metrics --------- Co-authored-by: sameer saini --- .../grammar/api/grammarToJson/GrammarToJson.java | 14 ++++++++++++-- .../grammar/api/jsonToGrammar/JsonToGrammar.java | 14 ++++++++++++-- .../core/operational/logs/LoggingEventType.java | 1 + .../operational/prometheus/MetricsHandler.java | 2 +- .../legend/engine/testable/api/TestableApi.java | 11 ++++++++++- .../generation/api/TestDataGeneration.java | 11 ++++++++++- 6 files changed, 46 insertions(+), 7 deletions(-) diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/grammarToJson/GrammarToJson.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/grammarToJson/GrammarToJson.java index 0a658bc8dd5..fe50a13e2ce 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/grammarToJson/GrammarToJson.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/grammarToJson/GrammarToJson.java @@ -24,6 +24,8 @@ import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.classInstance.graph.RootGraphFetchTree; import org.finos.legend.engine.shared.core.api.grammar.GrammarAPI; +import org.finos.legend.engine.shared.core.operational.prometheus.MetricsHandler; +import org.finos.legend.engine.shared.core.operational.prometheus.Prometheus; import org.pac4j.core.profile.CommonProfile; import org.pac4j.core.profile.ProfileManager; import org.pac4j.jax.rs.annotations.Pac4JProfileManager; @@ -34,8 +36,10 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import java.util.Map; import static org.finos.legend.engine.shared.core.operational.http.InflateInterceptor.APPLICATION_ZLIB; @@ -49,14 +53,20 @@ public class GrammarToJson extends GrammarAPI @ApiOperation(value = "Generates Pure protocol JSON from Pure language text") @Consumes({MediaType.TEXT_PLAIN, APPLICATION_ZLIB}) @Produces(MediaType.APPLICATION_JSON) + @Prometheus(name = "GrammarToJson model", doc = "Grammar to Json duration summary") public Response model(String text, @DefaultValue("") @ApiParam("The source ID to be used by the parser") @QueryParam("sourceId") String sourceId, @DefaultValue("0") @ApiParam("The line number the parser will offset by") @QueryParam("lineOffset") int lineOffset, @DefaultValue("true") @QueryParam("returnSourceInformation") boolean returnSourceInformation, - @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm) + @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm, + @Context UriInfo uriInfo) { + long start = System.currentTimeMillis(); PureGrammarParserExtensions.logExtensionList(); - return grammarToJson(text, (a) -> PureGrammarParser.newInstance().parseModel(a, sourceId, lineOffset, 0, returnSourceInformation), pm, "Grammar to Json : Model"); + Response response = grammarToJson(text, (a) -> PureGrammarParser.newInstance().parseModel(a, sourceId, lineOffset, 0, returnSourceInformation), pm, "Grammar to Json : Model"); + long end = System.currentTimeMillis(); + MetricsHandler.observeRequest(uriInfo != null ? uriInfo.getPath() : null, start, end); + return response; } @POST diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/jsonToGrammar/JsonToGrammar.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/jsonToGrammar/JsonToGrammar.java index f7c3aa04a97..83a5e5c629b 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/jsonToGrammar/JsonToGrammar.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar-http-api/src/main/java/org/finos/legend/engine/language/pure/grammar/api/jsonToGrammar/JsonToGrammar.java @@ -27,6 +27,8 @@ import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.classInstance.graph.RootGraphFetchTree; import org.finos.legend.engine.shared.core.api.grammar.GrammarAPI; import org.finos.legend.engine.shared.core.api.grammar.RenderStyle; +import org.finos.legend.engine.shared.core.operational.prometheus.MetricsHandler; +import org.finos.legend.engine.shared.core.operational.prometheus.Prometheus; import org.pac4j.core.profile.CommonProfile; import org.pac4j.core.profile.ProfileManager; import org.pac4j.jax.rs.annotations.Pac4JProfileManager; @@ -37,8 +39,10 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import java.util.Map; import static org.finos.legend.engine.shared.core.operational.http.InflateInterceptor.APPLICATION_ZLIB; @@ -53,12 +57,18 @@ public class JsonToGrammar extends GrammarAPI @ApiOperation(value = "Generates Pure language text from Pure protocol Pure Model Context Data") @Consumes({MediaType.APPLICATION_JSON, APPLICATION_ZLIB}) @Produces(MediaType.TEXT_PLAIN) + @Prometheus(name = "GrammarToJson model", doc = "Grammar to Json duration summary") public Response model(PureModelContextData pureModelContext, @QueryParam("renderStyle") @DefaultValue("PRETTY") RenderStyle renderStyle, - @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm) + @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm, + @Context UriInfo uriInfo) { + long start = System.currentTimeMillis(); PureGrammarComposerExtensionLoader.logExtensionList(); - return jsonToGrammar(pureModelContext, renderStyle, (value, renderStyle1) -> PureGrammarComposer.newInstance(PureGrammarComposerContext.Builder.newInstance().withRenderStyle(renderStyle1).build()).renderPureModelContextData(value), pm, "Json to Grammar : Model"); + Response response = jsonToGrammar(pureModelContext, renderStyle, (value, renderStyle1) -> PureGrammarComposer.newInstance(PureGrammarComposerContext.Builder.newInstance().withRenderStyle(renderStyle1).build()).renderPureModelContextData(value), pm, "Json to Grammar : Model"); + long end = System.currentTimeMillis(); + MetricsHandler.observeRequest(uriInfo != null ? uriInfo.getPath() : null, start, end); + return response; } @POST diff --git a/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/logs/LoggingEventType.java b/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/logs/LoggingEventType.java index fc92800afcc..2755daf92fe 100644 --- a/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/logs/LoggingEventType.java +++ b/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/logs/LoggingEventType.java @@ -389,4 +389,5 @@ public enum LoggingEventType implements ILoggingEventType EXPLAIN_INTERACTIVE_EXECUTION_ERROR, TEST_DATA_GENERATION_ERROR, + RUN_TEST_ERROR, } diff --git a/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/prometheus/MetricsHandler.java b/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/prometheus/MetricsHandler.java index 4a07587940f..077d2422ff9 100644 --- a/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/prometheus/MetricsHandler.java +++ b/legend-engine-core/legend-engine-core-shared/legend-engine-shared-core/src/main/java/org/finos/legend/engine/shared/core/operational/prometheus/MetricsHandler.java @@ -53,7 +53,7 @@ public class MetricsHandler private static final Histogram SUCCESSFUL_REQUEST_LATENCY = Histogram.build().name("legend_engine_successful_request_latency") .help("Measure legend engine's http request latency") - .buckets(.1, .2, .5, 1, 2, 5, 10, 30, 100, 300) + .buckets(.1, .2, .5, 1, 2, 5, 10, 30, 100, 300, 600, 1200) .labelNames("uri") .register(getMetricsRegistry()); diff --git a/legend-engine-core/legend-engine-core-testable/legend-engine-testable-http-api/src/main/java/org/finos/legend/engine/testable/api/TestableApi.java b/legend-engine-core/legend-engine-core-testable/legend-engine-testable-http-api/src/main/java/org/finos/legend/engine/testable/api/TestableApi.java index 684a6c440ec..b80de778237 100644 --- a/legend-engine-core/legend-engine-core-testable/legend-engine-testable-http-api/src/main/java/org/finos/legend/engine/testable/api/TestableApi.java +++ b/legend-engine-core/legend-engine-core-testable/legend-engine-testable-http-api/src/main/java/org/finos/legend/engine/testable/api/TestableApi.java @@ -32,6 +32,8 @@ import org.finos.legend.engine.shared.core.operational.http.InflateInterceptor; import org.finos.legend.engine.shared.core.operational.logs.LogInfo; import org.finos.legend.engine.shared.core.operational.logs.LoggingEventType; +import org.finos.legend.engine.shared.core.operational.prometheus.MetricsHandler; +import org.finos.legend.engine.shared.core.operational.prometheus.Prometheus; import org.finos.legend.engine.testable.TestableRunner; import org.finos.legend.engine.testable.model.RunTestsInput; @@ -39,8 +41,10 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import org.finos.legend.engine.testable.model.RunTestsResult; import org.pac4j.core.profile.CommonProfile; @@ -73,20 +77,25 @@ public TestableApi(ModelManager modelManager) @Path("runTests") @ApiOperation(value = "Run tests on testables") @Consumes({MediaType.APPLICATION_JSON, InflateInterceptor.APPLICATION_ZLIB}) - public Response doTests(RunTestsInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager profileManager) + @Prometheus(name = "run tests", doc = "Test run duration summary") + public Response doTests(RunTestsInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager profileManager, @Context UriInfo uriInfo) { MutableList profiles = ProfileManagerHelper.extractProfiles(profileManager); Identity identity = Identity.makeIdentity(profiles); + long start = System.currentTimeMillis(); try { LOGGER.info(new LogInfo(identity.getName(), LoggingEventType.TESTABLE_DO_TESTS_START, "").toString()); Pair modelAndData = this.modelManager.loadModelAndData(input.model, input.model instanceof PureModelContextPointer ? ((PureModelContextPointer) input.model).serializer.version : null, identity, null); RunTestsResult runTestsResult = testableRunner.doTests(input.testables, modelAndData.getTwo(), modelAndData.getOne()); LOGGER.info(new LogInfo(identity.getName(), LoggingEventType.TESTABLE_DO_TESTS_STOP, "").toString()); + long end = System.currentTimeMillis(); + MetricsHandler.observeRequest(uriInfo != null ? uriInfo.getPath() : null, start, end); return ManageConstantResult.manageResult(identity.getName(), runTestsResult, objectMapper); } catch (Exception e) { + MetricsHandler.observeError(LoggingEventType.RUN_TEST_ERROR, e, null); return ExceptionTool.exceptionManager(e, LoggingEventType.TESTABLE_DO_TESTS_ERROR, identity.getName()); } } diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-testDataGeneration-http-api/src/main/java/org/finos/legend/engine/testData/generation/api/TestDataGeneration.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-testDataGeneration-http-api/src/main/java/org/finos/legend/engine/testData/generation/api/TestDataGeneration.java index 04a1a61c6da..cb31e8a8d2c 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-testDataGeneration-http-api/src/main/java/org/finos/legend/engine/testData/generation/api/TestDataGeneration.java +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-testDataGeneration-http-api/src/main/java/org/finos/legend/engine/testData/generation/api/TestDataGeneration.java @@ -29,6 +29,8 @@ import org.finos.legend.engine.shared.core.kerberos.ProfileManagerHelper; import org.finos.legend.engine.shared.core.operational.errorManagement.ExceptionTool; import org.finos.legend.engine.shared.core.operational.logs.LoggingEventType; +import org.finos.legend.engine.shared.core.operational.prometheus.MetricsHandler; +import org.finos.legend.engine.shared.core.operational.prometheus.Prometheus; import org.finos.legend.engine.testData.generation.model.TestDataGenerationInput; import org.finos.legend.engine.testData.generation.model.TestDataGenerationResult; import org.finos.legend.engine.testData.generation.service.TestDataGenerationService; @@ -41,8 +43,10 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import static org.finos.legend.engine.shared.core.operational.http.InflateInterceptor.APPLICATION_ZLIB; @@ -63,18 +67,23 @@ public TestDataGeneration(ModelManager modelManager) @Path("DONOTUSE_generateTestData") @ApiOperation(value = "Studio WIP: will not be backward compatible until we remove the DONOTUSE flag") @Consumes({MediaType.APPLICATION_JSON, APPLICATION_ZLIB}) - public Response generateTestData(TestDataGenerationInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager profileManager) + @Prometheus(name = "generate test data") + public Response generateTestData(TestDataGenerationInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager profileManager, @Context UriInfo uriInfo) { MutableList profiles = ProfileManagerHelper.extractProfiles(profileManager); Identity identity = Identity.makeIdentity(profiles); PureModel pureModel = modelManager.loadModel(input.model, input.clientVersion == null ? PureClientVersions.production : input.clientVersion, identity, null); + long start = System.currentTimeMillis(); try { TestDataGenerationResult result = new TestDataGenerationResult(TestDataGenerationService.generateEmbeddedData(input.query, pureModel.getMapping(input.mapping), pureModel)); + long end = System.currentTimeMillis(); + MetricsHandler.observeRequest(uriInfo != null ? uriInfo.getPath() : null, start, end); return ManageConstantResult.manageResult(identity.getName(), result, objectMapper); } catch (Exception e) { + MetricsHandler.observeError(LoggingEventType.TEST_DATA_GENERATION_ERROR, e, null); return ExceptionTool.exceptionManager(e, LoggingEventType.TEST_DATA_GENERATION_ERROR, Response.Status.BAD_REQUEST, identity.getName()); } }