From 34d5c411aad8ac6768e8c2f15c5c0cfc870d10c1 Mon Sep 17 00:00:00 2001 From: Tim Quinn Date: Thu, 29 Aug 2024 12:11:05 -0500 Subject: [PATCH] 4.x Allow users to direct Helidon to use an existing global `OpenTelemetry` instance rather than create its own (#9205) * Allow explicit use/avoidance of existing OTel instance via configuration * Clarify config property name * Refer to 'telemetry' instead of 'tracing' in property name --- .../telemetry/OpenTelemetryProducer.java | 4 +-- tracing/providers/opentelemetry/pom.xml | 5 ++++ .../opentelemetry/HelidonOpenTelemetry.java | 13 ++++++++ .../opentelemetry/AgentDetectorTest.java | 30 +++++++++++++++++-- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/OpenTelemetryProducer.java b/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/OpenTelemetryProducer.java index 1c5a086e5ab..a672f16d70b 100644 --- a/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/OpenTelemetryProducer.java +++ b/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/OpenTelemetryProducer.java @@ -90,8 +90,8 @@ private void init() { mpConfig.getOptionalValue(EXPORTER_NAME_PROPERTY, String.class).ifPresent(e -> exporterName = e); - // If there is an OTEL Agent – delegate everything to it. - if (HelidonOpenTelemetry.AgentDetector.isAgentPresent(config)) { + // If there is an OTEL Agent – or otherwise we should use a pre-existing global OTel instance - delegate to it. + if (HelidonOpenTelemetry.AgentDetector.useExistingGlobalOpenTelemetry(config)) { openTelemetry = GlobalOpenTelemetry.get(); } else { diff --git a/tracing/providers/opentelemetry/pom.xml b/tracing/providers/opentelemetry/pom.xml index 18758ae13f1..d8bdf95fa07 100644 --- a/tracing/providers/opentelemetry/pom.xml +++ b/tracing/providers/opentelemetry/pom.xml @@ -83,6 +83,11 @@ junit-jupiter-api test + + org.junit.jupiter + junit-jupiter-params + test + org.hamcrest hamcrest-all diff --git a/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/HelidonOpenTelemetry.java b/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/HelidonOpenTelemetry.java index 133710df4a9..23474c8f918 100644 --- a/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/HelidonOpenTelemetry.java +++ b/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/HelidonOpenTelemetry.java @@ -51,6 +51,7 @@ public final class HelidonOpenTelemetry { public static final String IO_OPENTELEMETRY_JAVAAGENT = "io.opentelemetry.javaagent"; static final String UNSUPPORTED_OPERATION_MESSAGE = "Span listener attempted to invoke an illegal operation"; + static final String USE_EXISTING_OTEL = "io.helidon.telemetry.otel.use-existing-instance"; private static final System.Logger LOGGER = System.getLogger(HelidonOpenTelemetry.class.getName()); private static final LazyValue> SPAN_LISTENERS = @@ -144,6 +145,18 @@ public static boolean isAgentPresent(Config config) { return false; } + /** + * Return whether the user has requested that Helidon use an existing global OpenTelemetry instance rather than + * creating one itself; specifying that the OpenTelemetry agent is present automatically implies using the agent's + * existing instance. + * + * @param config configuration potentially containing the setting + * @return true if Helidon is configured to use an existing global OpenTelemetry instance; false otherwise + */ + public static boolean useExistingGlobalOpenTelemetry(Config config) { + return isAgentPresent(config) || config.get(USE_EXISTING_OTEL).asBoolean().orElse(false); + } + private static boolean checkSystemProperties() { return System.getProperties().stringPropertyNames() .stream() diff --git a/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/AgentDetectorTest.java b/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/AgentDetectorTest.java index d631b36112d..d2a00e62706 100644 --- a/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/AgentDetectorTest.java +++ b/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/AgentDetectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Oracle and/or its affiliates. + * Copyright (c) 2023, 2024 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,15 +17,19 @@ package io.helidon.tracing.providers.opentelemetry; import java.util.Map; +import java.util.stream.Stream; import io.helidon.config.Config; import io.helidon.config.ConfigSources; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; - +import static org.junit.jupiter.params.provider.Arguments.arguments; /** * Check Agent Detector working correctly. @@ -56,4 +60,26 @@ void checkEnvVariable(){ boolean present = HelidonOpenTelemetry.AgentDetector.isAgentPresent(config); assertThat(present, is(true)); } + + @ParameterizedTest + @MethodSource + void checkUsePreexistingOTel(String testDescr, Config config, boolean expectedResult) { + assertThat(testDescr, HelidonOpenTelemetry.AgentDetector.useExistingGlobalOpenTelemetry(config), is(expectedResult)); + } + + static Stream checkUsePreexistingOTel() { + return Stream.of(arguments("OTel agent present true", + Config.just(ConfigSources.create(Map.of(HelidonOpenTelemetry.OTEL_AGENT_PRESENT_PROPERTY, "true"))), + true), + arguments("OTel agent present not specified, use existing OTel true", + Config.just(ConfigSources.create(Map.of(HelidonOpenTelemetry.USE_EXISTING_OTEL, "true"))), + true), + arguments("Neither config value set", + Config.empty(), + false), + arguments("OTel agent present but NOT to use existing OTel instance", + Config.just(ConfigSources.create(Map.of(HelidonOpenTelemetry.OTEL_AGENT_PRESENT_PROPERTY, "true", + HelidonOpenTelemetry.USE_EXISTING_OTEL, "false"))), + true)); + } }