From b627d3b57830ba490a3460ce79060f7e867b52db Mon Sep 17 00:00:00 2001 From: a-cordier Date: Tue, 4 Nov 2025 15:03:37 +0000 Subject: [PATCH] feat: add endpoint to expose analytics definitions see https://gravitee.atlassian.net/browse/GKO-1579 --- .../spring/ResourceContextConfiguration.java | 31 + .../pom.xml | 11 + .../rest/GraviteeManagementV2Application.java | 2 + .../mapper/AnalyticsDefinitionMapper.java | 69 + .../AnalyticsDefinitionResource.java | 89 + .../EnvironmentAnalyticsResource.java | 12 + .../resources/openapi/openapi-analytics.yaml | 853 ++++- .../AnalyticsDefinitionResourceTest.java | 105 + .../spring/ResourceContextConfiguration.java | 31 + .../spring/ResourceContextConfiguration.java | 31 + .../spring/ResourceContextConfiguration.java | 31 + .../definition/AnalyticsDefinition.java | 57 + .../definition/AnalyticsDefinition.java | 18 + .../definition/AnalyticsDefinitionSpec.java | 20 + .../model/engine/definition/ApiSpec.java | 26 + .../model/engine/definition/FacetSpec.java | 54 + .../model/engine/definition/FilterSpec.java | 70 + .../model/engine/definition/MetricSpec.java | 88 + .../model/engine/definition/NumberRange.java | 18 + .../definition/GetApiMetricsUseCase.java | 40 + .../engine/definition/GetApiSpecsUseCase.java | 37 + .../definition/GetMetricFacetsUseCase.java | 40 + .../definition/GetMetricFiltersUseCase.java | 40 + .../AnalyticsDefinitionDomainServiceImpl.java | 94 + .../definition/analytics-definition.yaml | 3310 +++++++---------- .../request.json | 31 + .../response.json | 27 + .../request.json | 10 +- .../response.json | 49 +- .../request.json | 11 +- .../response.json | 20 +- .../request.json | 11 +- .../response.json | 40 +- .../request.json | 8 +- .../response.json | 21 +- .../measures-http-request-count/request.json | 6 +- .../measures-http-request-count/response.json | 11 +- .../request.json | 10 +- .../response.json | 111 +- .../request.json | 6 +- .../response.json | 56 +- .../request.json | 8 +- .../response.json | 116 +- .../analytics/openapi-analytics.yaml | 1 + 44 files changed, 3372 insertions(+), 2358 deletions(-) create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/mapper/AnalyticsDefinitionMapper.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResource.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResourceTest.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/domain_service/engine/definition/AnalyticsDefinition.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinition.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinitionSpec.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/ApiSpec.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FacetSpec.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FilterSpec.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/MetricSpec.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/NumberRange.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiMetricsUseCase.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiSpecsUseCase.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFacetsUseCase.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFiltersUseCase.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/infra/domain_service/analytics/AnalyticsDefinitionDomainServiceImpl.java create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/request.json create mode 100644 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/response.json create mode 120000 gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/openapi-analytics.yaml diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-automation/gravitee-apim-rest-api-automation-rest/src/test/java/io/gravitee/apim/rest/api/automation/spring/ResourceContextConfiguration.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-automation/gravitee-apim-rest-api-automation-rest/src/test/java/io/gravitee/apim/rest/api/automation/spring/ResourceContextConfiguration.java index 1d25941a7d9..7418a6516ba 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-automation/gravitee-apim-rest-api-automation-rest/src/test/java/io/gravitee/apim/rest/api/automation/spring/ResourceContextConfiguration.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-automation/gravitee-apim-rest-api-automation-rest/src/test/java/io/gravitee/apim/rest/api/automation/spring/ResourceContextConfiguration.java @@ -37,6 +37,11 @@ import inmemory.SharedPolicyGroupCrudServiceInMemory; import inmemory.SharedPolicyGroupHistoryCrudServiceInMemory; import inmemory.spring.InMemoryConfiguration; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiMetricsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiSpecsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFacetsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFiltersUseCase; import io.gravitee.apim.core.api.domain_service.ApiExportDomainService; import io.gravitee.apim.core.api.domain_service.ApiImportDomainService; import io.gravitee.apim.core.api.domain_service.ApiMetadataDecoderDomainService; @@ -129,6 +134,7 @@ import io.gravitee.apim.core.subscription.use_case.RejectSubscriptionUseCase; import io.gravitee.apim.infra.adapter.SubscriptionAdapter; import io.gravitee.apim.infra.adapter.SubscriptionAdapterImpl; +import io.gravitee.apim.infra.domain_service.analytics.AnalyticsDefinitionDomainServiceImpl; import io.gravitee.apim.infra.domain_service.application.ValidateApplicationSettingsDomainServiceImpl; import io.gravitee.apim.infra.domain_service.documentation.ValidatePageSourceDomainServiceImpl; import io.gravitee.apim.infra.domain_service.group.ValidateGroupCRDDomainServiceImpl; @@ -874,4 +880,29 @@ public CockpitPromotionServiceProvider cockpitPromotionServiceProvider() { public CreatePromotionUseCase createPromotionUseCase() { return mock(CreatePromotionUseCase.class); } + + @Bean + public AnalyticsDefinition analyticsDefinitionDomainService() { + return new AnalyticsDefinitionDomainServiceImpl(); + } + + @Bean + public GetApiSpecsUseCase getApiSpecsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiSpecsUseCase(analyticsDefinition); + } + + @Bean + public GetApiMetricsUseCase getApiMetricsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiMetricsUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFiltersUseCase getMetricFiltersUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFiltersUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFacetsUseCase getMetricFacetsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFacetsUseCase(analyticsDefinition); + } } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/pom.xml b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/pom.xml index 479bf30a94f..1424c7b4a1c 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/pom.xml +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/pom.xml @@ -293,7 +293,18 @@ ${project.basedir}/src/main/resources/openapi/openapi-installation-deprecated.yaml + + model-analytics + + generate + + + ${project.basedir}/src/main/resources/openapi/openapi-analytics.yaml + ${openapi.modelPackage}.analytics.engine + + + diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/GraviteeManagementV2Application.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/GraviteeManagementV2Application.java index 6524b3209f1..47ced5227b5 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/GraviteeManagementV2Application.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/GraviteeManagementV2Application.java @@ -33,6 +33,7 @@ import io.gravitee.rest.api.management.v2.rest.provider.ObjectMapperResolver; import io.gravitee.rest.api.management.v2.rest.provider.YamlWriter; import io.gravitee.rest.api.management.v2.rest.resource.OpenAPIResource; +import io.gravitee.rest.api.management.v2.rest.resource.analytics.definition.AnalyticsDefinitionResource; import io.gravitee.rest.api.management.v2.rest.resource.api.ApisResource; import io.gravitee.rest.api.management.v2.rest.resource.application.ApplicationsResource; import io.gravitee.rest.api.management.v2.rest.resource.asyncjob.AsyncJobsResource; @@ -73,6 +74,7 @@ public GraviteeManagementV2Application() { register(EnvironmentsResource.class); register(ApisResource.class); register(ApplicationsResource.class); + register(AnalyticsDefinitionResource.class); // Resources deprecated at root level register(EndpointsResource.class); diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/mapper/AnalyticsDefinitionMapper.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/mapper/AnalyticsDefinitionMapper.java new file mode 100644 index 00000000000..702d86420d7 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/mapper/AnalyticsDefinitionMapper.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.rest.api.management.v2.rest.mapper; + +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.ApiSpec; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.ApiSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FacetSpec; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FacetSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FilterSpec; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FilterSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.MetricSpec; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.MetricSpecsResponse; +import java.util.List; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AnalyticsDefinitionMapper { + AnalyticsDefinitionMapper INSTANCE = Mappers.getMapper(AnalyticsDefinitionMapper.class); + + ApiSpec mapApiSpec(io.gravitee.apim.core.analytics.model.engine.definition.ApiSpec apiSpec); + + List mapApiSpecs(List apiSpecs); + + default ApiSpecsResponse toApiSpecsResponse(List apiSpecs) { + return new ApiSpecsResponse().data(mapApiSpecs(apiSpecs)); + } + + MetricSpec mapMetricSpec(io.gravitee.apim.core.analytics.model.engine.definition.MetricSpec metricSpec); + + List mapMetricSpecs(List metricSpecs); + + default MetricSpecsResponse toMetricSpecsResponse( + List metricSpecs + ) { + return new MetricSpecsResponse().data(mapMetricSpecs(metricSpecs)); + } + + FacetSpec mapFacetSpec(io.gravitee.apim.core.analytics.model.engine.definition.FacetSpec facetSpec); + + List mapFacetSpecs(List facetSpecs); + + default FacetSpecsResponse toFacetSpecsResponse(List facetSpecs) { + return new FacetSpecsResponse().data(mapFacetSpecs(facetSpecs)); + } + + FilterSpec mapFilterSpec(io.gravitee.apim.core.analytics.model.engine.definition.FilterSpec filterSpec); + + List mapFilterSpecs(List filterSpecs); + + default FilterSpecsResponse toFilterSpecsResponse( + List filterSpecs + ) { + return new FilterSpecsResponse().data(mapFilterSpecs(filterSpecs)); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResource.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResource.java new file mode 100644 index 00000000000..e9112653ba8 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResource.java @@ -0,0 +1,89 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.rest.api.management.v2.rest.resource.analytics.definition; + +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiMetricsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiSpecsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFacetsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFiltersUseCase; +import io.gravitee.rest.api.management.v2.rest.mapper.AnalyticsDefinitionMapper; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.ApiSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FacetSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FilterSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.MetricSpecsResponse; +import io.gravitee.rest.api.model.permissions.RolePermission; +import io.gravitee.rest.api.model.permissions.RolePermissionAction; +import io.gravitee.rest.api.rest.annotation.Permission; +import io.gravitee.rest.api.rest.annotation.Permissions; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +public class AnalyticsDefinitionResource { + + @Inject + GetApiSpecsUseCase getApiSpecsUseCase; + + @Inject + GetApiMetricsUseCase getApiMetricsUseCase; + + @Inject + GetMetricFacetsUseCase getMetricFacetsUseCase; + + @Inject + GetMetricFiltersUseCase getMetricFiltersUseCase; + + @Path("/apis") + @GET + @Produces(MediaType.APPLICATION_JSON) + @Permissions({ @Permission(value = RolePermission.API_ANALYTICS, acls = { RolePermissionAction.READ }) }) + public ApiSpecsResponse getApiSpecs() { + return AnalyticsDefinitionMapper.INSTANCE.toApiSpecsResponse(getApiSpecsUseCase.execute().specs()); + } + + @Path("/apis/{apiName}/metrics") + @GET + @Produces(MediaType.APPLICATION_JSON) + @Permissions({ @Permission(value = RolePermission.API_ANALYTICS, acls = { RolePermissionAction.READ }) }) + public MetricSpecsResponse getApiMetrics(@PathParam("apiName") String apiName) { + return AnalyticsDefinitionMapper.INSTANCE.toMetricSpecsResponse( + getApiMetricsUseCase.execute(new GetApiMetricsUseCase.Input(apiName)).specs() + ); + } + + @Path("/metrics/{metricName}/facets") + @GET + @Produces(MediaType.APPLICATION_JSON) + @Permissions({ @Permission(value = RolePermission.API_ANALYTICS, acls = { RolePermissionAction.READ }) }) + public FacetSpecsResponse getMetricFacets(@PathParam("metricName") String metricName) { + return AnalyticsDefinitionMapper.INSTANCE.toFacetSpecsResponse( + getMetricFacetsUseCase.execute(new GetMetricFacetsUseCase.Input(metricName)).specs() + ); + } + + @Path("/metrics/{metricName}/filters") + @GET + @Produces(MediaType.APPLICATION_JSON) + @Permissions({ @Permission(value = RolePermission.API_ANALYTICS, acls = { RolePermissionAction.READ }) }) + public FilterSpecsResponse getMetricFilters(@PathParam("apiName") String apiName, @PathParam("metricName") String metricName) { + return AnalyticsDefinitionMapper.INSTANCE.toFilterSpecsResponse( + getMetricFiltersUseCase.execute(new GetMetricFiltersUseCase.Input(metricName)).specs() + ); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/environment/EnvironmentAnalyticsResource.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/environment/EnvironmentAnalyticsResource.java index 9146644f9eb..5973c68bd61 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/environment/EnvironmentAnalyticsResource.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/java/io/gravitee/rest/api/management/v2/rest/resource/environment/EnvironmentAnalyticsResource.java @@ -32,7 +32,9 @@ import io.gravitee.rest.api.management.v2.rest.model.EnvironmentAnalyticsTopAppsByRequestCountResponse; import io.gravitee.rest.api.management.v2.rest.model.EnvironmentAnalyticsTopFailedApisResponse; import io.gravitee.rest.api.management.v2.rest.model.EnvironmentAnalyticsTopHitsApisResponse; +import io.gravitee.rest.api.management.v2.rest.resource.analytics.definition.AnalyticsDefinitionResource; import io.gravitee.rest.api.management.v2.rest.resource.environment.param.TimeRangeParam; +import io.gravitee.rest.api.management.v2.rest.resource.plugin.PoliciesResource; import io.gravitee.rest.api.model.permissions.RolePermission; import io.gravitee.rest.api.model.permissions.RolePermissionAction; import io.gravitee.rest.api.rest.annotation.Permission; @@ -45,6 +47,8 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.container.ResourceContext; +import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import java.time.Duration; import java.time.Instant; @@ -52,6 +56,9 @@ public class EnvironmentAnalyticsResource { + @Context + private ResourceContext resourceContext; + @Inject SearchEnvironmentResponseStatusRangesUseCase searchEnvironmentResponseStatusRangesUseCase; @@ -193,4 +200,9 @@ public EnvironmentAnalyticsTopFailedApisResponse getTopFailedApis(@BeanParam @Va return EnvironmentAnalyticsMapper.INSTANCE.map(topFailedApis); } + + @Path("/definition") + public AnalyticsDefinitionResource getAnalyticsDefinitionApisResource() { + return resourceContext.getResource(AnalyticsDefinitionResource.class); + } } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/resources/openapi/openapi-analytics.yaml b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/resources/openapi/openapi-analytics.yaml index 780032ebc71..b8281fc44fb 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/resources/openapi/openapi-analytics.yaml +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/resources/openapi/openapi-analytics.yaml @@ -24,7 +24,8 @@ info: tags: - name: computation description: Analytics computation operations for data processing and aggregation - + - name: definition + description: Gravitee analytics definition containing metrics, facets and filters that can be used to query analytics data. servers: - url: "/management/v2" description: APIM Management API v2 - Default base URL @@ -36,6 +37,208 @@ servers: default: DEFAULT paths: + /environments/{envId}/analytics/definition/apis: + get: + operationId: queryApiSpecs + summary: Query available APIs for analytics + description: | + Returns a list of available APIs for analytics, that can be used to obtain available metrics each one of them. + tags: + - definition + parameters: + - $ref: "#/components/parameters/EnvId" + responses: + "200": + description: | + The response contains a list of available APIs for analytics, that can be used to obtain available metrics each one of them. + content: + application/json: + schema: + $ref: "#/components/schemas/ApiSpecsResponse" + examples: + apis: + summary: API Specs Response + value: + data: + - name: "HTTP_PROXY" + label: "HTTP Proxy" + - name: "MESSAGE" + label: "Message" + - name: "KAFKA" + label: "Kafka" + - name: "LLM" + label: "LLM" + - name: "MCP" + label: "MCP" + "500": + description: Internal server error while getting available API specs. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + + /environments/{envId}/analytics/definition/apis/{apiName}/metrics: + get: + operationId: queryMetricSpecs + summary: Query available metrics for an API type + description: | + Returns a list of available metrics for a specific API type, including their supported measures, facets, and filters. + tags: + - definition + parameters: + - $ref: "#/components/parameters/EnvId" + - $ref: "#/components/parameters/ApiName" + responses: + "200": + description: | + The response contains a list of available metrics for the specified API type, with their configurations including measures, facets, and filters. + content: + application/json: + schema: + $ref: "#/components/schemas/MetricSpecsResponse" + examples: + http-proxy-metrics: + summary: HTTP Proxy API Metrics + value: + data: + - name: "HTTP_REQUESTS" + label: "HTTP Requests" + apis: ["HTTP_PROXY", "LLM"] + type: "COUNTER" + measures: ["COUNT", "RPS"] + facets: ["API", "APPLICATION", "GATEWAY"] + filters: ["API", "APPLICATION", "HTTP_STATUS"] + - name: "HTTP_GATEWAY_RESPONSE_TIME" + label: "Gateway response time" + apis: ["HTTP_PROXY", "LLM"] + type: "GAUGE" + unit: "MILLISECONDS" + measures: ["AVG", "MIN", "MAX", "P50", "P90", "P95", "P99"] + facets: ["API", "APPLICATION", "GATEWAY"] + filters: ["API", "APPLICATION", "HTTP_STATUS"] + "400": + description: Bad request - Invalid API name for metrics. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal server error while getting metric specifications. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + + /environments/{envId}/analytics/definition/metrics/{metricName}/filters: + get: + operationId: queryFilterSpecsForMetric + summary: Query available filters for a specific metric + description: | + Returns a list of available filters that can be applied to a specific metric within an API type, including their operators and value constraints. + tags: + - definition + parameters: + - $ref: "#/components/parameters/EnvId" + - $ref: "#/components/parameters/MetricName" + responses: + "200": + description: | + The response contains a list of available filters for the specified metric, including their supported operators, types, and optional enum values or ranges. + content: + application/json: + schema: + $ref: "#/components/schemas/FilterSpecsResponse" + examples: + http-requests-filters: + summary: HTTP Requests Metric Filters + value: + data: + - name: "API" + label: "API" + type: "KEYWORD" + operators: ["EQ", "IN"] + - name: "APPLICATION" + label: "Application" + type: "KEYWORD" + operators: ["EQ", "IN"] + - name: "HTTP_STATUS" + label: "Status Code" + type: "NUMBER" + operators: ["EQ", "LTE", "GTE"] + range: + min: 100 + max: 600 + - name: "HTTP_STATUS_CODE_GROUP" + label: "Status Code Group" + type: "ENUM" + operators: ["EQ", "IN"] + enumValues: ["1xx", "2xx", "3xx", "4xx", "5xx"] + "400": + description: Bad request - Invalid metric name for filters. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "404": + description: API type or metric not found. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal server error while getting filter specifications for the metric. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + + /environments/{envId}/analytics/definition/metrics/{metricName}/facets: + get: + operationId: queryFacetSpecsForMetric + summary: Query available facets for a specific metric + description: | + Returns a list of available facets that can be used to group data for a specific metric within an API type, including their data types. + tags: + - definition + parameters: + - $ref: "#/components/parameters/EnvId" + - $ref: "#/components/parameters/MetricName" + responses: + "200": + description: | + The response contains a list of available facets for the specified metric that can be used for grouping analytics data, including their data types. + content: + application/json: + schema: + $ref: "#/components/schemas/FacetSpecsResponse" + examples: + http-requests-facets: + summary: HTTP Requests Metric Facets + value: + data: + - name: "API" + label: "API" + type: "KEYWORD" + - name: "APPLICATION" + label: "Application" + type: "KEYWORD" + - name: "GATEWAY" + label: "Gateway" + type: "KEYWORD" + + "400": + description: Bad request - Invalid metric name for facets. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal server error while getting facet specifications for the metric. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /environments/{envId}/analytics/measures: post: operationId: queryMeasures @@ -49,9 +252,9 @@ paths: - $ref: "#/components/parameters/EnvId" requestBody: description: | - A measures request is a request to obtain a single set of measures / aggregations, without grouping them by bucket. + A measures request is a request to obtain a single set of measures, without grouping them by bucket. - - Measures requests allow to return aggregated values for the specified metric and aggregations. + - Measures requests allow to return aggregated values for the specified metric and measures. - Available measures can change depending on the required metric. @@ -72,8 +275,8 @@ paths: from: "2025-01-01T00:00:00Z" to: "2025-01-31T23:59:59Z" metrics: - - name: "HTTP_REQUEST_COUNT" - aggregations: ["COUNT", "RPS"] + - name: "HTTP_REQUESTS" + measures: ["COUNT", "RPS"] multiple-metrics: summary: Multiple metrics example value: @@ -81,10 +284,10 @@ paths: from: "2025-01-01T00:00:00Z" to: "2025-01-31T23:59:59Z" metrics: - - name: "HTTP_REQUEST_COUNT" - aggregations: ["COUNT"] + - name: "HTTP_REQUESTS" + measures: ["COUNT"] - name: "HTTP_GATEWAY_RESPONSE_TIME" - aggregations: ["AVG"] + measures: ["AVG"] responses: "200": description: | @@ -98,20 +301,24 @@ paths: summary: Single metric response value: metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" measures: - COUNT: 2984 - RPS: 45.7 + - name: "COUNT" + value: 2984 + - name: "RPS" + value: 45.7 multiple-metrics: summary: Multiple metrics response value: metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" measures: - COUNT: 2984 + - name: "COUNT" + value: 2984 - name: "HTTP_GATEWAY_RESPONSE_TIME" measures: - AVG: 89.5 + - name: "AVG" + value: 89.5 "400": description: Bad request - Invalid Measures Request. content: @@ -157,9 +364,9 @@ paths: timeRange: from: "2025-01-01T00:00:00Z" to: "2025-01-31T23:59:59Z" + by: ["API"] metrics: - - name: "HTTP_REQUEST_COUNT" - by: ["API"] + - name: "HTTP_REQUESTS" limit: 1 order: measure: "COUNT" @@ -173,14 +380,16 @@ paths: $ref: "#/components/schemas/FacetsResponse" example: metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" buckets: - key: "07ba30d4-7b42-418b-a3f9-2ad684947b82" measures: - COUNT: 1234 + - name: "COUNT" + value: 1234 - key: "a0131e80-d886-462a-8c0b-1d205e42cc12" measures: - COUNT: 989 + - name: "COUNT" + value: 989 "400": description: Bad request - Invalid Facets Request. content: @@ -229,7 +438,7 @@ paths: interval: "auto" by: ["API"] metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" responses: "200": description: Time series analytics response @@ -240,26 +449,30 @@ paths: example: interval: "1m" metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" buckets: - key: "2025-01-01T00:00:00Z" timestamp: 1735689600000 buckets: - key: "a5954f6e-1d95-463a-9a41-2442c575d022" measures: - COUNT: 1234 + - name: "COUNT" + value: 1234 - key: "12bff449-1556-491c-8e34-c1c93b27e1cb" measures: - COUNT: 989 + - name: "COUNT" + value: 989 - key: "2025-01-01T00:01:00Z" timestamp: 1735689660000 buckets: - key: "a5954f6e-1d95-463a-9a41-2442c575d022" measures: - COUNT: 873 + - name: "COUNT" + value: 873 - key: "12bff449-1556-491c-8e34-c1c93b27e1cb" measures: - COUNT: 938 + - name: "COUNT" + value: 938 "400": description: Bad request - Invalid Time Series Request content: @@ -284,21 +497,48 @@ components: type: string default: DEFAULT + ApiName: + name: apiName + in: path + required: true + description: The API type identifier for which to retrieve metrics + schema: + $ref: "#/components/schemas/ApiName" + + MetricName: + name: metricName + in: path + required: true + description: The metric identifier for which to retrieve filter specifications + schema: + $ref: "#/components/schemas/MetricName" + schemas: + ApiName: + type: string + enum: + - HTTP_PROXY + - MESSAGE + - KAFKA + - LLM + - MCP + description: Available API names for analytics queries + example: "HTTP_PROXY" + MetricName: type: string enum: - HTTP_REQUESTS - - HTTP_ERROR_RATE + - HTTP_ERRORS - HTTP_REQUEST_CONTENT_LENGTH - HTTP_RESPONSE_CONTENT_LENGTH - HTTP_ENDPOINT_RESPONSE_TIME - HTTP_GATEWAY_RESPONSE_TIME - HTTP_GATEWAY_LATENCY - LLM_PROMPT_TOKEN_SENT - - LLM_PROMPT_TOKEN_RECEIVE + - LLM_PROMPT_TOKEN_RECEIVED - LLM_PROMPT_TOKEN_SENT_COST - - LLM_PROMPT_TOKEN_RECEIVE_COST + - LLM_PROMPT_TOKEN_RECEIVED_COST - MESSAGE_PAYLOAD_SIZE - MESSAGES - MESSAGE_ERRORS @@ -322,6 +562,7 @@ components: - SUBSCRIPTIONS - APIS description: Available metric names for analytics queries + FacetName: type: string enum: @@ -348,9 +589,10 @@ components: - MESSAGE_OPERATION_TYPE - KAFKA_TOPIC - API_STATE - - API_LIFECYCLE_STATEgst + - API_LIFECYCLE_STATE - API_VISIBILITY description: Available facet names for grouping analytics data + FilterName: type: string enum: @@ -388,76 +630,6 @@ components: - HTTP_REQUEST_CONTENT_LENGTH - HTTP_RESPONSE_CONTENT_LENGTH description: Available filter names for filtering analytics data - Error: - description: | - The generic error object returned by any endpoint of the Gravitee APIM API. - type: object - properties: - httpStatus: - type: integer - format: int32 - description: The error code - example: 400 - message: - type: string - description: A global response error message - example: Bad request - technicalCode: - type: string - description: A technical code to identify the error - example: invalid.import.definition - parameters: - type: object - description: | - Parameters add information about the context of the error. - additionalProperties: - type: string - example: - name: "HTTP_REQUEST_COUNT" - type: "TIME_SERIES" - interval: "-1d" - details: - type: array - description: A list of details about the error - items: - type: object - properties: - message: - type: string - description: A fine grained error message regarding a failing property. - example: Bad request - location: - type: string - description: The json path of the field in error. - example: updateApi.properties[0].key - invalidValue: - oneOf: - - type: string - - type: number - - type: boolean - - type: array - - type: object - description: The invalid value (can be any type) - example: "-1d" - example: - - message: "Interval must be a positive duration (e.g., '1h', '1d', 'auto')" - location: "requests[0].interval" - invalidValue: "-1d" - example: - httpStatus: 400 - message: "Bad request - Invalid Time Series Request" - technicalCode: "invalid.analytics.request" - parameters: - field: "requests[0].interval" - value: "-1d" - interval: "-1d" - details: - - message: "Invalid interval value" - location: "requests[0].interval" - invalidValue: "-1d" - - message: "Interval must be a positive duration (e.g., '1h', '1d', 'auto')" - location: "requests[0].interval" - invalidValue: "-1d" Operator: type: string @@ -468,7 +640,7 @@ components: - GTE description: Filter operator - Aggregation: + MeasureName: type: string enum: - AVG @@ -480,7 +652,28 @@ components: - P99 - COUNT - RPS - description: Aggregation function + - PERCENTAGE + description: Measure name identifier. Represents the type of measure/aggregation applied to a metric. + example: "COUNT" + + Measure: + type: object + required: + - name + - value + description: A single measure result containing the measure name and its value. + properties: + name: + $ref: "#/components/schemas/MeasureName" + value: + oneOf: + - type: number + - type: string + description: The measure value. Can be a number or a string representation of a number. + example: 2984 + example: + name: "COUNT" + value: 2984 OrderDirection: type: string @@ -489,6 +682,279 @@ components: - DESC description: Sort order direction + MetricType: + type: string + enum: + - COUNTER + - GAUGE + description: | + Metric type identifier. + + - **COUNTER**: A counter metric increases monotonically, representing cumulative values over time. Counters are typically used for counting events or occurrences. + + - **GAUGE**: A gauge metric can increase and decrease over time, representing values that can go up or down. Gauges are typically used for measuring current state or instantaneous values. + example: "COUNTER" + + UnitName: + type: string + enum: + - BYTES + - MILLISECONDS + - NUMBER + description: | + Unit of measurement for gauge metrics. Specifies the unit in which the metric values are expressed. + + This field is optional and only applicable for GAUGE metrics. COUNTER metrics do not have units. + example: "BYTES" + + ApiSpec: + description: | + An API type specification. Available metrics are defined by the API type. + type: object + properties: + name: + $ref: "#/components/schemas/ApiName" + label: + type: string + description: A human-readable label for the API + example: "HTTP Proxy" + example: + name: "HTTP_PROXY" + label: "HTTP Proxy" + + FacetSpec: + type: object + required: + - name + - label + - type + description: Facet specification for analytics grouping + properties: + name: + $ref: "#/components/schemas/FacetName" + label: + type: string + description: Human-readable label for the facet + example: "API" + type: + type: string + enum: + - STRING + - KEYWORD + - NUMBER + description: Data type of the facet + example: "KEYWORD" + example: + name: "API" + label: "API" + type: "KEYWORD" + + FilterSpec: + type: object + required: + - name + - label + - type + - operators + description: Filter specification for filtering analytics. Available filters are defined for a specific metric. + properties: + name: + $ref: "#/components/schemas/FilterName" + label: + type: string + description: Human-readable label for the filter + example: "API" + type: + type: string + enum: + - KEYWORD + - STRING + - NUMBER + - ENUM + description: Data type of the filter + example: "KEYWORD" + operators: + type: array + items: + $ref: "#/components/schemas/Operator" + description: List of supported operators for this filter + example: ["EQ", "IN"] + enumValues: + type: array + items: + type: string + description: Enum values (only applicable for enum type) + example: ["GET", "POST", "PUT"] + range: + type: object + properties: + min: + type: number + description: Minimum value + example: 100 + max: + type: number + description: Maximum value + example: 600 + description: Value range (only applicable for integer/long types) + example: + min: 100 + max: 600 + example: + name: "API" + label: "API" + type: "KEYWORD" + operators: ["EQ", "IN"] + + MetricSpec: + type: object + required: + - name + - label + - apis + - type + - measures + - facets + - filters + description: Metric specification for analytics queries + properties: + name: + $ref: "#/components/schemas/MetricName" + label: + type: string + description: Human-readable label for the metric + example: "HTTP Requests" + apis: + type: array + items: + $ref: "#/components/schemas/ApiName" + description: List of API types this metric applies to + example: ["HTTP_PROXY", "LLM"] + type: + $ref: "#/components/schemas/MetricType" + unit: + $ref: "#/components/schemas/UnitName" + measures: + type: array + items: + $ref: "#/components/schemas/MeasureName" + description: List of supported measures for this metric + example: ["COUNT", "RPS"] + facets: + type: array + items: + $ref: "#/components/schemas/FacetName" + description: List of facets that can be used for grouping this metric + example: ["API", "APPLICATION", "GATEWAY"] + filters: + type: array + items: + $ref: "#/components/schemas/FilterName" + description: List of filters that can be applied to this metric + example: ["API", "APPLICATION", "HTTP_STATUS"] + example: + name: "HTTP_REQUESTS" + label: "HTTP Requests" + apis: ["HTTP_PROXY", "LLM"] + type: "COUNTER" + measures: ["COUNT", "RPS"] + facets: ["API", "APPLICATION", "GATEWAY"] + filters: ["API", "APPLICATION", "HTTP_STATUS"] + + ApiSpecsResponse: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/ApiSpec" + description: The response contains a list of available APIs for analytics queries. + example: + data: + - name: "HTTP_PROXY" + label: "HTTP Proxy" + - name: "MESSAGE" + label: "Message" + - name: "KAFKA" + label: "Kafka" + - name: "LLM" + label: "LLM" + - name: "MCP" + label: "MCP" + + FacetSpecsResponse: + type: object + description: The response contains a list of available facets for grouping a metric. + properties: + data: + type: array + items: + $ref: "#/components/schemas/FacetSpec" + example: + data: + - name: "API" + label: "API" + type: "KEYWORD" + - name: "APPLICATION" + label: "Application" + type: "KEYWORD" + - name: "GATEWAY" + label: "Gateway" + type: "KEYWORD" + + FilterSpecsResponse: + type: object + description: The response contains a list of available filters for filtering analytics data. + properties: + data: + type: array + items: + $ref: "#/components/schemas/FilterSpec" + example: + data: + - name: "API" + label: "API" + type: "KEYWORD" + operators: ["EQ", "IN"] + - name: "HTTP_METHOD" + label: "HTTP Method" + type: "ENUM" + operators: ["EQ", "IN"] + enumValues: ["GET", "POST", "PUT"] + - name: "HTTP_STATUS" + label: "Status Code" + type: "NUMBER" + operators: ["EQ", "LTE", "GTE"] + range: + min: 100 + max: 600 + + MetricSpecsResponse: + type: object + description: The response contains a list of available metrics for a specific API type, including their supported measures, facets, and filters. + properties: + data: + type: array + items: + $ref: "#/components/schemas/MetricSpec" + example: + data: + - name: "HTTP_REQUESTS" + label: "HTTP Requests" + apis: ["HTTP_PROXY", "LLM"] + type: "COUNTER" + measures: ["COUNT", "RPS"] + facets: ["API", "APPLICATION", "GATEWAY"] + filters: ["API", "APPLICATION", "HTTP_STATUS"] + - name: "HTTP_GATEWAY_RESPONSE_TIME" + label: "Gateway response time" + apis: ["HTTP_PROXY", "LLM"] + type: "GAUGE" + unit: "MILLISECONDS" + measures: ["AVG", "MIN", "MAX", "P50", "P90", "P95", "P99"] + facets: ["API", "APPLICATION", "GATEWAY"] + filters: ["API", "APPLICATION", "HTTP_STATUS"] + Interval: type: string description: Time interval for time series queries (e.g., "1m", "auto"). @@ -531,6 +997,10 @@ components: - type: string - type: number - type: array + items: + oneOf: + - type: string + - type: number items: oneOf: - type: string @@ -571,11 +1041,11 @@ components: properties: name: $ref: "#/components/schemas/MetricName" - aggregations: + measures: type: array items: - $ref: "#/components/schemas/Aggregation" - description: List of aggregations to apply + $ref: "#/components/schemas/MeasureName" + description: List of measures to compute for this metric filters: type: array items: @@ -592,7 +1062,7 @@ components: value: "7b6ebef3-6236-4ac5-815e-d3dcef83df5d" metrics: - name: "HTTP_GATEWAY_RESPONSE_TIME" - aggregations: ["P90", "P95", "P99"] + measures: ["P90", "P95", "P99"] FacetsRequest: type: object @@ -656,7 +1126,7 @@ components: operator: "EQ" value: "7b6ebef3-6236-4ac5-815e-d3dcef83df5d" metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" TimeSeriesRequest: type: object @@ -705,9 +1175,10 @@ components: operator: "EQ" value: "7b6ebef3-6236-4ac5-815e-d3dcef83df5d" metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" + measures: ["COUNT"] - name: "HTTP_GATEWAY_RESPONSE_TIME" - aggregations: ["AVG"] + measures: ["AVG"] MetricRequest: type: object @@ -717,11 +1188,11 @@ components: properties: name: $ref: "#/components/schemas/MetricName" - aggregations: + measures: type: array items: - $ref: "#/components/schemas/Aggregation" - description: List of aggregations to apply + $ref: "#/components/schemas/MeasureName" + description: List of measures to compute for this metric filters: type: array items: @@ -729,40 +1200,18 @@ components: description: Request-level filters Measures: - type: object - properties: - AVG: - type: number - description: Average value - MIN: - type: number - description: Minimum value - MAX: - type: number - description: Maximum value - P50: - type: number - description: 50th percentile value - P90: - type: number - description: 90th percentile value - P95: - type: number - description: 95th percentile value - P99: - type: number - description: 99th percentile value - COUNT: - type: number - description: Count value - RPS: - type: number - description: Requests per second value - additionalProperties: false + type: array + items: + $ref: "#/components/schemas/Measure" description: | - Map of aggregation name to measure value (e.g., {"COUNT": 2984, "RPS": 45.7, "P90": 89.9}) - The measures object is always represented as the leaf node of the buckets tree for other types of analytics requests. - Only valid aggregation names from the Aggregation enum are allowed as keys. + Array of measure results. Each measure contains a name and value. + The measures array is always represented as the leaf node of the buckets tree for other types of analytics requests. + Example: [{"name": "COUNT", "value": 2984}, {"name": "RPS", "value": 45.7}] + example: + - name: "COUNT" + value: 2984 + - name: "RPS" + value: 45.7 Bucket: oneOf: @@ -783,7 +1232,7 @@ components: properties: key: type: string - description: Bucket key (facet value for facet buckets, timestamp string for time series buckets) + description: The bucket key is the identifier of the bucket. buckets: $ref: "#/components/schemas/BucketList" description: A bucket can contain either measures (leaf node) or nested buckets (for grouping) @@ -821,11 +1270,11 @@ components: properties: key: type: string - description: Bucket key (facet value for facet buckets, timestamp string for time series buckets) + description: The bucket key is an ISO 8601 timestamp string. timestamp: type: integer format: int64 - description: Timestamp in milliseconds since Unix epoch (optional) + description: Timestamp in milliseconds since Unix epoch example: 1735689600000 buckets: $ref: "#/components/schemas/BucketList" @@ -857,9 +1306,10 @@ components: description: List of measure metric responses example: metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" measures: - COUNT: 2984 + - name: "COUNT" + value: 2984 FacetsResponse: type: object @@ -881,19 +1331,22 @@ components: description: List of facet metric responses. Each metric can have either measures or buckets for grouping. example: metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" buckets: - key: "49ddd7db-35d6-497e-b497-2dc16af0cdcc" buckets: - key: "e65289b0-35b2-40e7-8d41-711fba7fdc96" measures: - RPS: 45.7 + - name: "RPS" + value: 45.7 - key: "4c65d87a-008a-4a4c-b11a-a38b7a662fcc" measures: - RPS: 34.9 - - key: "71091fd9-a6a9-4c7f-afdb-d837ea28058c" - measures: - COUNT: 989 + - name: "RPS" + value: 34.9 + - key: "71091fd9-a6a9-4c7f-afdb-d837ea28058c" + measures: + - name: "RPS" + value: 989 TimeSeriesResponse: type: object @@ -919,24 +1372,104 @@ components: example: interval: "1m" metrics: - - name: "HTTP_REQUEST_COUNT" + - name: "HTTP_REQUESTS" buckets: - key: "2025-01-01T00:00:00Z" timestamp: 1735689600000 buckets: - key: "a5954f6e-1d95-463a-9a41-2442c575d022" measures: - COUNT: 1234 + - name: "COUNT" + value: 1234 - key: "12bff449-1556-491c-8e34-c1c93b27e1cb" measures: - COUNT: 989 + - name: "COUNT" + value: 989 - key: "2025-01-01T00:01:00Z" timestamp: 1735689660000 buckets: - key: "a5954f6e-1d95-463a-9a41-2442c575d022" measures: - COUNT: 873 + - name: "COUNT" + value: 873 - key: "12bff449-1556-491c-8e34-c1c93b27e1cb" measures: - COUNT: 938 + - name: "COUNT" + value: 938 + Error: + description: | + The generic error object returned by any endpoint of the Gravitee APIM API. + type: object + properties: + httpStatus: + type: integer + format: int32 + description: The error code + example: 400 + message: + type: string + description: A global response error message + example: Bad request + technicalCode: + type: string + description: A technical code to identify the error + example: invalid.import.definition + parameters: + type: object + description: | + Parameters add information about the context of the error. + additionalProperties: + type: string + example: + name: "HTTP_REQUESTS" + type: "TIME_SERIES" + interval: "-1d" + details: + type: array + description: A list of details about the error + items: + type: object + properties: + message: + type: string + description: A fine grained error message regarding a failing property. + example: Bad request + location: + type: string + description: The json path of the field in error. + example: updateApi.properties[0].key + invalidValue: + oneOf: + - type: string + - type: number + - type: boolean + - type: array + items: + oneOf: + - type: string + - type: number + - type: boolean + - type: object + - type: object + description: The invalid value (can be any type) + example: "-1d" + example: + - message: "Interval must be a positive duration (e.g., '1h', '1d', 'auto')" + location: "requests[0].interval" + invalidValue: "-1d" + example: + httpStatus: 400 + message: "Bad request - Invalid Time Series Request" + technicalCode: "invalid.analytics.request" + parameters: + field: "requests[0].interval" + value: "-1d" + interval: "-1d" + details: + - message: "Invalid interval value" + location: "requests[0].interval" + invalidValue: "-1d" + - message: "Interval must be a positive duration (e.g., '1h', '1d', 'auto')" + location: "requests[0].interval" + invalidValue: "-1d" diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResourceTest.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResourceTest.java new file mode 100644 index 00000000000..8f62106ccb9 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/resource/analytics/definition/AnalyticsDefinitionResourceTest.java @@ -0,0 +1,105 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.rest.api.management.v2.rest.resource.analytics.definition; + +import static assertions.MAPIAssertions.assertThat; + +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.ApiSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FacetSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.FilterSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.model.analytics.engine.MetricSpecsResponse; +import io.gravitee.rest.api.management.v2.rest.resource.api.ApiResourceTest; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +/** + * @author Antoine CORDIER (antoine.cordier at graviteesource.com) + * @author GraviteeSource Team + */ +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class AnalyticsDefinitionResourceTest extends ApiResourceTest { + + @Override + protected String contextPath() { + return "/environments/" + ENVIRONMENT + "/analytics/definition"; + } + + @Test + void should_return_api_specs() { + var response = rootTarget().path("apis").request().get(); + + assertThat(response) + .hasStatus(200) + .asEntity(ApiSpecsResponse.class) + .extracting(ApiSpecsResponse::getData) + .satisfies(apis -> assertThat(apis).isNotEmpty()); + } + + @Test + void should_return_api_metrics() { + var response = rootTarget().path("apis").path("HTTP_PROXY").path("metrics").request().get(); + + assertThat(response) + .hasStatus(200) + .asEntity(MetricSpecsResponse.class) + .extracting(MetricSpecsResponse::getData) + .satisfies(metrics -> assertThat(metrics).isNotEmpty()); + } + + @Test + void should_return_metric_filters() { + var response = rootTarget().path("metrics").path("HTTP_REQUESTS").path("filters").request().get(); + + assertThat(response) + .hasStatus(200) + .asEntity(FilterSpecsResponse.class) + .extracting(FilterSpecsResponse::getData) + .satisfies(filters -> assertThat(filters).isNotEmpty()); + } + + @Test + void should_return_metric_facets() { + var response = rootTarget().path("metrics").path("HTTP_REQUESTS").path("facets").request().get(); + + assertThat(response) + .hasStatus(200) + .asEntity(FacetSpecsResponse.class) + .extracting(FacetSpecsResponse::getData) + .satisfies(facets -> assertThat(facets).isNotEmpty()); + } + + @Test + void should_return_error_for_unknown_metric_facets() { + var response = rootTarget().path("metrics").path("FOO").path("facets").request().get(); + + assertThat(response).hasStatus(400); + } + + @Test + void should_return_error_for_unknown_metric_filters() { + var response = rootTarget().path("metrics").path("BAR").path("facets").request().get(); + + assertThat(response).hasStatus(400); + } + + @Test + void should_return_error_for_unknown_api_metrics() { + var response = rootTarget().path("apis").path("BAZ").path("metrics").request().get(); + + assertThat(response).hasStatus(400); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/spring/ResourceContextConfiguration.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/spring/ResourceContextConfiguration.java index c1a10a74810..df7d154d488 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/spring/ResourceContextConfiguration.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/test/java/io/gravitee/rest/api/management/v2/rest/spring/ResourceContextConfiguration.java @@ -40,6 +40,11 @@ import inmemory.SharedPolicyGroupCrudServiceInMemory; import inmemory.UserDomainServiceInMemory; import inmemory.spring.InMemoryConfiguration; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiMetricsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiSpecsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFacetsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFiltersUseCase; import io.gravitee.apim.core.api.domain_service.ApiExportDomainService; import io.gravitee.apim.core.api.domain_service.ApiImportDomainService; import io.gravitee.apim.core.api.domain_service.ApiMetadataDecoderDomainService; @@ -135,6 +140,7 @@ import io.gravitee.apim.core.user.domain_service.UserDomainService; import io.gravitee.apim.infra.adapter.SubscriptionAdapter; import io.gravitee.apim.infra.adapter.SubscriptionAdapterImpl; +import io.gravitee.apim.infra.domain_service.analytics.AnalyticsDefinitionDomainServiceImpl; import io.gravitee.apim.infra.domain_service.application.ValidateApplicationSettingsDomainServiceImpl; import io.gravitee.apim.infra.domain_service.documentation.ValidatePageSourceDomainServiceImpl; import io.gravitee.apim.infra.domain_service.group.ValidateGroupCRDDomainServiceImpl; @@ -868,4 +874,29 @@ public CockpitPromotionServiceProvider cockpitPromotionServiceProvider() { public CreatePromotionUseCase createPromotionUseCase() { return mock(CreatePromotionUseCase.class); } + + @Bean + public AnalyticsDefinition analyticsDefinitionDomainService() { + return new AnalyticsDefinitionDomainServiceImpl(); + } + + @Bean + public GetApiSpecsUseCase getApiSpecsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiSpecsUseCase(analyticsDefinition); + } + + @Bean + public GetApiMetricsUseCase getApiMetricsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiMetricsUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFiltersUseCase getMetricFiltersUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFiltersUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFacetsUseCase getMetricFacetsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFacetsUseCase(analyticsDefinition); + } } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-management/gravitee-apim-rest-api-management-rest/src/test/java/io/gravitee/rest/api/management/rest/spring/ResourceContextConfiguration.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-management/gravitee-apim-rest-api-management-rest/src/test/java/io/gravitee/rest/api/management/rest/spring/ResourceContextConfiguration.java index 24f9d999ea2..0aaa0325b63 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-management/gravitee-apim-rest-api-management-rest/src/test/java/io/gravitee/rest/api/management/rest/spring/ResourceContextConfiguration.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-management/gravitee-apim-rest-api-management-rest/src/test/java/io/gravitee/rest/api/management/rest/spring/ResourceContextConfiguration.java @@ -32,6 +32,11 @@ import inmemory.SharedPolicyGroupCrudServiceInMemory; import inmemory.spring.InMemoryConfiguration; import io.gravitee.apim.core.access_point.query_service.AccessPointQueryService; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiMetricsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiSpecsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFacetsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFiltersUseCase; import io.gravitee.apim.core.api.domain_service.ApiExportDomainService; import io.gravitee.apim.core.api.domain_service.ApiImportDomainService; import io.gravitee.apim.core.api.domain_service.ApiMetadataDecoderDomainService; @@ -109,6 +114,7 @@ import io.gravitee.apim.core.subscription.use_case.ImportSubscriptionSpecUseCase; import io.gravitee.apim.infra.adapter.SubscriptionAdapter; import io.gravitee.apim.infra.adapter.SubscriptionAdapterImpl; +import io.gravitee.apim.infra.domain_service.analytics.AnalyticsDefinitionDomainServiceImpl; import io.gravitee.apim.infra.domain_service.api.ApiHostValidatorDomainServiceImpl; import io.gravitee.apim.infra.domain_service.application.ValidateApplicationSettingsDomainServiceImpl; import io.gravitee.apim.infra.domain_service.documentation.ValidatePageSourceDomainServiceImpl; @@ -1006,4 +1012,29 @@ public CockpitPromotionServiceProvider cockpitPromotionServiceProvider() { public CreatePromotionUseCase createPromotionUseCase() { return mock(CreatePromotionUseCase.class); } + + @Bean + public AnalyticsDefinition analyticsDefinitionDomainService() { + return new AnalyticsDefinitionDomainServiceImpl(); + } + + @Bean + public GetApiSpecsUseCase getApiSpecsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiSpecsUseCase(analyticsDefinition); + } + + @Bean + public GetApiMetricsUseCase getApiMetricsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiMetricsUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFiltersUseCase getMetricFiltersUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFiltersUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFacetsUseCase getMetricFacetsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFacetsUseCase(analyticsDefinition); + } } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/test/java/io/gravitee/rest/api/portal/rest/spring/ResourceContextConfiguration.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/test/java/io/gravitee/rest/api/portal/rest/spring/ResourceContextConfiguration.java index 7ab233bd19f..d53fe452e3a 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/test/java/io/gravitee/rest/api/portal/rest/spring/ResourceContextConfiguration.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/test/java/io/gravitee/rest/api/portal/rest/spring/ResourceContextConfiguration.java @@ -31,6 +31,11 @@ import inmemory.SharedPolicyGroupCrudServiceInMemory; import inmemory.spring.InMemoryConfiguration; import io.gravitee.apim.core.access_point.query_service.AccessPointQueryService; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiMetricsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetApiSpecsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFacetsUseCase; +import io.gravitee.apim.core.analytics.use_case.engine.definition.GetMetricFiltersUseCase; import io.gravitee.apim.core.api.domain_service.ApiExportDomainService; import io.gravitee.apim.core.api.domain_service.ApiImportDomainService; import io.gravitee.apim.core.api.domain_service.ApiMetadataDecoderDomainService; @@ -107,6 +112,7 @@ import io.gravitee.apim.core.subscription.use_case.ImportSubscriptionSpecUseCase; import io.gravitee.apim.infra.adapter.SubscriptionAdapter; import io.gravitee.apim.infra.adapter.SubscriptionAdapterImpl; +import io.gravitee.apim.infra.domain_service.analytics.AnalyticsDefinitionDomainServiceImpl; import io.gravitee.apim.infra.domain_service.api.ApiHostValidatorDomainServiceImpl; import io.gravitee.apim.infra.domain_service.application.ValidateApplicationSettingsDomainServiceImpl; import io.gravitee.apim.infra.domain_service.documentation.ValidatePageSourceDomainServiceImpl; @@ -967,4 +973,29 @@ public CockpitPromotionServiceProvider cockpitPromotionServiceProvider() { public CreatePromotionUseCase createPromotionUseCase() { return mock(CreatePromotionUseCase.class); } + + @Bean + public AnalyticsDefinition analyticsDefinitionDomainService() { + return new AnalyticsDefinitionDomainServiceImpl(); + } + + @Bean + public GetApiSpecsUseCase getApiSpecsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiSpecsUseCase(analyticsDefinition); + } + + @Bean + public GetApiMetricsUseCase getApiMetricsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetApiMetricsUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFiltersUseCase getMetricFiltersUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFiltersUseCase(analyticsDefinition); + } + + @Bean + public GetMetricFacetsUseCase getMetricFacetsUseCase(AnalyticsDefinition analyticsDefinition) { + return new GetMetricFacetsUseCase(analyticsDefinition); + } } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/domain_service/engine/definition/AnalyticsDefinition.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/domain_service/engine/definition/AnalyticsDefinition.java new file mode 100644 index 00000000000..8a6076b26c4 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/domain_service/engine/definition/AnalyticsDefinition.java @@ -0,0 +1,57 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.domain_service.engine.definition; + +import io.gravitee.apim.core.analytics.model.engine.definition.ApiSpec; +import io.gravitee.apim.core.analytics.model.engine.definition.FacetSpec; +import io.gravitee.apim.core.analytics.model.engine.definition.FilterSpec; +import io.gravitee.apim.core.analytics.model.engine.definition.MetricSpec; +import io.gravitee.apim.core.exception.ValidationDomainException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public interface AnalyticsDefinition { + List getApis(); + + List getMetrics(ApiSpec.Name apiSpecName); + + List getFilters(MetricSpec.Name metricSpecName); + + List getFacets(MetricSpec.Name metricSpecName); + + default ApiSpec.Name validateApiName(String apiName) { + try { + return ApiSpec.Name.valueOf(apiName); + } catch (IllegalArgumentException e) { + throw new ValidationDomainException( + "Invalid api name", + Map.of("invalidName", apiName, "validNames", Arrays.toString(ApiSpec.Name.values())) + ); + } + } + + default MetricSpec.Name validateMetricName(String metricName) { + try { + return MetricSpec.Name.valueOf(metricName); + } catch (IllegalArgumentException e) { + throw new ValidationDomainException( + "Invalid metric name", + Map.of("invalidName", metricName, "validNames", Arrays.toString(MetricSpec.Name.values())) + ); + } + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinition.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinition.java new file mode 100644 index 00000000000..001ba29c4c3 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinition.java @@ -0,0 +1,18 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.model.engine.definition; + +public record AnalyticsDefinition(AnalyticsDefinitionSpec spec) {} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinitionSpec.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinitionSpec.java new file mode 100644 index 00000000000..a3dfbfe7a27 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/AnalyticsDefinitionSpec.java @@ -0,0 +1,20 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.model.engine.definition; + +import java.util.List; + +public record AnalyticsDefinitionSpec(List apis, List metrics, List filters, List facets) {} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/ApiSpec.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/ApiSpec.java new file mode 100644 index 00000000000..79b6dbe241f --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/ApiSpec.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.model.engine.definition; + +public record ApiSpec(Name name, String label) { + public enum Name { + HTTP_PROXY, + MESSAGE, + KAFKA, + LLM, + MCP, + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FacetSpec.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FacetSpec.java new file mode 100644 index 00000000000..ca2851a9f75 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FacetSpec.java @@ -0,0 +1,54 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.model.engine.definition; + +import java.util.List; + +public record FacetSpec(Name name, String label, String type, List enumValues, NumberRange range) { + public enum Name { + API, + APPLICATION, + PLAN, + GATEWAY, + TENANT, + ZONE, + HTTP_METHOD, + HTTP_STATUS_CODE_GROUP, + HTTP_STATUS, + HTTP_PATH, + HTTP_PATH_MAPPING, + HOST, + GEO_IP_COUNTRY, + GEO_IP_REGION, + GEO_IP_CITY, + GEO_IP_CONTINENT, + CONSUMER_IP, + HTTP_USER_AGENT_OS_NAME, + HTTP_USER_AGENT_DEVICE, + MESSAGE_CONNECTOR_TYPE, + MESSAGE_OPERATION_TYPE, + KAFKA_TOPIC, + API_STATE, + API_LIFECYCLE_STATE, + API_VISIBILITY, + } + + public enum Type { + STRING, + KEYWORD, + NUMBER, + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FilterSpec.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FilterSpec.java new file mode 100644 index 00000000000..55bb30444cb --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/FilterSpec.java @@ -0,0 +1,70 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.model.engine.definition; + +import java.util.List; + +public record FilterSpec(Name name, String label, Type type, List enumValues, NumberRange range, List operators) { + public enum Name { + API, + APPLICATION, + PLAN, + GATEWAY, + TENANT, + ZONE, + HTTP_METHOD, + HTTP_STATUS_CODE_GROUP, + HTTP_STATUS, + HTTP_PATH, + HTTP_PATH_MAPPING, + HOST, + GEO_IP_COUNTRY, + GEO_IP_REGION, + GEO_IP_CITY, + GEO_IP_CONTINENT, + CONSUMER_IP, + HTTP_USER_AGENT_OS_NAME, + HTTP_USER_AGENT_DEVICE, + MESSAGE_CONNECTOR_TYPE, + MESSAGE_OPERATION_TYPE, + KAFKA_TOPIC, + API_STATE, + API_LIFECYCLE_STATE, + API_VISIBILITY, + MESSAGE_SIZE, + MESSAGE_COUNT, + MESSAGE_ERROR_COUNT, + HTTP_ENDPOINT_RESPONSE_TIME, + HTTP_GATEWAY_LATENCY, + HTTP_GATEWAY_RESPONSE_TIME, + HTTP_REQUEST_CONTENT_LENGTH, + HTTP_RESPONSE_CONTENT_LENGTH, + } + + public enum Type { + STRING, + KEYWORD, + ENUM, + NUMBER, + } + + public enum Operator { + EQ, + LTE, + GTE, + IN, + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/MetricSpec.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/MetricSpec.java new file mode 100644 index 00000000000..dfeeb89d79a --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/MetricSpec.java @@ -0,0 +1,88 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.model.engine.definition; + +import java.util.List; + +public record MetricSpec( + Name name, + String label, + List apis, + Type type, + Unit unit, + List measures, + List filters, + List facets +) { + public enum Name { + HTTP_REQUESTS, + HTTP_ERRORS, + HTTP_REQUEST_CONTENT_LENGTH, + HTTP_RESPONSE_CONTENT_LENGTH, + HTTP_ENDPOINT_RESPONSE_TIME, + HTTP_GATEWAY_RESPONSE_TIME, + HTTP_GATEWAY_LATENCY, + LLM_PROMPT_TOKEN_SENT, + LLM_PROMPT_TOKEN_RECEIVED, + LLM_PROMPT_TOKEN_SENT_COST, + LLM_PROMPT_TOKEN_RECEIVED_COST, + MESSAGE_PAYLOAD_SIZE, + MESSAGES, + MESSAGE_ERRORS, + MESSAGE_GATEWAY_LATENCY, + KAFKA_DOWNSTREAM_PUBLISH_MESSAGES, + KAFKA_DOWNSTREAM_SUBSCRIBE_MESSAGES, + KAFKA_DOWNSTREAM_PUBLISH_MESSAGES_BYTES, + KAFKA_DOWNSTREAM_SUBSCRIBE_MESSAGE_BYTES, + KAFKA_UPSTREAM_PUBLISH_MESSAGES, + KAFKA_UPSTREAM_SUBSCRIBE_MESSAGES, + KAFKA_UPSTREAM_PUBLISH_MESSAGE_BYTES, + KAFKA_UPSTREAM_SUBSCRIBE_MESSAGE_BYTES, + KAFKA_DOWNSTREAM_AUTHENTICATION_SUCCESSES, + KAFKA_DOWNSTREAM_AUTHENTICATED_CONNECTIONS, + KAFKA_UPSTREAM_AUTHENTICATION_SUCCESSES, + KAFKA_UPSTREAM_AUTHENTICATED_CONNECTIONS, + KAFKA_UPSTREAM_AUTHENTICATION_ERRORS, + KAFKA_DOWNSTREAM_AUTHENTICATION_ERRORS, + KAFKA_DOWNSTREAM_ACTIVE_CONNECTIONS, + KAFKA_UPSTREAM_ACTIVE_CONNECTIONS, + SUBSCRIPTIONS, + APIS, + } + + public enum Type { + GAUGE, + COUNTER, + } + + public enum Unit { + NUMBER, + MILLISECONDS, + BYTES, + } + + public enum Measure { + AVG, + COUNT, + MAX, + MIN, + RPS, + P99, + P95, + P90, + PERCENTAGE, + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/NumberRange.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/NumberRange.java new file mode 100644 index 00000000000..1d2e4ffd776 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/model/engine/definition/NumberRange.java @@ -0,0 +1,18 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.model.engine.definition; + +public record NumberRange(Number min, Number max) {} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiMetricsUseCase.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiMetricsUseCase.java new file mode 100644 index 00000000000..2a073aeb67d --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiMetricsUseCase.java @@ -0,0 +1,40 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.use_case.engine.definition; + +import io.gravitee.apim.core.UseCase; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.model.engine.definition.MetricSpec; +import java.util.List; + +@UseCase +public class GetApiMetricsUseCase { + + public record Input(String api) {} + + public record Output(List specs) {} + + private final AnalyticsDefinition definition; + + public GetApiMetricsUseCase(AnalyticsDefinition definition) { + this.definition = definition; + } + + public Output execute(Input input) { + var api = definition.validateApiName(input.api()); + return new Output(definition.getMetrics(api)); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiSpecsUseCase.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiSpecsUseCase.java new file mode 100644 index 00000000000..7f00fd421c6 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetApiSpecsUseCase.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.use_case.engine.definition; + +import io.gravitee.apim.core.UseCase; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.model.engine.definition.ApiSpec; +import java.util.List; + +@UseCase +public class GetApiSpecsUseCase { + + private final AnalyticsDefinition definitionDomainService; + + public GetApiSpecsUseCase(AnalyticsDefinition definitionDomainService) { + this.definitionDomainService = definitionDomainService; + } + + public record Output(List specs) {} + + public Output execute() { + return new Output(definitionDomainService.getApis()); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFacetsUseCase.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFacetsUseCase.java new file mode 100644 index 00000000000..efd22ed9b29 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFacetsUseCase.java @@ -0,0 +1,40 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.use_case.engine.definition; + +import io.gravitee.apim.core.UseCase; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.model.engine.definition.FacetSpec; +import java.util.List; + +@UseCase +public class GetMetricFacetsUseCase { + + private final AnalyticsDefinition definition; + + public GetMetricFacetsUseCase(AnalyticsDefinition definition) { + this.definition = definition; + } + + public record Input(String metric) {} + + public record Output(List specs) {} + + public Output execute(Input input) { + var metric = definition.validateMetricName(input.metric()); + return new Output(definition.getFacets(metric)); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFiltersUseCase.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFiltersUseCase.java new file mode 100644 index 00000000000..45bf96ba645 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/analytics/use_case/engine/definition/GetMetricFiltersUseCase.java @@ -0,0 +1,40 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.analytics.use_case.engine.definition; + +import io.gravitee.apim.core.UseCase; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.model.engine.definition.FilterSpec; +import java.util.List; + +@UseCase +public class GetMetricFiltersUseCase { + + private final AnalyticsDefinition definition; + + public GetMetricFiltersUseCase(AnalyticsDefinition definition) { + this.definition = definition; + } + + public record Input(String metric) {} + + public record Output(List specs) {} + + public Output execute(Input input) { + var metric = definition.validateMetricName(input.metric()); + return new Output(definition.getFilters(metric)); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/infra/domain_service/analytics/AnalyticsDefinitionDomainServiceImpl.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/infra/domain_service/analytics/AnalyticsDefinitionDomainServiceImpl.java new file mode 100644 index 00000000000..763403d7dd3 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/infra/domain_service/analytics/AnalyticsDefinitionDomainServiceImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.infra.domain_service.analytics; + +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import io.gravitee.apim.core.analytics.domain_service.engine.definition.AnalyticsDefinition; +import io.gravitee.apim.core.analytics.model.engine.definition.AnalyticsDefinitionSpec; +import io.gravitee.apim.core.analytics.model.engine.definition.ApiSpec; +import io.gravitee.apim.core.analytics.model.engine.definition.FacetSpec; +import io.gravitee.apim.core.analytics.model.engine.definition.FilterSpec; +import io.gravitee.apim.core.analytics.model.engine.definition.MetricSpec; +import java.util.List; +import org.springframework.stereotype.Service; + +@Service +public class AnalyticsDefinitionDomainServiceImpl implements AnalyticsDefinition { + + private static final String ANALYTICS_DEFINITION_FILE = "analytics/definition/analytics-definition.yaml"; + + private static final YAMLMapper YAML = new YAMLMapper(); + + private final AnalyticsDefinitionSpec spec; + + public AnalyticsDefinitionDomainServiceImpl() { + spec = readYAMLDefinition().spec(); + } + + private static io.gravitee.apim.core.analytics.model.engine.definition.AnalyticsDefinition readYAMLDefinition() { + try { + return YAML.readValue( + AnalyticsDefinitionDomainServiceImpl.class.getClassLoader().getResourceAsStream(ANALYTICS_DEFINITION_FILE), + io.gravitee.apim.core.analytics.model.engine.definition.AnalyticsDefinition.class + ); + } catch (Exception e) { + throw new IllegalStateException("Unable to read analytics definition file", e); + } + } + + @Override + public List getApis() { + return spec.apis(); + } + + @Override + public List getMetrics(ApiSpec.Name apiSpecName) { + return spec + .metrics() + .stream() + .filter(metric -> metric.apis().contains(apiSpecName)) + .toList(); + } + + @Override + public List getFilters(MetricSpec.Name metricSpecName) { + var metric = getMetricByName(metricSpecName); + return spec + .filters() + .stream() + .filter(filter -> metric.filters().contains(filter.name())) + .toList(); + } + + @Override + public List getFacets(MetricSpec.Name metricSpecName) { + var metric = getMetricByName(metricSpecName); + return spec + .facets() + .stream() + .filter(facet -> metric.facets().contains(facet.name())) + .toList(); + } + + private MetricSpec getMetricByName(MetricSpec.Name metricSpecName) { + return spec + .metrics() + .stream() + .filter(metric -> metric.name().equals(metricSpecName)) + .findFirst() + .orElse(null); + } +} diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/definition/analytics-definition.yaml b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/definition/analytics-definition.yaml index 5b490c3d9d1..e517b46ead0 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/definition/analytics-definition.yaml +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/definition/analytics-definition.yaml @@ -12,1647 +12,1258 @@ spec: label: MCP metrics: - intervals: - - auto - values: - - name: HTTP_REQUESTS - label: HTTP Requests - apis: - - HTTP_PROXY - - LLM - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - backend: - elasticsearch: - indices: - - v4-metrics - type: document - - - name: HTTP_ERROR_RATE - label: Error Rate - apis: - - HTTP_PROXY - - LLM - type: gauge - unit: percent - aggregations: [] - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - backend: - elasticsearch: - indices: - - v4-metrics - type: document - - - name: HTTP_REQUEST_CONTENT_LENGTH - label: Request content length - apis: - - HTTP_PROXY - - LLM - type: gauge - unit: bytes - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - backend: - elasticsearch: - indices: - - v4-metrics - - requests - type: document - field: request-content-length - - - name: HTTP_RESPONSE_CONTENT_LENGTH - label: Response content length - apis: - - HTTP_PROXY - - LLM - type: gauge - unit: bytes - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - backend: - elasticsearch: - indices: - - v4-metrics - type: document - field: request-content-length - - - name: HTTP_ENDPOINT_RESPONSE_TIME - label: Endpoint response time - apis: - - HTTP_PROXY - - LLM - type: gauge - unit: ms - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - backend: - elasticsearch: - indices: - - v4-metrics - type: document - field: endpoint-response-time-ms - - - name: HTTP_GATEWAY_RESPONSE_TIME - label: Gateway response time - apis: - - HTTP_PROXY - - LLM - type: gauge - unit: ms - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - backend: - elasticsearch: - indices: - - v4-metrics - type: document - field: gateway-response-time-ms - - - name: HTTP_GATEWAY_LATENCY - label: Latency - apis: - - HTTP_PROXY - - LLM - type: gauge - unit: ms - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - backend: - elasticsearch: - indices: - - v4-metrics - type: document - field: gateway-latency-ms - - - name: LLM_PROMPT_TOKEN_SENT - label: Sent token count - apis: - - LLM - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - LLM_PROMPT_TOKEN_SENT - - LLM_PROMPT_TOKEN_RECEIVED - - LLM_PROMPT_TOKEN_SENT_COST - - LLM_PROMPT_TOKEN_RECEIVED_COST - backend: - elasticsearch: - indices: - - v4-metrics - type: document - countWith: - field: additional-metrics.long_ai-prompt-token-sent - method: sum - - - name: LLM_PROMPT_TOKEN_RECEIVED - label: Received token count - apis: - - LLM - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - LLM_PROMPT_TOKEN_SENT - - LLM_PROMPT_TOKEN_RECEIVED - - LLM_PROMPT_TOKEN_SENT_COST - - LLM_PROMPT_TOKEN_RECEIVED_COST - backend: - elasticsearch: - indices: - - v4-metrics - type: document - countWith: - field: additional-metrics.long_ai-prompt-token-receive - method: sum - - - name: LLM_PROMPT_TOKEN_SENT_COST - label: Sent token cost - apis: - - LLM - type: gauge - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - LLM_PROMPT_TOKEN_SENT - - LLM_PROMPT_TOKEN_RECEIVED - - LLM_PROMPT_TOKEN_SENT_COST - - LLM_PROMPT_TOKEN_RECEIVED_COST - backend: - elasticsearch: - indices: - - v4-metrics - type: document - field: additional-metrics.double_ai-prompt-token-sent-cost - - - name: LLM_PROMPT_TOKEN_RECEIVED_COST - label: Received token cost - apis: - - LLM - type: gauge - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HTTP_GATEWAY_LATENCY - - HTTP_GATEWAY_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - LLM_PROMPT_TOKEN_SENT - - LLM_PROMPT_TOKEN_RECEIVED - - LLM_PROMPT_TOKEN_SENT_COST - - LLM_PROMPT_TOKEN_RECEIVED_COST - backend: - elasticsearch: - indices: - - v4-metrics - type: document - field: additional-metrics.double_ai-prompt-token-receive-cost - - - name: MESSAGE_PAYLOAD_SIZE - label: Message Payload Size - apis: - - MESSAGE - type: gauge - unit: bytes - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - - MESSAGE_ERROR_COUNT - - MESSAGE_COUNT - - MESSAGE_GATEWAY_LATENCY - backend: - elasticsearch: - indices: - - v4-message-metrics - type: document - field: content-length - joinFacets: - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - followIndex: v4-metrics - correlationField: request-id - - - name: MESSAGES - label: Message count - apis: - - MESSAGE - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HTTP_ENDPOINT_RESPONSE_TIME - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - - MESSAGE_ERROR_COUNT - - MESSAGE_COUNT - - MESSAGE_GATEWAY_LATENCY - backend: - elasticsearch: - indices: - - v4-message-metrics - type: document - countWith: - field: count-increment - method: sum - joinFacets: - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - followIndex: v4-metrics - correlationField: request-id - - - name: MESSAGE_ERRORS - label: Message Error Count - apis: - - MESSAGE - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - - MESSAGE_ERROR_COUNT - - MESSAGE_COUNT - - MESSAGE_GATEWAY_LATENCY - backend: - elasticsearch: - indices: - - v4-message-metrics - type: document - countWith: - field: error-count-increment - method: sum - joinFacets: - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - followIndex: v4-metrics - correlationField: request-id - - - name: MESSAGE_GATEWAY_LATENCY - label: Message processing time - apis: - - MESSAGE - type: gauge - unit: ms - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - - MESSAGE_CONNECTOR_ID - - MESSAGE_CONNECTOR_TYPE - - MESSAGE_OPERATION_TYPE - - MESSAGE_ERROR_COUNT - - MESSAGE_COUNT - - MESSAGE_GATEWAY_LATENCY - backend: - elasticsearch: - indices: - - v4-message-metrics - type: document - field: gateway-latency-ms - joinFacets: - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - TENANT - - ZONE - - HTTP_METHOD - - HTTP_STATUS_CODE_GROUP - - HTTP_STATUS - - HTTP_PATH - - HTTP_PATH_MAPPING - - HTTP_USER_AGENT_OS_NAME - - HTTP_USER_AGENT_DEVICE - - HOST - - GEO_IP_COUNTRY - - GEO_IP_REGION - - GEO_IP_CITY - - GEO_IP_CONTINENT - - CONSUMER_IP - followIndex: v4-metrics - correlationField: request-id - - - name: KAFKA_DOWNSTREAM_PUBLISH_MESSAGES - label: Downstream Publish Messages - apis: - - KAFKA - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: downstream-publish-messages-total - - - name: KAFKA_DOWNSTREAM_SUBSCRIBE_MESSAGES - label: Downstream Subscribe Messages - apis: - - KAFKA - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - - - name: KAFKA_DOWNSTREAM_PUBLISH_MESSAGES_BYTES - label: Downstream Publish Message Bytes - apis: - - KAFKA - type: gauge - unit: bytes - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: downstream-publish-messages-bytes - - - name: KAFKA_DOWNSTREAM_SUBSCRIBE_MESSAGE_BYTES - label: Downstream Subscribe Message Bytes - apis: - - KAFKA - type: gauge - unit: bytes - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: downstream-subscribe-messages-bytes - - - name: KAFKA_UPSTREAM_PUBLISH_MESSAGES - label: Upstream Publish Messages - apis: - - KAFKA - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-publish-messages-total - - - name: KAFKA_UPSTREAM_SUBSCRIBE_MESSAGES - label: Upstream Subscribe Messages - apis: - - KAFKA - type: counter - aggregations: - - COUNT - - RPS - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-subscribe-messages-total - - - name: KAFKA_UPSTREAM_PUBLISH_MESSAGE_BYTES - label: Upstream Publish Message Bytes - apis: - - KAFKA - type: gauge - unit: bytes - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-publish-message-bytes - - - name: KAFKA_UPSTREAM_SUBSCRIBE_MESSAGE_BYTES - label: Upstream Subscribe Message Bytes - apis: - - KAFKA - type: gauge - unit: bytes - aggregations: - - AVG - - MIN - - MAX - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - - KAFKA_TOPIC - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-subscribe-message-bytes - - - name: KAFKA_DOWNSTREAM_AUTHENTICATION_SUCCESSES - label: Downstream Authentication Successes - apis: - - KAFKA - type: counter - aggregations: - - COUNT - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: downstream-authentication-successes-total - - - name: KAFKA_DOWNSTREAM_AUTHENTICATED_CONNECTIONS - label: Downstream Authenticated Connections - apis: - - KAFKA - type: gauge - aggregations: - - MAX - - AVG - - MIN - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: downstream-authenticated-connections - - - name: KAFKA_UPSTREAM_AUTHENTICATION_SUCCESSES - label: Upstream Authentication Successes - apis: - - KAFKA - type: counter - aggregations: - - COUNT - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-authentication-successes-total - - - name: KAFKA_UPSTREAM_AUTHENTICATED_CONNECTIONS - label: Upstream Authenticated Connections - apis: - - KAFKA - type: gauge - aggregations: - - MAX - - MIN - - AVG - - P50 - - P90 - - P95 - - P99 - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-authenticated-connections - - - name: KAFKA_UPSTREAM_AUTHENTICATION_ERRORS - label: Upstream Authentication Errors - apis: - - KAFKA - type: counter - aggregations: - - COUNT - facets: - - API - - APPLICATION - - PLAN - - GATEWAY - filter: - - API - - APPLICATION - - PLAN - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-authentication-failures-total - - - name: KAFKA_DOWNSTREAM_AUTHENTICATION_ERRORS - label: Downstream Authentication Errors - apis: - - KAFKA - type: counter - aggregations: - - COUNT - facets: - - API - - GATEWAY - filter: - - API - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: downstream-authentication-failures-total - - - name: KAFKA_DOWNSTREAM_ACTIVE_CONNECTIONS - label: Downstream Active Connections - apis: - - KAFKA - type: gauge - aggregations: - - MIN - - MAX - - AVG - - P50 - - P90 - - P95 - - P99 - facets: - - API - - GATEWAY - filter: - - API - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: downstream-active-connections - - - name: KAFKA_UPSTREAM_ACTIVE_CONNECTIONS - label: Upstream Active Connections - apis: - - KAFKA - type: gauge - aggregations: - - MIN - - MAX - - AVG - - P50 - - P90 - - P95 - - P99 - facets: - - API - - GATEWAY - filter: - - API - - GATEWAY - backend: - elasticsearch: - indices: - - event-metrics - type: data-stream - field: upstream-active-connections - - - name: SUBSCRIPTIONS - label: Subscriptions Count - apis: - - HTTP_PROXY - - MESSAGE - - KAFKA - - LLM - - MCP - type: counter - aggregations: - - COUNT - facets: - - API - - APPLICATION - filter: - - API - - APPLICATION - backend: - mongodb: - collection: subscriptions - timestampField: createdAt - groupWith: - - facet: API - field: api - - facet: APPLICATION - field: application - filterWith: - - facet: API - field: api - - facet: APPLICATION - field: application - additionalFilters: - - and: - - or: - - status: ACCEPTED - - status: RESUMED - - consummerStatus: STARTED - - - name: APIS - label: APIs - apis: - - HTTP_PROXY - - MESSAGE - - KAFKA - - LLM - - MCP - type: counter - aggregations: - - COUNT - facets: - - API_STATE - - API_LIFECYCLE_STATE - - API_VISIBILITY - filter: - - API_STATE - - API_LIFECYCLE_STATE - - API_VISIBILITY - backend: - mongodb: - collection: apis - frameTimeWith: - lower: createdAt - upper: createdAt - groupWith: - - facet: API_LIFECYCLE_STATE - field: apiLifecycleState - - facet: API_VISIBILITY - field: visibility - filterWith: - - facet: API_LIFECYCLE_STATE - field: apiLifecycleState - - facet: API_VISIBILITY - field: visibility - additionalFilters: [] + - name: HTTP_REQUESTS + label: HTTP Requests + apis: + - HTTP_PROXY + - LLM + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: HTTP_ERRORS + label: Error Rate + apis: + - HTTP_PROXY + - LLM + type: GAUGE + unit: NUMBER + measures: + - PERCENTAGE + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: HTTP_REQUEST_CONTENT_LENGTH + label: Request content length + apis: + - HTTP_PROXY + - LLM + type: GAUGE + unit: BYTES + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: HTTP_RESPONSE_CONTENT_LENGTH + label: Response content length + apis: + - HTTP_PROXY + - LLM + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + type: GAUGE + unit: BYTES + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: HTTP_ENDPOINT_RESPONSE_TIME + label: Endpoint response time + apis: + - HTTP_PROXY + - LLM + type: GAUGE + unit: MILLISECONDS + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: HTTP_GATEWAY_RESPONSE_TIME + label: Gateway response time + apis: + - HTTP_PROXY + - LLM + type: GAUGE + unit: MILLISECONDS + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: HTTP_GATEWAY_LATENCY + label: Latency + type: GAUGE + unit: MILLISECONDS + apis: + - HTTP_PROXY + - LLM + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: LLM_PROMPT_TOKEN_SENT + label: Sent token count + apis: + - LLM + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + + - name: LLM_PROMPT_TOKEN_RECEIVED + label: Received token count + apis: + - LLM + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: LLM_PROMPT_TOKEN_SENT_COST + label: Sent token cost + apis: + - LLM + type: GAUGE + unit: NUMBER + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: LLM_PROMPT_TOKEN_RECEIVED_COST + label: Received token cost + apis: + - LLM + type: GAUGE + unit: NUMBER + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HTTP_GATEWAY_LATENCY + - HTTP_GATEWAY_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + + - name: MESSAGE_PAYLOAD_SIZE + label: Message Payload Size + apis: + - MESSAGE + type: GAUGE + unit: BYTES + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + + - name: MESSAGES + label: Message count + apis: + - MESSAGE + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HTTP_ENDPOINT_RESPONSE_TIME + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + + - name: MESSAGE_ERRORS + label: Message Error Count + apis: + - MESSAGE + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + + - name: MESSAGE_GATEWAY_LATENCY + type: GAUGE + unit: MILLISECONDS + label: Message processing time + apis: + - MESSAGE + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_METHOD + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - TENANT + - ZONE + - HTTP_STATUS_CODE_GROUP + - HTTP_STATUS + - HTTP_PATH + - HTTP_PATH_MAPPING + - HTTP_USER_AGENT_OS_NAME + - HTTP_USER_AGENT_DEVICE + - HOST + - GEO_IP_COUNTRY + - GEO_IP_REGION + - GEO_IP_CITY + - GEO_IP_CONTINENT + - CONSUMER_IP + - MESSAGE_CONNECTOR_TYPE + - MESSAGE_OPERATION_TYPE + + - name: KAFKA_DOWNSTREAM_PUBLISH_MESSAGES + label: Downstream Publish Messages + apis: + - KAFKA + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + + - name: KAFKA_DOWNSTREAM_SUBSCRIBE_MESSAGES + label: Downstream Subscribe Messages + apis: + - KAFKA + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + - name: KAFKA_DOWNSTREAM_PUBLISH_MESSAGES_BYTES + label: Downstream Publish Message Bytes + apis: + - KAFKA + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + + - name: KAFKA_DOWNSTREAM_SUBSCRIBE_MESSAGE_BYTES + label: Downstream Subscribe Message Bytes + apis: + - KAFKA + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + type: GAUGE + unit: BYTES + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + + - name: KAFKA_UPSTREAM_PUBLISH_MESSAGES + label: Upstream Publish Messages + apis: + - KAFKA + type: COUNTER + measures: + - COUNT + - RPS + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + + - name: KAFKA_UPSTREAM_SUBSCRIBE_MESSAGES + label: Upstream Subscribe Messages + apis: + - KAFKA + measures: + - COUNT + - RPS + type: COUNTER + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + + - name: KAFKA_UPSTREAM_PUBLISH_MESSAGE_BYTES + label: Upstream Publish Message Bytes + apis: + - KAFKA + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + + - name: KAFKA_UPSTREAM_SUBSCRIBE_MESSAGE_BYTES + label: Upstream Subscribe Message Bytes + apis: + - KAFKA + type: GAUGE + unit: BYTES + measures: + - AVG + - MIN + - MAX + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + - KAFKA_TOPIC + + - name: KAFKA_DOWNSTREAM_AUTHENTICATION_SUCCESSES + label: Downstream Authentication Successes + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - COUNT + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + + - name: KAFKA_DOWNSTREAM_AUTHENTICATED_CONNECTIONS + label: Downstream Authenticated Connections + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - MAX + - AVG + - MIN + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + + - name: KAFKA_UPSTREAM_AUTHENTICATION_SUCCESSES + label: Upstream Authentication Successes + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - COUNT + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + + - name: KAFKA_UPSTREAM_AUTHENTICATED_CONNECTIONS + label: Upstream Authenticated Connections + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - MAX + - MIN + - AVG + - P90 + - P95 + - P99 + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + + - name: KAFKA_UPSTREAM_AUTHENTICATION_ERRORS + label: Upstream Authentication Errors + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - COUNT + facets: + - API + - APPLICATION + - PLAN + - GATEWAY + filters: + - API + - APPLICATION + - PLAN + - GATEWAY + + - name: KAFKA_DOWNSTREAM_AUTHENTICATION_ERRORS + label: Downstream Authentication Errors + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - COUNT + facets: + - API + - GATEWAY + filters: + - API + - GATEWAY + + - name: KAFKA_DOWNSTREAM_ACTIVE_CONNECTIONS + label: Downstream Active Connections + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - MIN + - MAX + - AVG + - P90 + - P95 + - P99 + facets: + - API + - GATEWAY + filters: + - API + - GATEWAY + + - name: KAFKA_UPSTREAM_ACTIVE_CONNECTIONS + label: Upstream Active Connections + apis: + - KAFKA + type: GAUGE + unit: NUMBER + measures: + - MIN + - MAX + - AVG + - P90 + - P95 + - P99 + facets: + - API + - GATEWAY + filters: + - API + - GATEWAY + + - name: SUBSCRIPTIONS + label: Subscriptions Count + apis: + - HTTP_PROXY + - MESSAGE + - KAFKA + - LLM + - MCP + type: COUNTER + measures: + - COUNT + facets: + - API + - APPLICATION + filters: + - API + - APPLICATION + + - name: APIS + label: APIs + apis: + - HTTP_PROXY + - MESSAGE + - KAFKA + - LLM + - MCP + type: COUNTER + measures: + - COUNT + facets: + - API_STATE + - API_LIFECYCLE_STATE + - API_VISIBILITY + filters: + - API_STATE + - API_LIFECYCLE_STATE + - API_VISIBILITY filters: - name: API label: API - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: api-id - name: APPLICATION label: Application - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: application-id - name: PLAN label: Plan - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: plan-id - name: GATEWAY label: Gateway - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: gateway - name: TENANT label: Tenant - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: tenant - name: ZONE label: Zone - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: zone - name: HTTP_METHOD label: HTTP Method - type: enum - enum: + type: ENUM + enumValues: - CONNECT - DELETE - GET @@ -1666,35 +1277,11 @@ spec: operators: - EQ - IN - backend: - elasticsearch: - field: http-method - valueMapping: - CONNECT: - value: 1 - DELETE: - value: 2 - GET: - value: 3 - HEAD: - value: 4 - OPTIONS: - value: 5 - PATCH: - value: 6 - POST: - value: 7 - PUT: - value: 8 - TRACE: - value: 9 - OTHER: - value: 0 - name: HTTP_STATUS_CODE_GROUP label: Status Code Group - type: enum - enum: + type: ENUM + enumValues: - 1xx - 2xx - 3xx @@ -1703,30 +1290,10 @@ spec: operators: - EQ - IN - backend: - elasticsearch: - field: status - valueMapping: - 1xx: - range: - gte: 100 - lte: 199 - 2xx: - range: - gte: 200 - lte: 299 - 3xx: - range: - gte: 300 - lte: 399 - 4xx: - range: - gte: 400 - lte: 499 - name: HTTP_STATUS label: Status Code - type: integer + type: NUMBER range: min: 100 max: 600 @@ -1734,631 +1301,292 @@ spec: - EQ - LTE - GTE - backend: - elasticsearch: - field: status - name: HTTP_PATH label: HTTP Path - type: string + type: STRING operators: - EQ - IN - backend: - elasticsearch: - field: path-info - - name: HTTP_PATH_MAPPING label: Path Mapping - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: mapped-path - name: HOST label: Host - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: host - name: GEO_IP_COUNTRY label: Country - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: geoip.country_iso_code - name: GEO_IP_REGION label: Region - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: geoip.region_name - name: GEO_IP_CITY label: City - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: geoip.city_name - name: GEO_IP_CONTINENT label: Continent - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: geoip.continent_name - name: CONSUMER_IP label: Consumer IP - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: remote-address - name: HTTP_USER_AGENT_OS_NAME label: User Agent OS - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: user_agent.os.name - name: HTTP_USER_AGENT_DEVICE label: User Agent Device - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: user_agent.device.name - name: MESSAGE_CONNECTOR_TYPE label: Connector Type - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: connector-type - name: MESSAGE_OPERATION_TYPE label: Operation - type: enum - enum: + type: ENUM + enumValues: - Publish - Subscribe operators: - EQ - IN - backend: - elasticsearch: - field: operation - valueMapping: - Publish: - value: publish - Subscribe: - value: subscribe - name: KAFKA_TOPIC label: Topic - type: keyword + type: KEYWORD operators: - EQ - IN - backend: - elasticsearch: - field: topic - name: API_STATE label: API State - type: enum - enum: + type: ENUM + enumValues: - STARTED - STOPPED operators: - EQ - IN - backend: - mongodb: - collection: apis - field: lifecycleState - name: API_LIFECYCLE_STATE label: API Lifecycle State - type: enum - enum: + type: ENUM + enumValues: - PUBLISHED - UNPUBLISHED - DEPRECATED operators: - EQ - IN - backend: - mongodb: - collection: apis - field: apiLifecycleState - valueMapping: - PUBLISHED: - value: PUBLISHED - UNPUBLISHED: - values: - - UNPUBLISHED - - CREATED - DEPRECATED: - value: DEPRECATED - name: API_VISIBILITY label: API Visibility - type: enum - enum: + type: ENUM + enumValues: - PUBLIC - PRIVATE operators: - EQ - IN - backend: - mongodb: - collection: apis - field: visibility - valueMapping: - PUBLISHED: - value: PUBLISHED - PRIVATE: - value: PRIVATE - name: MESSAGE_SIZE label: Message Size - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: content-length - name: MESSAGE_COUNT label: Message Count - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: count - name: MESSAGE_ERROR_COUNT label: Errors - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: error-count - name: HTTP_ENDPOINT_RESPONSE_TIME label: Endpoint Response Time - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: endpoint-response-time-ms - name: HTTP_GATEWAY_LATENCY label: Latency - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: gateway-latency-ms - name: HTTP_GATEWAY_RESPONSE_TIME label: Gateway Response Time - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: gateway-response-time-ms - name: HTTP_REQUEST_CONTENT_LENGTH label: Request Size - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: request-content-length - name: HTTP_RESPONSE_CONTENT_LENGTH label: Response Size - type: long + type: NUMBER operators: - EQ - LTE - GTE - backend: - elasticsearch: - field: response-content-length - facets: - name: API label: API - type: keyword - backend: - elasticsearch: - field: api-id + type: KEYWORD - name: APPLICATION label: Application - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: application-id + type: KEYWORD - name: PLAN label: Plan - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: plan-id + type: KEYWORD - name: GATEWAY label: Gateway - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: gateway + type: KEYWORD - name: TENANT label: Tenant - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: tenant + type: KEYWORD - name: ZONE label: Zone - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: zone + type: KEYWORD - name: HTTP_METHOD label: HTTP Method - type: enum - enum: - - CONNECT - - DELETE - - GET - - HEAD - - OPTIONS - - PATCH - - POST - - PUT - - TRACE - - OTHER - operators: - - EQ - - IN - backend: - elasticsearch: - field: http-method - valueMapping: - CONNECT: - value: 1 - DELETE: - value: 2 - GET: - value: 3 - HEAD: - value: 4 - OPTIONS: - value: 5 - PATCH: - value: 6 - POST: - value: 7 - PUT: - value: 8 - TRACE: - value: 9 - OTHER: - value: 0 + type: KEYWORD - name: HTTP_STATUS_CODE_GROUP label: Status Code Group - type: enum - enum: - - 1xx - - 2xx - - 3xx - - 4xx - - 5xx - operators: - - EQ - - IN - backend: - elasticsearch: - field: status - valueMapping: - 1xx: - range: - gte: 100 - lte: 199 - 2xx: - range: - gte: 200 - lte: 299 - 3xx: - range: - gte: 300 - lte: 399 - 4xx: - range: - gte: 400 - lte: 499 + type: KEYWORD - name: HTTP_STATUS label: Status Code - type: integer - range: - min: 100 - max: 600 - operators: - - EQ - - LTE - - GTE - backend: - elasticsearch: - field: status + type: NUMBER - name: HTTP_PATH label: HTTP Path - type: string - operators: - - EQ - - IN - backend: - elasticsearch: - field: path-info + type: STRING - name: HTTP_PATH_MAPPING label: Path Mapping - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: mapped-path + type: KEYWORD - name: HOST label: Host - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: host + type: KEYWORD - name: GEO_IP_COUNTRY label: Country - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: geoip.country_iso_code + type: KEYWORD - name: GEO_IP_REGION label: Region - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: geoip.region_name + type: KEYWORD - name: GEO_IP_CITY label: City - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: geoip.city_name + type: KEYWORD - name: GEO_IP_CONTINENT label: Continent - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: geoip.continent_name + type: KEYWORD - name: CONSUMER_IP label: Consumer IP - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: remote-address + type: KEYWORD - name: HTTP_USER_AGENT_OS_NAME label: User Agent OS - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: user_agent.os.name + type: KEYWORD - name: HTTP_USER_AGENT_DEVICE label: User Agent Device - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: user_agent.device.name + type: KEYWORD - name: MESSAGE_CONNECTOR_TYPE label: Connector Type - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: connector-type + type: KEYWORD - name: MESSAGE_OPERATION_TYPE label: Operation - type: enum - enum: - - Publish - - Subscribe - operators: - - EQ - - IN - backend: - elasticsearch: - field: operation - valueMapping: - Publish: - value: publish - Subscribe: - value: subscribe + type: KEYWORD - name: KAFKA_TOPIC label: Topic - type: keyword - operators: - - EQ - - IN - backend: - elasticsearch: - field: topic + type: KEYWORD - name: API_STATE label: API State - type: enum - enum: - - STARTED - - STOPPED - operators: - - EQ - - IN - backend: - mongodb: - collection: apis - field: lifecycleState + type: KEYWORD - name: API_LIFECYCLE_STATE label: API Lifecycle State - type: enum - enum: - - PUBLISHED - - UNPUBLISHED - - DEPRECATED - operators: - - EQ - - IN - backend: - mongodb: - collection: apis - field: apiLifecycleState - valueMapping: - PUBLISHED: - value: PUBLISHED - UNPUBLISHED: - values: - - UNPUBLISHED - - CREATED - DEPRECATED: - value: DEPRECATED + type: KEYWORD - name: API_VISIBILITY label: API Visibility - type: enum - enum: - - PUBLIC - - PRIVATE - operators: - - EQ - - IN - backend: - mongodb: - collection: apis - field: visibility - valueMapping: - PUBLISHED: - value: PUBLISHED - PRIVATE: - value: PRIVATE + type: KEYWORD + diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/request.json new file mode 100644 index 00000000000..2695ad0a75e --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/request.json @@ -0,0 +1,31 @@ +{ + "timeRange": { + "from": "2025-01-01T00:00:00Z", + "to": "2025-01-31T23:59:59Z" + }, + "filters": [ + { + "name": "API", + "operator": "EQ", + "value": "8528bd43-c264-4719-8d9e-ad8afb34ce71" + } + ], + "by": [ + "API" + ], + "metrics": [ + { + "name": "HTTP_ERRORS", + "measures": [ + "PERCENTAGE" + ], + "filters": [ + { + "name": "TENANT", + "operator": "EQ", + "value": "europe" + } + ] + } + ] +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/response.json new file mode 100644 index 00000000000..05cdebf9514 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-error-rate-per-api/response.json @@ -0,0 +1,27 @@ +{ + "metrics": [ + { + "name": "HTTP_ERRORS", + "buckets": [ + { + "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", + "measures": [ + { + "name": "PERCENTAGE", + "value": 1 + } + ] + }, + { + "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", + "measures": [ + { + "name": "PERCENTAGE", + "value": 45.9 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/request.json index 1094b046571..77aea16218d 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/request.json @@ -10,8 +10,9 @@ "value": "8528bd43-c264-4719-8d9e-ad8afb34ce71" } ], - "by": ["API"], - "aggregations": ["COUNT"], + "by": [ + "API" + ], "order": { "measure": "COUNT", "direction": "DESC" @@ -20,6 +21,9 @@ "metrics": [ { "name": "HTTP_REQUESTS", + "measures": [ + "COUNT" + ], "filters": [ { "name": "TENANT", @@ -29,4 +33,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/response.json index e360356f15f..8f15c1d6b73 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api-top-five/response.json @@ -1,39 +1,54 @@ { "metrics": [ { - "name": "HTTP_REQUEST_COUNT", + "name": "HTTP_REQUESTS", "buckets": [ { "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", - "measures": { - "COUNT": 1234 - } + "measures": [ + { + "name": "COUNT", + "value": 1234 + } + ] }, { "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", - "measures": { - "COUNT": 989 - } + "measures": [ + { + "name": "COUNT", + "value": 989 + } + ] }, { "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", - "measures": { - "COUNT": 890 - } + "measures": [ + { + "name": "COUNT", + "value": 890 + } + ] }, { "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", - "measures": { - "COUNT": 789 - } + "measures": [ + { + "name": "COUNT", + "value": 789 + } + ] }, { "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", - "measures": { - "COUNT": 678 - } + "measures": [ + { + "name": "COUNT", + "value": 678 + } + ] } ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/request.json index d37554ce0dd..cb904b7285f 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/request.json @@ -10,12 +10,15 @@ "value": "8528bd43-c264-4719-8d9e-ad8afb34ce71" } ], - "by": ["API"], - "aggregations": ["COUNT"], + "by": [ + "API" + ], "metrics": [ { "name": "HTTP_REQUESTS", - "aggregations": ["COUNT"], + "measures": [ + "COUNT" + ], "filters": [ { "name": "TENANT", @@ -25,4 +28,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/response.json index a7db3a9adb3..1548e00f92e 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-request-count-per-api/response.json @@ -5,17 +5,23 @@ "buckets": [ { "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", - "measures": { - "COUNT": 1234 - } + "measures": [ + { + "name": "COUNT", + "value": 1234 + } + ] }, { "key": "8528bd43-c264-4719-8d9e-ad8afb34ce71", - "measures": { - "COUNT": 989 - } + "measures": [ + { + "name": "COUNT", + "value": 989 + } + ] } ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/request.json index 0a3db86d62d..854f997dff5 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/request.json @@ -3,11 +3,16 @@ "from": "2025-01-01T00:00:00Z", "to": "2025-01-31T23:59:59Z" }, - "by": ["API", "APPLICATION"], + "by": [ + "API", + "APPLICATION" + ], "metrics": [ { "name": "HTTP_REQUESTS", - "aggregations": ["RPS"], + "measures": [ + "RPS" + ], "filters": [ { "name": "TENANT", @@ -17,4 +22,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/response.json index bcc06c43c0a..31b2ee9076b 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/facets-http-rps-by-api-and-application/response.json @@ -1,22 +1,28 @@ { "metrics": [ { - "name": "HTTP_REQUEST_COUNT", + "name": "HTTP_REQUESTS", "buckets": [ { "key": "9b024d99-3265-4476-9bea-760d2240d99d", "buckets": [ { "key": "8ff7124d-e927-458f-86e6-996dd5f3910c", - "measures": { - "RPS": 45.7 - } + "measures": [ + { + "name": "RPS", + "value": 45.7 + } + ] }, { "key": "91223d08-02db-4f61-8b84-7f443f6bda8e", - "measures": { - "RPS": 34.9 - } + "measures": [ + { + "name": "RPS", + "value": 34.9 + } + ] } ] }, @@ -25,19 +31,25 @@ "buckets": [ { "key": "a3437e53-80a8-473f-ab81-d53c0eb1ed58", - "measures": { - "RPS": 74.3 - } + "measures": [ + { + "name": "RPS", + "value": 74.3 + } + ] }, { "key": "f6f03431-2683-45c5-ac6e-888b2f1f81e4", - "measures": { - "RPS": 88.9 - } + "measures": [ + { + "name": "RPS", + "value": 88.9 + } + ] } ] } ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/request.json index f9bcde16d55..bac8bedef0d 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/request.json @@ -13,7 +13,11 @@ "metrics": [ { "name": "HTTP_GATEWAY_RESPONSE_TIME", - "aggregations": ["P90", "P95", "P99"], + "measures": [ + "P90", + "P95", + "P99" + ], "filters": [ { "name": "TENANT", @@ -23,4 +27,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/response.json index 0dfd28a80f6..0dd1cb09830 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-gateway-response-time-percentiles/response.json @@ -2,11 +2,20 @@ "metrics": [ { "name": "HTTP_GATEWAY_RESPONSE_TIME", - "measures": { - "P90": "89.9", - "P95": "95.1", - "P99": "123.4" - } + "measures": [ + { + "name": "P90", + "value": "89.9" + }, + { + "name": "P95", + "value": "95.1" + }, + { + "name": "P99", + "value": "123.4" + } + ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/request.json index a22b4aca740..abc0fa32f44 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/request.json @@ -13,7 +13,9 @@ "metrics": [ { "name": "HTTP_REQUESTS", - "aggregations": ["COUNT"], + "measures": [ + "COUNT" + ], "filters": [ { "name": "TENANT", @@ -23,4 +25,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/response.json index 749b5915807..80299691ac9 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/measures-http-request-count/response.json @@ -2,9 +2,12 @@ "metrics": [ { "name": "HTTP_REQUESTS", - "measures": { - "COUNT": 2984 - } + "measures": [ + { + "name": "COUNT", + "value": 2984 + } + ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/request.json index 53d8b68461f..d258f9b6883 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/request.json @@ -4,11 +4,15 @@ "to": "2025-01-31T23:59:59Z" }, "interval": "auto", - "by": ["API"], + "by": [ + "API" + ], "metrics": [ { "name": "HTTP_REQUESTS", - "aggregations": ["COUNT"], + "measures": [ + "COUNT" + ], "filters": [ { "name": "TENANT", @@ -18,4 +22,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/response.json index bb20ba55a24..e8ffd603cc0 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count-per-api/response.json @@ -3,7 +3,6 @@ "metrics": [ { "name": "HTTP_REQUESTS", - "buckets": [ { "key": "2025-01-01T00:00:00Z", @@ -11,15 +10,21 @@ "buckets": [ { "key": "a5954f6e-1d95-463a-9a41-2442c575d022", - "measures": { - "COUNT": 1234 - } + "measures": [ + { + "name": "COUNT", + "value": 1234 + } + ] }, { "key": "12bff449-1556-491c-8e34-c1c93b27e1cb", - "measures": { - "COUNT": 989 - } + "measures": [ + { + "name": "COUNT", + "value": 989 + } + ] } ] }, @@ -29,15 +34,21 @@ "buckets": [ { "key": "a5954f6e-1d95-463a-9a41-2442c575d022", - "measures": { - "COUNT": 873 - } + "measures": [ + { + "name": "COUNT", + "value": 873 + } + ] }, { "key": "12bff449-1556-491c-8e34-c1c93b27e1cb", - "measures": { - "COUNT": 938 - } + "measures": [ + { + "name": "COUNT", + "value": 938 + } + ] } ] }, @@ -47,15 +58,21 @@ "buckets": [ { "key": "a5954f6e-1d95-463a-9a41-2442c575d022", - "measures": { - "COUNT": 736 - } + "measures": [ + { + "name": "COUNT", + "value": 736 + } + ] }, { "key": "12bff449-1556-491c-8e34-c1c93b27e1cb", - "measures": { - "COUNT": 763 - } + "measures": [ + { + "name": "COUNT", + "value": 763 + } + ] } ] }, @@ -65,15 +82,21 @@ "buckets": [ { "key": "a5954f6e-1d95-463a-9a41-2442c575d022", - "measures": { - "COUNT": 938 - } + "measures": [ + { + "name": "COUNT", + "value": 938 + } + ] }, { "key": "12bff449-1556-491c-8e34-c1c93b27e1cb", - "measures": { - "COUNT": 2345 - } + "measures": [ + { + "name": "COUNT", + "value": 2345 + } + ] } ] }, @@ -83,15 +106,21 @@ "buckets": [ { "key": "a5954f6e-1d95-463a-9a41-2442c575d022", - "measures": { - "COUNT": 647 - } + "measures": [ + { + "name": "COUNT", + "value": 647 + } + ] }, { "key": "12bff449-1556-491c-8e34-c1c93b27e1cb", - "measures": { - "COUNT": 236 - } + "measures": [ + { + "name": "COUNT", + "value": 236 + } + ] } ] }, @@ -101,19 +130,25 @@ "buckets": [ { "key": "a5954f6e-1d95-463a-9a41-2442c575d022", - "measures": { - "COUNT": 764 - } + "measures": [ + { + "name": "COUNT", + "value": 764 + } + ] }, { "key": "12bff449-1556-491c-8e34-c1c93b27e1cb", - "measures": { - "COUNT": 236 - } + "measures": [ + { + "name": "COUNT", + "value": 236 + } + ] } ] } ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/request.json index 729965ed7c9..65f4dc27633 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/request.json @@ -14,7 +14,9 @@ "metrics": [ { "name": "HTTP_REQUESTS", - "aggregations": ["COUNT"], + "measures": [ + "COUNT" + ], "filters": [ { "name": "TENANT", @@ -24,4 +26,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/response.json index 563439e34a6..3ab6009cf5d 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-http-request-count/response.json @@ -7,46 +7,64 @@ { "key": "2025-01-01T00:00:00Z", "timestamp": 1735689600000, - "measures": { - "COUNT": 2984 - } + "measures": [ + { + "name": "COUNT", + "value": 2984 + } + ] }, { "key": "2025-01-01T00:01:00Z", "timestamp": 1735689660000, - "measures": { - "COUNT": 3000 - } + "measures": [ + { + "name": "COUNT", + "value": 3000 + } + ] }, { "key": "2025-01-01T00:02:00Z", "timestamp": 1735689720000, - "measures": { - "COUNT": 2888 - } + "measures": [ + { + "name": "COUNT", + "value": 2888 + } + ] }, { "key": "2025-01-01T00:03:00Z", "timestamp": 1735689780000, - "measures": { - "COUNT": 2999 - } + "measures": [ + { + "name": "COUNT", + "value": 2999 + } + ] }, { "key": "2025-01-01T00:04:00Z", "timestamp": 1735689840000, - "measures": { - "COUNT": 3001 - } + "measures": [ + { + "name": "COUNT", + "value": 3001 + } + ] }, { "key": "2025-01-01T00:05:00Z", "timestamp": 1735689900000, - "measures": { - "COUNT": 2984 - } + "measures": [ + { + "name": "COUNT", + "value": 2984 + } + ] } ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/request.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/request.json index 49e9025ac7c..6768c4e8337 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/request.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/request.json @@ -21,7 +21,11 @@ "value": "europe" } ], - "aggregations": ["P90", "P95", "P99"] + "measures": [ + "P90", + "P95", + "P99" + ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/response.json b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/response.json index e58eff7b24c..09796a8b8d7 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/response.json +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/mocks/time-series-latency-gateway-response-time-percentiles/response.json @@ -7,58 +7,112 @@ { "key": "2025-01-01T00:00:00Z", "timestamp": 1735689600000, - "measures": { - "P90": 89.9, - "P95": 95.1, - "P99": 123.4 - } + "measures": [ + { + "name": "P90", + "value": 89.9 + }, + { + "name": "P95", + "value": 95.1 + }, + { + "name": "P99", + "value": 123.4 + } + ] }, { "key": "2025-01-01T00:01:00Z", "timestamp": 1735689660000, - "measures": { - "P90": 90.1, - "P95": 95.2, - "P99": 123.5 - } + "measures": [ + { + "name": "P90", + "value": 90.1 + }, + { + "name": "P95", + "value": 95.2 + }, + { + "name": "P99", + "value": 123.5 + } + ] }, { "key": "2025-01-01T00:02:00Z", "timestamp": 1735689720000, - "measures": { - "P90": 90.2, - "P95": 95.3, - "P99": 123.6 - } + "measures": [ + { + "name": "P90", + "value": 90.2 + }, + { + "name": "P95", + "value": 95.3 + }, + { + "name": "P99", + "value": 123.6 + } + ] }, { "key": "2025-01-01T00:03:00Z", "timestamp": 1735689780000, - "measures": { - "P90": 90.3, - "P95": 95.4, - "P99": 123.7 - } + "measures": [ + { + "name": "P90", + "value": 90.3 + }, + { + "name": "P95", + "value": 95.4 + }, + { + "name": "P99", + "value": 123.7 + } + ] }, { "key": "2025-01-01T00:04:00Z", "timestamp": 1735689840000, - "measures": { - "P90": 90.4, - "P95": 95.5, - "P99": 123.8 - } + "measures": [ + { + "name": "P90", + "value": 90.4 + }, + { + "name": "P95", + "value": 95.5 + }, + { + "name": "P99", + "value": 123.8 + } + ] }, { "key": "2025-01-01T00:05:00Z", "timestamp": 1735689900000, - "measures": { - "P90": 90.5, - "P95": 95.6, - "P99": 123.9 - } + "measures": [ + { + "name": "P90", + "value": 90.5 + }, + { + "name": "P95", + "value": 95.6 + }, + { + "name": "P99", + "value": 123.9 + } + ] } ] } ] -} +} \ No newline at end of file diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/openapi-analytics.yaml b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/openapi-analytics.yaml new file mode 120000 index 00000000000..da62743555f --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/resources/analytics/openapi-analytics.yaml @@ -0,0 +1 @@ +/Users/antoine.cordier/src/gravitee/gravitee-api-management/gravitee-apim-rest-api/gravitee-apim-rest-api-management-v2/gravitee-apim-rest-api-management-v2-rest/src/main/resources/openapi/openapi-analytics.yaml \ No newline at end of file