From a128ab5a0845258cad64647900abbb40f21dc737 Mon Sep 17 00:00:00 2001 From: Rafael Bey <24432403+rafaelbey@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:33:07 -0400 Subject: [PATCH] adds promethues metric tracking for functionActivator validate & publishToSandbox (#2911) Co-authored-by: sameer saini --- .../operational/logs/LoggingEventType.java | 3 +++ .../api/FunctionActivatorAPI.java | 25 ++++++++++++++++--- .../snowflakeApp/api/TestValidation.java | 4 +-- 3 files changed, 26 insertions(+), 6 deletions(-) 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 2755daf92fe..26504ba0e44 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 @@ -390,4 +390,7 @@ public enum LoggingEventType implements ILoggingEventType TEST_DATA_GENERATION_ERROR, RUN_TEST_ERROR, + + FUNCTION_ACTIVATOR_VALIDATE_ERROR, + FUNCTION_ACTIVATOR_PUBLISHTOSANDBOX_ERROR } diff --git a/legend-engine-xts-functionActivator/legend-engine-xt-functionActivator-http-api/src/main/java/org/finos/legend/engine/functionActivator/api/FunctionActivatorAPI.java b/legend-engine-xts-functionActivator/legend-engine-xt-functionActivator-http-api/src/main/java/org/finos/legend/engine/functionActivator/api/FunctionActivatorAPI.java index 570af4c8710..5e974bf0fe2 100644 --- a/legend-engine-xts-functionActivator/legend-engine-xt-functionActivator-http-api/src/main/java/org/finos/legend/engine/functionActivator/api/FunctionActivatorAPI.java +++ b/legend-engine-xts-functionActivator/legend-engine-xt-functionActivator-http-api/src/main/java/org/finos/legend/engine/functionActivator/api/FunctionActivatorAPI.java @@ -24,6 +24,7 @@ import org.eclipse.collections.api.list.MutableList; import org.finos.legend.engine.functionActivator.api.input.FunctionActivatorInput; import org.finos.legend.engine.functionActivator.api.output.FunctionActivatorInfo; +import org.finos.legend.engine.functionActivator.service.FunctionActivatorError; import org.finos.legend.engine.protocol.functionActivator.deployment.FunctionActivatorDeploymentConfiguration; import org.finos.legend.engine.functionActivator.service.FunctionActivatorLoader; import org.finos.legend.engine.functionActivator.service.FunctionActivatorService; @@ -41,6 +42,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.pure.generated.Root_meta_external_function_activator_FunctionActivator; import org.finos.legend.pure.generated.Root_meta_pure_extension_Extension; import org.pac4j.core.profile.CommonProfile; @@ -48,8 +51,10 @@ import org.pac4j.jax.rs.annotations.Pac4JProfileManager; import javax.ws.rs.*; +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.List; @@ -99,21 +104,27 @@ public Response list(@ApiParam(hidden = true) @Pac4JProfileManager ProfileManage @ApiOperation(value = "Validate that the functions can be properly activated by the activator.") @Consumes({MediaType.APPLICATION_JSON, APPLICATION_ZLIB}) @Produces(MediaType.APPLICATION_JSON) - public Response validate(FunctionActivatorInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm) + @Prometheus(name = "FunctionActivator validate", doc = "Function Activator validate duration histogram") + public Response validate(FunctionActivatorInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm, @Context UriInfo uriInfo) { MutableList profiles = ProfileManagerHelper.extractProfiles(pm); Identity identity = Identity.makeIdentity(profiles); try { + long start = System.currentTimeMillis(); String clientVersion = input.clientVersion == null ? PureClientVersions.production : input.clientVersion; PureModel pureModel = modelManager.loadModel(input.model, clientVersion, identity, null); Root_meta_external_function_activator_FunctionActivator activator = (Root_meta_external_function_activator_FunctionActivator) pureModel.getPackageableElement(input.functionActivator); FunctionActivatorService service = getActivatorService(activator, pureModel); - return Response.ok(objectMapper.writeValueAsString(service.validate(Identity.makeIdentity(profiles), pureModel, activator, input.model, routerExtensions))).type(MediaType.APPLICATION_JSON_TYPE).build(); + MutableList validate = service.validate(Identity.makeIdentity(profiles), pureModel, activator, input.model, routerExtensions); + long end = System.currentTimeMillis(); + MetricsHandler.observeRequest(uriInfo != null ? uriInfo.getPath() : null, start, end); + return Response.ok(objectMapper.writeValueAsString(validate)).type(MediaType.APPLICATION_JSON_TYPE).build(); } catch (Exception ex) { ex.printStackTrace(); + MetricsHandler.observeError(LoggingEventType.FUNCTION_ACTIVATOR_VALIDATE_ERROR, ex, null); return ExceptionTool.exceptionManager(ex, LoggingEventType.CATCH_ALL, identity.getName()); } } @@ -123,21 +134,27 @@ public Response validate(FunctionActivatorInput input, @ApiParam(hidden = true) @ApiOperation(value = "Public the activator to a sandbox environment. Production deployment will occur using the SDLC pipeline.") @Consumes({MediaType.APPLICATION_JSON, APPLICATION_ZLIB}) @Produces(MediaType.APPLICATION_JSON) - public Response publishToSandbox(FunctionActivatorInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm) + @Prometheus(name = "FunctionActivator publishToSandbox", doc = "Function Activator publishToSandbox duration histogram") + public Response publishToSandbox(FunctionActivatorInput input, @ApiParam(hidden = true) @Pac4JProfileManager ProfileManager pm, @Context UriInfo uriInfo) { MutableList profiles = ProfileManagerHelper.extractProfiles(pm); Identity identity = Identity.makeIdentity(profiles); try { + long start = System.currentTimeMillis(); String clientVersion = input.clientVersion == null ? PureClientVersions.production : input.clientVersion; PureModel pureModel = modelManager.loadModel(input.model, clientVersion, identity, null); Root_meta_external_function_activator_FunctionActivator activator = (Root_meta_external_function_activator_FunctionActivator) pureModel.getPackageableElement(input.functionActivator); FunctionActivatorService service = getActivatorService(activator,pureModel); - return Response.ok(objectMapper.writeValueAsString(service.publishToSandbox(Identity.makeIdentity(profiles), pureModel, activator, input.model, service.selectConfig(this.runtimeDeploymentConfig), routerExtensions))).type(MediaType.APPLICATION_JSON_TYPE).build(); + DeploymentResult deploymentResult = service.publishToSandbox(Identity.makeIdentity(profiles), pureModel, activator, input.model, service.selectConfig(this.runtimeDeploymentConfig), routerExtensions); + long end = System.currentTimeMillis(); + MetricsHandler.observeRequest(uriInfo != null ? uriInfo.getPath() : null, start, end); + return Response.ok(objectMapper.writeValueAsString(deploymentResult)).type(MediaType.APPLICATION_JSON_TYPE).build(); } catch (Exception ex) { ex.printStackTrace(); + MetricsHandler.observeError(LoggingEventType.FUNCTION_ACTIVATOR_PUBLISHTOSANDBOX_ERROR, ex, null); return ExceptionTool.exceptionManager(ex, LoggingEventType.CATCH_ALL, identity.getName()); } } diff --git a/legend-engine-xts-snowflakeApp/legend-engine-xt-snowflakeApp-api/src/test/java/org/finos/legend/engine/language/snowflakeApp/api/TestValidation.java b/legend-engine-xts-snowflakeApp/legend-engine-xt-snowflakeApp-api/src/test/java/org/finos/legend/engine/language/snowflakeApp/api/TestValidation.java index 8f1bdc557e5..04b5ac47270 100644 --- a/legend-engine-xts-snowflakeApp/legend-engine-xt-snowflakeApp-api/src/test/java/org/finos/legend/engine/language/snowflakeApp/api/TestValidation.java +++ b/legend-engine-xts-snowflakeApp/legend-engine-xt-snowflakeApp-api/src/test/java/org/finos/legend/engine/language/snowflakeApp/api/TestValidation.java @@ -52,7 +52,7 @@ public void testProperPlan() " ownership : Deployment { identifier: 'ownership' };" + " function: a::f():TabularDataSet[1];" + "}"; - Response response = api.validate(new FunctionActivatorInput("vX_X_X", "a::myApp", PureGrammarParser.newInstance().parseModel(val)), null); + Response response = api.validate(new FunctionActivatorInput("vX_X_X", "a::myApp", PureGrammarParser.newInstance().parseModel(val)), null, null); Assert.assertEquals("[]", response.getEntity().toString()); } @@ -75,7 +75,7 @@ public void testImproperPlan() " ownership : Deployment { identifier: 'ownership' };" + " function: a::f():Person[*];" + "}"; - Response response = api.validate(new FunctionActivatorInput("vX_X_X", "a::myApp", PureGrammarParser.newInstance().parseModel(val)), null); + Response response = api.validate(new FunctionActivatorInput("vX_X_X", "a::myApp", PureGrammarParser.newInstance().parseModel(val)), null, null); Assert.assertEquals("[{\"foundSQLs\":[],\"message\":\"SnowflakeApp can't be used with a plan containing '0' SQL expressions\"}]", response.getEntity().toString()); }