From f37ec1dcfbe7e69a6b0badd79f925785c411af15 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Tue, 19 Nov 2024 22:02:18 +0530 Subject: [PATCH 01/10] Add metrics logs observer --- ballerina/init.bal | 12 ++++++++++++ .../stdlib/observe/internal/NativeFunctions.java | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/ballerina/init.bal b/ballerina/init.bal index 688708b..acfc22d 100644 --- a/ballerina/init.bal +++ b/ballerina/init.bal @@ -31,6 +31,13 @@ function init() { externPrintError("failed to enable tracing"); } } + + if (observe:isMetricsLogsEnabled()) { + var err = externEnableMetricsLogging(observe:getTracingProvider()); + if (err is error) { + externPrintError("failed to enable tracing"); + } + } } function externEnableMetrics(string provider) returns error? = @java:Method { @@ -43,6 +50,11 @@ function externEnableTracing(string provider) returns error? = @java:Method { name: "enableTracing" } external; +function externEnableMetricsLogging(string provider) returns error? = @java:Method { + 'class: "io.ballerina.stdlib.observe.internal.NativeFunctions", + name: "enableMetricsLogging" +} external; + function externPrintError(string message) = @java:Method { 'class: "io.ballerina.stdlib.observe.internal.NativeFunctions", name: "printError" diff --git a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java index 548c4be..ea80c63 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java @@ -17,9 +17,11 @@ */ package io.ballerina.stdlib.observe.internal; +import io.ballerina.runtime.api.Environment; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.observability.ObserveUtils; +import io.ballerina.runtime.observability.metrics.BallerinaMetricsLogsObserver; import io.ballerina.runtime.observability.metrics.BallerinaMetricsObserver; import io.ballerina.runtime.observability.metrics.DefaultMetricRegistry; import io.ballerina.runtime.observability.metrics.MetricRegistry; @@ -94,6 +96,15 @@ public static BError enableTracing(BString providerName) { } } + public static BError enableMetricsLogging(Environment env, BString providerName) { + try { + ObserveUtils.addObserver(new BallerinaMetricsLogsObserver(env)); + return null; + } catch (BError e) { + return e; + } + } + public static void printError(BString message) { errStream.println("error: " + message.getValue()); } From 09707649e67ccf0c40b5c2b9e81e2068dad62ae3 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Tue, 19 Nov 2024 22:03:48 +0530 Subject: [PATCH 02/10] Add metrics logs observer --- ballerina/init.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/init.bal b/ballerina/init.bal index acfc22d..937640a 100644 --- a/ballerina/init.bal +++ b/ballerina/init.bal @@ -33,7 +33,7 @@ function init() { } if (observe:isMetricsLogsEnabled()) { - var err = externEnableMetricsLogging(observe:getTracingProvider()); + var err = externEnableMetricsLogging(observe:getMetricsLogsProvider()); if (err is error) { externPrintError("failed to enable tracing"); } From dc1eee0b91b2e09a9b92166e2f62d11def9e9036 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Thu, 21 Nov 2024 11:23:08 +0530 Subject: [PATCH 03/10] Move observer classes from ballerina-lang --- .../observe/internal/NativeFunctions.java | 6 +- .../BallerinaMetricsLogsObserver.java | 126 +++++++++++++++ .../observers/BallerinaMetricsObserver.java | 143 ++++++++++++++++++ .../observers/BallerinaTracingObserver.java | 48 ++++++ 4 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java create mode 100644 native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java create mode 100644 native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java diff --git a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java index ea80c63..9876184 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java @@ -21,13 +21,13 @@ import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.observability.ObserveUtils; -import io.ballerina.runtime.observability.metrics.BallerinaMetricsLogsObserver; -import io.ballerina.runtime.observability.metrics.BallerinaMetricsObserver; +import io.ballerina.stdlib.observe.observers.BallerinaMetricsLogsObserver; +import io.ballerina.stdlib.observe.observers.BallerinaMetricsObserver; import io.ballerina.runtime.observability.metrics.DefaultMetricRegistry; import io.ballerina.runtime.observability.metrics.MetricRegistry; import io.ballerina.runtime.observability.metrics.noop.NoOpMetricProvider; import io.ballerina.runtime.observability.metrics.spi.MetricProvider; -import io.ballerina.runtime.observability.tracer.BallerinaTracingObserver; +import io.ballerina.stdlib.observe.observers.BallerinaTracingObserver; import io.ballerina.runtime.observability.tracer.TracersStore; import io.ballerina.runtime.observability.tracer.noop.NoOpTracerProvider; import io.ballerina.runtime.observability.tracer.spi.TracerProvider; diff --git a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java new file mode 100644 index 0000000..6053b78 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java @@ -0,0 +1,126 @@ +/* + * 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.stdlib.observe.observers; + +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 io.ballerina.runtime.observability.metrics.Tag; + +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.*; + +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/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java new file mode 100644 index 0000000..65c75aa --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java @@ -0,0 +1,143 @@ +/* + * 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.stdlib.observe.observers; + +import io.ballerina.runtime.observability.BallerinaObserver; +import io.ballerina.runtime.observability.ObserverContext; +import io.ballerina.runtime.observability.metrics.*; + +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.*; + +/** + * 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/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java new file mode 100644 index 0000000..2e57767 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java @@ -0,0 +1,48 @@ +/* + * 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.stdlib.observe.observers; + +import io.ballerina.runtime.observability.BallerinaObserver; +import io.ballerina.runtime.observability.ObserverContext; +import io.ballerina.runtime.observability.tracer.TracingUtils; + +/** + * 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 8a09df42527483765af4dbd44be7105d0bc90449 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Thu, 21 Nov 2024 14:11:45 +0530 Subject: [PATCH 04/10] Update license headers --- .../stdlib/observe/observers/BallerinaMetricsObserver.java | 6 +++--- .../stdlib/observe/observers/BallerinaTracingObserver.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java index 65c75aa..093bb36 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java @@ -1,12 +1,12 @@ /* - * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. * - * WSO2 Inc. licenses this file to you under the Apache License, + * 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 + * 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 diff --git a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java index 2e57767..ad124cf 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaTracingObserver.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. * - * WSO2 Inc. licenses this file to you under the Apache License, + * 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 From 4b3174657628b564cc5a69b048f6be49e4897bbc Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Thu, 21 Nov 2024 14:13:26 +0530 Subject: [PATCH 05/10] Define metric log function name --- .../stdlib/observe/observers/BallerinaMetricsLogsObserver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java index 6053b78..f4a0ab1 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java @@ -38,6 +38,7 @@ public class BallerinaMetricsLogsObserver implements BallerinaObserver { private static final String ORG_NAME = "ballerinax"; + private static final String METRIC_LOG_FUNCTION_NAME = "printMetricsLog"; private static final String PROPERTY_START_TIME = "_observation_start_time_"; private static final PrintStream consoleError = System.err; @@ -121,6 +122,6 @@ private void handleError(String metricName, Set tags, RuntimeException e) { 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); + environment.getRuntime().callFunction(metricsLogsModule, METRIC_LOG_FUNCTION_NAME, null, logAttributes); } } From 3b9b929c7d5ea73e5423588795e91b46b030fffb Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Fri, 22 Nov 2024 10:41:15 +0530 Subject: [PATCH 06/10] Remove metricsLogsProvider config --- ballerina/init.bal | 4 ++-- .../io/ballerina/stdlib/observe/internal/NativeFunctions.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ballerina/init.bal b/ballerina/init.bal index 937640a..bfd54f9 100644 --- a/ballerina/init.bal +++ b/ballerina/init.bal @@ -33,7 +33,7 @@ function init() { } if (observe:isMetricsLogsEnabled()) { - var err = externEnableMetricsLogging(observe:getMetricsLogsProvider()); + var err = externEnableMetricsLogging(); if (err is error) { externPrintError("failed to enable tracing"); } @@ -50,7 +50,7 @@ function externEnableTracing(string provider) returns error? = @java:Method { name: "enableTracing" } external; -function externEnableMetricsLogging(string provider) returns error? = @java:Method { +function externEnableMetricsLogging() returns error? = @java:Method { 'class: "io.ballerina.stdlib.observe.internal.NativeFunctions", name: "enableMetricsLogging" } external; diff --git a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java index 9876184..bb5f27b 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java @@ -96,7 +96,7 @@ public static BError enableTracing(BString providerName) { } } - public static BError enableMetricsLogging(Environment env, BString providerName) { + public static BError enableMetricsLogging(Environment env) { try { ObserveUtils.addObserver(new BallerinaMetricsLogsObserver(env)); return null; From 0a2ad8dadbc6e4fa4b8cad117e0ccbc398fd33f6 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Fri, 22 Nov 2024 14:28:05 +0530 Subject: [PATCH 07/10] Fix checkstyle errors --- .../stdlib/observe/internal/NativeFunctions.java | 6 +++--- .../observers/BallerinaMetricsLogsObserver.java | 8 +++++--- .../observe/observers/BallerinaMetricsObserver.java | 11 +++++++++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java index bb5f27b..34651d1 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/internal/NativeFunctions.java @@ -21,16 +21,16 @@ import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.observability.ObserveUtils; -import io.ballerina.stdlib.observe.observers.BallerinaMetricsLogsObserver; -import io.ballerina.stdlib.observe.observers.BallerinaMetricsObserver; import io.ballerina.runtime.observability.metrics.DefaultMetricRegistry; import io.ballerina.runtime.observability.metrics.MetricRegistry; import io.ballerina.runtime.observability.metrics.noop.NoOpMetricProvider; import io.ballerina.runtime.observability.metrics.spi.MetricProvider; -import io.ballerina.stdlib.observe.observers.BallerinaTracingObserver; import io.ballerina.runtime.observability.tracer.TracersStore; import io.ballerina.runtime.observability.tracer.noop.NoOpTracerProvider; import io.ballerina.runtime.observability.tracer.spi.TracerProvider; +import io.ballerina.stdlib.observe.observers.BallerinaMetricsLogsObserver; +import io.ballerina.stdlib.observe.observers.BallerinaMetricsObserver; +import io.ballerina.stdlib.observe.observers.BallerinaTracingObserver; import java.io.PrintStream; import java.util.ServiceLoader; diff --git a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java index f4a0ab1..a705496 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java @@ -24,7 +24,6 @@ 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 io.ballerina.runtime.observability.metrics.Tag; @@ -34,10 +33,13 @@ 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.STATUS_CODE_GROUP_SUFFIX; +import static io.ballerina.runtime.observability.ObservabilityConstants.TAG_KEY_HTTP_STATUS_CODE_GROUP; public class BallerinaMetricsLogsObserver implements BallerinaObserver { private static final String ORG_NAME = "ballerinax"; + private static final String MODULE_NAME = "metrics.logs"; private static final String METRIC_LOG_FUNCTION_NAME = "printMetricsLog"; private static final String PROPERTY_START_TIME = "_observation_start_time_"; private static final PrintStream consoleError = System.err; @@ -121,7 +123,7 @@ private void handleError(String metricName, Set tags, RuntimeException e) { 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"); + Module metricsLogsModule = new Module(ORG_NAME, MODULE_NAME, "1"); environment.getRuntime().callFunction(metricsLogsModule, METRIC_LOG_FUNCTION_NAME, null, logAttributes); } } diff --git a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java index 093bb36..da409ed 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsObserver.java @@ -19,7 +19,12 @@ import io.ballerina.runtime.observability.BallerinaObserver; import io.ballerina.runtime.observability.ObserverContext; -import io.ballerina.runtime.observability.metrics.*; +import io.ballerina.runtime.observability.metrics.DefaultMetricRegistry; +import io.ballerina.runtime.observability.metrics.Gauge; +import io.ballerina.runtime.observability.metrics.MetricId; +import io.ballerina.runtime.observability.metrics.MetricRegistry; +import io.ballerina.runtime.observability.metrics.StatisticConfig; +import io.ballerina.runtime.observability.metrics.Tag; import java.io.PrintStream; import java.time.Duration; @@ -27,7 +32,9 @@ import java.util.Map; 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.STATUS_CODE_GROUP_SUFFIX; +import static io.ballerina.runtime.observability.ObservabilityConstants.TAG_KEY_HTTP_STATUS_CODE_GROUP; /** * Observe the runtime and collect measurements. From 3fedf019490ab5e7c1d4f3a4d493c8cf8bb0ae43 Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Thu, 28 Nov 2024 10:06:29 +0530 Subject: [PATCH 08/10] Remove accessing metrics logs provider --- .../observers/BallerinaMetricsLogsObserver.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java index a705496..8e749b0 100644 --- a/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java +++ b/native/src/main/java/io/ballerina/stdlib/observe/observers/BallerinaMetricsLogsObserver.java @@ -52,10 +52,12 @@ public BallerinaMetricsLogsObserver(Environment environment) { @Override public void startServerObservation(ObserverContext observerContext) { + startObservation(observerContext); } @Override public void startClientObservation(ObserverContext observerContext) { + startObservation(observerContext); } @Override @@ -76,6 +78,12 @@ public void stopClientObservation(ObserverContext observerContext) { stopObservation(observerContext); } + private void startObservation(ObserverContext observerContext) { + if (observerContext.getProperty(PROPERTY_START_TIME) == null) { + observerContext.addProperty(PROPERTY_START_TIME, System.nanoTime()); + } + } + private void stopObservation(ObserverContext observerContext) { Set tags = new HashSet<>(); Map customTags = observerContext.customMetricTags; @@ -117,7 +125,7 @@ private void stopObservation(ObserverContext observerContext) { 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 + + consoleError.println("error: error collecting metric logs for " + metricName + " with tags " + tags + ": " + e.getMessage()); } From e7d3ad3078e055b96a1722bdca5b99b9e267304c Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Fri, 20 Dec 2024 10:07:49 +0530 Subject: [PATCH 09/10] Update lang version --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 08c29c1..9424f0f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,7 @@ org.gradle.caching=true group=io.ballerina version=1.3.1-SNAPSHOT -ballerinaLangVersion=2201.11.0-20241112-214900-6b80ab87 +ballerinaLangVersion=2201.11.0-20241219-143200-53f6d83e githubSpotbugsVersion=6.0.18 githubJohnrengelmanShadowVersion=8.1.1 underCouchDownloadVersion=5.4.0 @@ -28,7 +28,7 @@ openTelemetryVersion=1.7.0 nettyCodecVersion=4.1.100.Final gsonVersion=2.10.1 -observeVersion=1.4.0-20241113-092000-b83ae74 +observeVersion=1.4.0-20241220-100300-6b4cf7a # Test Dependency Versions testngVersion=7.6.1 From 12981d1f9399a1129f5df735e50adcd18927991c Mon Sep 17 00:00:00 2001 From: NipunaMadhushan Date: Fri, 20 Dec 2024 15:35:32 +0530 Subject: [PATCH 10/10] Skip spotbugsmain --- native/spotbugs-exclude.xml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 native/spotbugs-exclude.xml diff --git a/native/spotbugs-exclude.xml b/native/spotbugs-exclude.xml new file mode 100644 index 0000000..5d9747a --- /dev/null +++ b/native/spotbugs-exclude.xml @@ -0,0 +1,7 @@ + + + + + + +