From 9430ea767549d0ae5c232c4d905daf2d91c5ab56 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Tue, 19 Nov 2024 21:36:55 +0530 Subject: [PATCH 1/8] Add Ballerina metrics logs observer --- .../runtime/observability/ObserveUtils.java | 19 ++- .../metrics/BallerinaMetricsLogsObserver.java | 112 ++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java index 685add2c9219..567c91e38143 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java @@ -19,6 +19,7 @@ import io.ballerina.runtime.api.Environment; import io.ballerina.runtime.api.Module; +import io.ballerina.runtime.api.Runtime; import io.ballerina.runtime.api.types.ObjectType; import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.utils.StringUtils; @@ -72,6 +73,8 @@ public final class ObserveUtils { private static final BString metricsReporter; private static final boolean tracingEnabled; private static final BString tracingProvider; + private static final boolean metricsLogsEnabled; + private static final BString metricsLogsProvider; static { // TODO: Move config initialization to ballerina level once checking config key is possible at ballerina level @@ -88,13 +91,19 @@ public final class ObserveUtils { , false); VariableKey tracingProviderKey = new VariableKey(observeModule, "tracingProvider", PredefinedTypes.TYPE_STRING, false); + VariableKey metricsLogsEnabledKey = new VariableKey(observeModule, "metricsLogsEnabled", PredefinedTypes.TYPE_BOOLEAN + , false); + VariableKey metricsLogsProviderKey = new VariableKey(observeModule, "metricsLogsProvider", + PredefinedTypes.TYPE_STRING, false); metricsEnabled = readConfig(metricsEnabledKey, enabledKey, false); metricsProvider = readConfig(metricsProviderKey, null, StringUtils.fromString("default")); metricsReporter = readConfig(metricsReporterKey, providerKey, StringUtils.fromString("choreo")); tracingEnabled = readConfig(tracingEnabledKey, enabledKey, false); tracingProvider = readConfig(tracingProviderKey, providerKey, StringUtils.fromString("choreo")); - enabled = metricsEnabled || tracingEnabled; + metricsLogsEnabled = readConfig(metricsLogsEnabledKey, enabledKey, false); + metricsLogsProvider = readConfig(metricsLogsProviderKey, providerKey, StringUtils.fromString("choreo")); + enabled = metricsEnabled || tracingEnabled || metricsLogsEnabled; } private ObserveUtils() { @@ -136,6 +145,14 @@ public static BString getTracingProvider() { return tracingProvider; } + public static boolean isMetricsLogsEnabled() { + return metricsLogsEnabled; + } + + public static BString getMetricsLogsProvider() { + return metricsLogsProvider; + } + /** * Add metrics and tracing observers. * diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java new file mode 100644 index 000000000000..270b5a356d69 --- /dev/null +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java @@ -0,0 +1,112 @@ +package io.ballerina.runtime.observability.metrics; + +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.Module; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.observability.BallerinaObserver; +import io.ballerina.runtime.observability.ObserverContext; + +import java.io.PrintStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static io.ballerina.runtime.observability.ObservabilityConstants.*; + +public class BallerinaMetricsLogsObserver implements BallerinaObserver { + private static final String PROPERTY_START_TIME = "_observation_start_time_"; + private static final PrintStream consoleError = System.err; + + private static Environment environment; + + public BallerinaMetricsLogsObserver(Environment environment) { + BallerinaMetricsLogsObserver.environment = environment; + } + + @Override + public void startServerObservation(ObserverContext observerContext) { + } + + @Override + public void startClientObservation(ObserverContext observerContext) { + } + + @Override + public void stopServerObservation(ObserverContext observerContext) { + if (!observerContext.isStarted()) { + // Do not collect metrics if the observation hasn't started + return; + } + stopObservation(observerContext); + } + + @Override + public void stopClientObservation(ObserverContext observerContext) { + if (!observerContext.isStarted()) { + // Do not collect metrics if the observation hasn't started + return; + } + stopObservation(observerContext); + } + + private void stopObservation(ObserverContext observerContext) { + Set tags = new HashSet<>(); + Map customTags = observerContext.customMetricTags; + if (customTags != null) { + tags.addAll(customTags.values()); + } + tags.addAll(observerContext.getAllTags()); + + // Add status_code_group tag + Integer statusCode = (Integer) observerContext.getProperty(PROPERTY_KEY_HTTP_STATUS_CODE); + if (statusCode != null && statusCode > 0) { + tags.add(Tag.of(TAG_KEY_HTTP_STATUS_CODE_GROUP, (statusCode / 100) + STATUS_CODE_GROUP_SUFFIX)); + } + + try { + Long startTime = (Long) observerContext.getProperty(PROPERTY_START_TIME); + long duration = System.nanoTime() - startTime; + + Optional protocolValue = Optional.empty(); + if (tags.stream().anyMatch(tag -> tag.getKey().equals("protocol"))) { + protocolValue = tags.stream().filter(tag -> tag.getKey().equals("protocol")).map(Tag::getValue).findFirst(); + } + String protocol = protocolValue.orElse("http"); + + BMap logAttributes = ValueCreator.createMapValue(); + logAttributes.put(StringUtils.fromString("protocol"), StringUtils.fromString(protocol)); + tags.stream().filter(tag -> !tag.getKey().equals("protocol")) + .forEach(tag -> logAttributes.put(StringUtils.fromString(tag.getKey()), + StringUtils.fromString(tag.getValue()))); + logAttributes.put(StringUtils.fromString("response_time_seconds"), + StringUtils.fromString(String.valueOf(duration / 1E9))); + + printMetricLog(logAttributes); +// BString tempMessage = StringUtils.fromString("response_time_seconds: " + duration / 1E9); +// printLog(tempMessage); + } catch (RuntimeException e) { + handleError("multiple metrics", tags, e); + } + } + + private void handleError(String metricName, Set tags, RuntimeException e) { + // Metric Provider may throw exceptions if there is a mismatch in tags. + consoleError.println("error: error collecting metrics for " + metricName + " with tags " + tags + + ": " + e.getMessage()); + } + + private static void printMetricLog(BMap logAttributes) { + Module metricsLogsModule = new Module("ballerinax", "metrics.logs", "1"); + environment.getRuntime().callFunction(metricsLogsModule, "printMetricsLog", null, logAttributes); + } + + private static void printLog(BString message) { + Module metricsLogsModule = new Module("ballerinax", "metrics.logs", "1"); + environment.getRuntime().callFunction(metricsLogsModule, "printLog", null, message); + } +} From d7133b58e0ef25d41bf2a2461329a01f58aa80f5 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Wed, 20 Nov 2024 10:50:00 +0530 Subject: [PATCH 2/8] Add comments --- .../metrics/BallerinaMetricsLogsObserver.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java index 270b5a356d69..564b29f77463 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java @@ -7,10 +7,10 @@ import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.observability.BallerinaObserver; +import io.ballerina.runtime.observability.ObserveUtils; import io.ballerina.runtime.observability.ObserverContext; import java.io.PrintStream; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Optional; @@ -19,6 +19,7 @@ import static io.ballerina.runtime.observability.ObservabilityConstants.*; public class BallerinaMetricsLogsObserver implements BallerinaObserver { + private static final String ORG_NAME = "ballerinax"; private static final String PROPERTY_START_TIME = "_observation_start_time_"; private static final PrintStream consoleError = System.err; @@ -87,8 +88,6 @@ private void stopObservation(ObserverContext observerContext) { StringUtils.fromString(String.valueOf(duration / 1E9))); printMetricLog(logAttributes); -// BString tempMessage = StringUtils.fromString("response_time_seconds: " + duration / 1E9); -// printLog(tempMessage); } catch (RuntimeException e) { handleError("multiple metrics", tags, e); } @@ -101,12 +100,8 @@ private void handleError(String metricName, Set tags, RuntimeException e) { } private static void printMetricLog(BMap logAttributes) { - Module metricsLogsModule = new Module("ballerinax", "metrics.logs", "1"); + // TODO: Remove version when the API is finalized, and add the configured org name. + Module metricsLogsModule = new Module(ORG_NAME, ObserveUtils.getMetricsLogsProvider().getValue(), "1"); environment.getRuntime().callFunction(metricsLogsModule, "printMetricsLog", null, logAttributes); } - - private static void printLog(BString message) { - Module metricsLogsModule = new Module("ballerinax", "metrics.logs", "1"); - environment.getRuntime().callFunction(metricsLogsModule, "printLog", null, message); - } } From 80b44011aab3c0cb4506c25bb274f23d41408f44 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Wed, 20 Nov 2024 11:08:20 +0530 Subject: [PATCH 3/8] Resolve checkstyle errors --- .../observability/metrics/BallerinaMetricsLogsObserver.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java index 564b29f77463..c4f8c1023c71 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java @@ -16,7 +16,9 @@ import java.util.Optional; import java.util.Set; -import static io.ballerina.runtime.observability.ObservabilityConstants.*; +import static io.ballerina.runtime.observability.ObservabilityConstants.PROPERTY_KEY_HTTP_STATUS_CODE; +import static io.ballerina.runtime.observability.ObservabilityConstants.TAG_KEY_HTTP_STATUS_CODE_GROUP; +import static io.ballerina.runtime.observability.ObservabilityConstants.STATUS_CODE_GROUP_SUFFIX; public class BallerinaMetricsLogsObserver implements BallerinaObserver { private static final String ORG_NAME = "ballerinax"; From baf657013be50d62650602fe7ff6ef7bfbf91404 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Wed, 20 Nov 2024 14:12:44 +0530 Subject: [PATCH 4/8] Resolve checkstyle errors --- .../io/ballerina/runtime/observability/ObserveUtils.java | 5 ++--- .../observability/metrics/BallerinaMetricsLogsObserver.java | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java index 567c91e38143..ab773e90c508 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java @@ -19,7 +19,6 @@ import io.ballerina.runtime.api.Environment; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.Runtime; import io.ballerina.runtime.api.types.ObjectType; import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.utils.StringUtils; @@ -91,8 +90,8 @@ public final class ObserveUtils { , false); VariableKey tracingProviderKey = new VariableKey(observeModule, "tracingProvider", PredefinedTypes.TYPE_STRING, false); - VariableKey metricsLogsEnabledKey = new VariableKey(observeModule, "metricsLogsEnabled", PredefinedTypes.TYPE_BOOLEAN - , false); + VariableKey metricsLogsEnabledKey = new VariableKey(observeModule, "metricsLogsEnabled", + PredefinedTypes.TYPE_BOOLEAN, false); VariableKey metricsLogsProviderKey = new VariableKey(observeModule, "metricsLogsProvider", PredefinedTypes.TYPE_STRING, false); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java index c4f8c1023c71..a689af535305 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java @@ -77,7 +77,8 @@ private void stopObservation(ObserverContext observerContext) { Optional protocolValue = Optional.empty(); if (tags.stream().anyMatch(tag -> tag.getKey().equals("protocol"))) { - protocolValue = tags.stream().filter(tag -> tag.getKey().equals("protocol")).map(Tag::getValue).findFirst(); + protocolValue = tags.stream().filter(tag -> tag.getKey().equals("protocol")).map(Tag::getValue) + .findFirst(); } String protocol = protocolValue.orElse("http"); From 6a81b65406cb10ea5b8592fc331b247b6db7d0dd Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Thu, 21 Nov 2024 01:00:43 +0530 Subject: [PATCH 5/8] Add license header --- .../metrics/BallerinaMetricsLogsObserver.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java index a689af535305..80443da2106c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you 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.ballerina.runtime.observability.metrics; import io.ballerina.runtime.api.Environment; From 4c7862e7caa0fe7e67c827dbd39ad39874526b0e Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Thu, 21 Nov 2024 11:21:10 +0530 Subject: [PATCH 6/8] Move observer classes to ballerinai/observe module --- .../metrics/BallerinaMetricsLogsObserver.java | 127 --------------- .../metrics/BallerinaMetricsObserver.java | 144 ------------------ .../tracer/BallerinaTracingObserver.java | 47 ------ 3 files changed, 318 deletions(-) delete mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java delete mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsObserver.java delete mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BallerinaTracingObserver.java diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java deleted file mode 100644 index 80443da2106c..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsLogsObserver.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. - * - * WSO2 LLC. licenses this file to you 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.ballerina.runtime.observability.metrics; - -import io.ballerina.runtime.api.Environment; -import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.creators.ValueCreator; -import io.ballerina.runtime.api.utils.StringUtils; -import io.ballerina.runtime.api.values.BMap; -import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.observability.BallerinaObserver; -import io.ballerina.runtime.observability.ObserveUtils; -import io.ballerina.runtime.observability.ObserverContext; - -import java.io.PrintStream; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import static io.ballerina.runtime.observability.ObservabilityConstants.PROPERTY_KEY_HTTP_STATUS_CODE; -import static io.ballerina.runtime.observability.ObservabilityConstants.TAG_KEY_HTTP_STATUS_CODE_GROUP; -import static io.ballerina.runtime.observability.ObservabilityConstants.STATUS_CODE_GROUP_SUFFIX; - -public class BallerinaMetricsLogsObserver implements BallerinaObserver { - private static final String ORG_NAME = "ballerinax"; - private static final String PROPERTY_START_TIME = "_observation_start_time_"; - private static final PrintStream consoleError = System.err; - - private static Environment environment; - - public BallerinaMetricsLogsObserver(Environment environment) { - BallerinaMetricsLogsObserver.environment = environment; - } - - @Override - public void startServerObservation(ObserverContext observerContext) { - } - - @Override - public void startClientObservation(ObserverContext observerContext) { - } - - @Override - public void stopServerObservation(ObserverContext observerContext) { - if (!observerContext.isStarted()) { - // Do not collect metrics if the observation hasn't started - return; - } - stopObservation(observerContext); - } - - @Override - public void stopClientObservation(ObserverContext observerContext) { - if (!observerContext.isStarted()) { - // Do not collect metrics if the observation hasn't started - return; - } - stopObservation(observerContext); - } - - private void stopObservation(ObserverContext observerContext) { - Set tags = new HashSet<>(); - Map customTags = observerContext.customMetricTags; - if (customTags != null) { - tags.addAll(customTags.values()); - } - tags.addAll(observerContext.getAllTags()); - - // Add status_code_group tag - Integer statusCode = (Integer) observerContext.getProperty(PROPERTY_KEY_HTTP_STATUS_CODE); - if (statusCode != null && statusCode > 0) { - tags.add(Tag.of(TAG_KEY_HTTP_STATUS_CODE_GROUP, (statusCode / 100) + STATUS_CODE_GROUP_SUFFIX)); - } - - try { - Long startTime = (Long) observerContext.getProperty(PROPERTY_START_TIME); - long duration = System.nanoTime() - startTime; - - Optional protocolValue = Optional.empty(); - if (tags.stream().anyMatch(tag -> tag.getKey().equals("protocol"))) { - protocolValue = tags.stream().filter(tag -> tag.getKey().equals("protocol")).map(Tag::getValue) - .findFirst(); - } - String protocol = protocolValue.orElse("http"); - - BMap logAttributes = ValueCreator.createMapValue(); - logAttributes.put(StringUtils.fromString("protocol"), StringUtils.fromString(protocol)); - tags.stream().filter(tag -> !tag.getKey().equals("protocol")) - .forEach(tag -> logAttributes.put(StringUtils.fromString(tag.getKey()), - StringUtils.fromString(tag.getValue()))); - logAttributes.put(StringUtils.fromString("response_time_seconds"), - StringUtils.fromString(String.valueOf(duration / 1E9))); - - printMetricLog(logAttributes); - } catch (RuntimeException e) { - handleError("multiple metrics", tags, e); - } - } - - private void handleError(String metricName, Set tags, RuntimeException e) { - // Metric Provider may throw exceptions if there is a mismatch in tags. - consoleError.println("error: error collecting metrics for " + metricName + " with tags " + tags + - ": " + e.getMessage()); - } - - private static void printMetricLog(BMap logAttributes) { - // TODO: Remove version when the API is finalized, and add the configured org name. - Module metricsLogsModule = new Module(ORG_NAME, ObserveUtils.getMetricsLogsProvider().getValue(), "1"); - environment.getRuntime().callFunction(metricsLogsModule, "printMetricsLog", null, logAttributes); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsObserver.java deleted file mode 100644 index d796ed991094..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/metrics/BallerinaMetricsObserver.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you 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.ballerina.runtime.observability.metrics; - -import io.ballerina.runtime.observability.BallerinaObserver; -import io.ballerina.runtime.observability.ObserverContext; - -import java.io.PrintStream; -import java.time.Duration; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import static io.ballerina.runtime.observability.ObservabilityConstants.PROPERTY_KEY_HTTP_STATUS_CODE; -import static io.ballerina.runtime.observability.ObservabilityConstants.STATUS_CODE_GROUP_SUFFIX; -import static io.ballerina.runtime.observability.ObservabilityConstants.TAG_KEY_HTTP_STATUS_CODE_GROUP; - -/** - * Observe the runtime and collect measurements. - */ -public class BallerinaMetricsObserver implements BallerinaObserver { - - private static final String PROPERTY_START_TIME = "_observation_start_time_"; - private static final String PROPERTY_IN_PROGRESS_COUNTER = "_observation_in_progress_counter_"; - - private static final PrintStream consoleError = System.err; - - private static final MetricRegistry metricRegistry = DefaultMetricRegistry.getInstance(); - - private static final StatisticConfig[] responseTimeStatisticConfigs = new StatisticConfig[]{ - StatisticConfig.builder() - .expiry(Duration.ofSeconds(10)) - .percentiles(StatisticConfig.DEFAULT.getPercentiles()) - .build(), - StatisticConfig.builder() - .expiry(Duration.ofMinutes(1)) - .percentiles(StatisticConfig.DEFAULT.getPercentiles()) - .build(), - StatisticConfig.builder() - .expiry(Duration.ofMinutes(5)) - .percentiles(StatisticConfig.DEFAULT.getPercentiles()) - .build() - }; - - @Override - public void startServerObservation(ObserverContext observerContext) { - startObservation(observerContext); - } - - @Override - public void startClientObservation(ObserverContext observerContext) { - startObservation(observerContext); - } - - @Override - public void stopServerObservation(ObserverContext observerContext) { - if (!observerContext.isStarted()) { - // Do not collect metrics if the observation hasn't started - return; - } - stopObservation(observerContext); - } - - @Override - public void stopClientObservation(ObserverContext observerContext) { - if (!observerContext.isStarted()) { - // Do not collect metrics if the observation hasn't started - return; - } - stopObservation(observerContext); - } - - private void startObservation(ObserverContext observerContext) { - observerContext.addProperty(PROPERTY_START_TIME, System.nanoTime()); - Set tags = observerContext.getAllTags(); - try { - Gauge inProgressGauge = metricRegistry.gauge(new MetricId("inprogress_requests", "In-progress requests", - tags)); - inProgressGauge.increment(); - /* - * The in progress counter is stored so that the same counter can be decremted when the observation - * ends. This is needed as the the program may add tags to the context causing the tags to be - * different at the end compared to the start. - */ - observerContext.addProperty(PROPERTY_IN_PROGRESS_COUNTER, inProgressGauge); - } catch (RuntimeException e) { - handleError("inprogress_requests", tags, e); - } - } - - private void stopObservation(ObserverContext observerContext) { - Set tags = new HashSet<>(); - Map customTags = observerContext.customMetricTags; - if (customTags != null) { - tags.addAll(customTags.values()); - } - tags.addAll(observerContext.getAllTags()); - - // Add status_code_group tag - Integer statusCode = (Integer) observerContext.getProperty(PROPERTY_KEY_HTTP_STATUS_CODE); - if (statusCode != null && statusCode > 0) { - tags.add(Tag.of(TAG_KEY_HTTP_STATUS_CODE_GROUP, (statusCode / 100) + STATUS_CODE_GROUP_SUFFIX)); - } - - try { - Long startTime = (Long) observerContext.getProperty(PROPERTY_START_TIME); - long duration = System.nanoTime() - startTime; - ((Gauge) observerContext.getProperty(PROPERTY_IN_PROGRESS_COUNTER)).decrement(); - metricRegistry.gauge(new MetricId("response_time_seconds", - "Response time", tags), responseTimeStatisticConfigs).setValue(duration / 1E9); - metricRegistry.counter(new MetricId("response_time_nanoseconds_total", - "Total response response time for all requests", tags)).increment(duration); - metricRegistry.counter(new MetricId("requests_total", - "Total number of requests", tags)).increment(); - if (statusCode != null && 400 <= statusCode && statusCode < 600) { - metricRegistry.counter(new MetricId("response_errors_total", - "Total number of response errors", tags)).increment(); - } - } catch (RuntimeException e) { - handleError("multiple metrics", tags, e); - } - } - - private void handleError(String metricName, Set tags, RuntimeException e) { - // Metric Provider may throw exceptions if there is a mismatch in tags. - consoleError.println("error: error collecting metrics for " + metricName + " with tags " + tags + - ": " + e.getMessage()); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BallerinaTracingObserver.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BallerinaTracingObserver.java deleted file mode 100644 index d6cbc277d813..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BallerinaTracingObserver.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you 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.ballerina.runtime.observability.tracer; - -import io.ballerina.runtime.observability.BallerinaObserver; -import io.ballerina.runtime.observability.ObserverContext; - -/** - * Observe the runtime and start/stop tracing. - */ -public class BallerinaTracingObserver implements BallerinaObserver { - - @Override - public void startServerObservation(ObserverContext observerContext) { - TracingUtils.startObservation(observerContext, false); - } - - @Override - public void startClientObservation(ObserverContext observerContext) { - TracingUtils.startObservation(observerContext, true); - } - - @Override - public void stopServerObservation(ObserverContext observerContext) { - TracingUtils.stopObservation(observerContext); - } - - @Override - public void stopClientObservation(ObserverContext observerContext) { - TracingUtils.stopObservation(observerContext); - } -} From 413284074d8a65b8f4b1a334cd8128b41d487c71 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Fri, 22 Nov 2024 10:05:14 +0530 Subject: [PATCH 7/8] Remove metricsLogsProvider config --- .../io/ballerina/runtime/observability/ObserveUtils.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java index ab773e90c508..6f1c7a23fc8d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java @@ -73,7 +73,6 @@ public final class ObserveUtils { private static final boolean tracingEnabled; private static final BString tracingProvider; private static final boolean metricsLogsEnabled; - private static final BString metricsLogsProvider; static { // TODO: Move config initialization to ballerina level once checking config key is possible at ballerina level @@ -92,8 +91,6 @@ public final class ObserveUtils { PredefinedTypes.TYPE_STRING, false); VariableKey metricsLogsEnabledKey = new VariableKey(observeModule, "metricsLogsEnabled", PredefinedTypes.TYPE_BOOLEAN, false); - VariableKey metricsLogsProviderKey = new VariableKey(observeModule, "metricsLogsProvider", - PredefinedTypes.TYPE_STRING, false); metricsEnabled = readConfig(metricsEnabledKey, enabledKey, false); metricsProvider = readConfig(metricsProviderKey, null, StringUtils.fromString("default")); @@ -101,7 +98,6 @@ public final class ObserveUtils { tracingEnabled = readConfig(tracingEnabledKey, enabledKey, false); tracingProvider = readConfig(tracingProviderKey, providerKey, StringUtils.fromString("choreo")); metricsLogsEnabled = readConfig(metricsLogsEnabledKey, enabledKey, false); - metricsLogsProvider = readConfig(metricsLogsProviderKey, providerKey, StringUtils.fromString("choreo")); enabled = metricsEnabled || tracingEnabled || metricsLogsEnabled; } @@ -148,10 +144,6 @@ public static boolean isMetricsLogsEnabled() { return metricsLogsEnabled; } - public static BString getMetricsLogsProvider() { - return metricsLogsProvider; - } - /** * Add metrics and tracing observers. * From 70ee31032c938f26e2397ac16d6b18b436b53e9c Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Thu, 28 Nov 2024 10:23:50 +0530 Subject: [PATCH 8/8] Update defining configuration --- .../java/io/ballerina/runtime/observability/ObserveUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java index 6f1c7a23fc8d..a38117c3ca07 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/ObserveUtils.java @@ -97,7 +97,7 @@ public final class ObserveUtils { metricsReporter = readConfig(metricsReporterKey, providerKey, StringUtils.fromString("choreo")); tracingEnabled = readConfig(tracingEnabledKey, enabledKey, false); tracingProvider = readConfig(tracingProviderKey, providerKey, StringUtils.fromString("choreo")); - metricsLogsEnabled = readConfig(metricsLogsEnabledKey, enabledKey, false); + metricsLogsEnabled = readConfig(metricsLogsEnabledKey, metricsLogsEnabledKey, false); enabled = metricsEnabled || tracingEnabled || metricsLogsEnabled; }