diff --git a/microprofile/telemetry/pom.xml b/microprofile/telemetry/pom.xml index 363d1db5dce..690cea95a99 100644 --- a/microprofile/telemetry/pom.xml +++ b/microprofile/telemetry/pom.xml @@ -91,6 +91,11 @@ true + + io.helidon.logging + helidon-logging-jul + test + io.helidon.common.testing helidon-common-testing-junit5 diff --git a/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/HelidonTelemetryContainerFilter.java b/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/HelidonTelemetryContainerFilter.java index 6548f912211..fd69bddf46c 100644 --- a/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/HelidonTelemetryContainerFilter.java +++ b/microprofile/telemetry/src/main/java/io/helidon/microprofile/telemetry/HelidonTelemetryContainerFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024 Oracle and/or its affiliates. + * Copyright (c) 2023, 2025 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. @@ -106,9 +106,9 @@ class HelidonTelemetryContainerFilter implements ContainerRequestFilter, Contain LOGGER.log(System.Logger.Level.WARNING, String.format(""" Current OpenTelemetry semantic conventions include the HTTP method as part of REST span - names. Your configuration does not set mp.%s to true, so your service uses the legacy span name + names. Your configuration does not set %s to true, so your service uses the legacy span name format which excludes the HTTP method. This feature is deprecated and marked for removal in a - future major release of Helidon. Consider adding a setting of mp.%1$s to 'true' in your + future major release of Helidon. Consider adding a setting of %1$s to 'true' in your configuration to migrate to the current conventions.""", SPAN_NAME_INCLUDES_METHOD)); } diff --git a/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/MemoryLogHandler.java b/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/MemoryLogHandler.java new file mode 100644 index 00000000000..53d2a7cdb74 --- /dev/null +++ b/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/MemoryLogHandler.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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. + * 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.helidon.microprofile.telemetry; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.logging.LogRecord; +import java.util.logging.StreamHandler; + +public class MemoryLogHandler extends StreamHandler { + + private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + private static MemoryLogHandler create() { + try { + return new MemoryLogHandler(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public MemoryLogHandler() throws UnsupportedEncodingException { + setOutputStream(outputStream); + setEncoding(StandardCharsets.UTF_8.name()); + } + + @Override + public synchronized void publish(LogRecord record) { + super.publish(record); + flush(); // forces flush on writer + } + + public String logAsString() { + return outputStream.toString(StandardCharsets.UTF_8); + } +} diff --git a/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/WithSpanUsingLegacySpanNameTest.java b/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/WithSpanUsingLegacySpanNameTest.java index 3257cdb1608..799ef44448c 100644 --- a/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/WithSpanUsingLegacySpanNameTest.java +++ b/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/WithSpanUsingLegacySpanNameTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Oracle and/or its affiliates. + * Copyright (c) 2024, 2025 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. @@ -15,25 +15,54 @@ */ package io.helidon.microprofile.telemetry; +import java.io.UnsupportedEncodingException; +import java.util.logging.Handler; +import java.util.logging.Logger; import java.util.stream.Stream; import io.helidon.microprofile.testing.junit5.AddConfig; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; + @AddConfig(key = HelidonTelemetryContainerFilter.SPAN_NAME_INCLUDES_METHOD, value = "false") class WithSpanUsingLegacySpanNameTest extends WithSpanTestBase { + private static Logger logger = Logger.getLogger(HelidonTelemetryContainerFilter.class.getName()); + private static MemoryLogHandler memoryLogHandler; + + @BeforeAll + static void setup() { + for (Handler handler : logger.getHandlers()) { + if (handler instanceof MemoryLogHandler logHandler) { + memoryLogHandler = logHandler; + } + } + } + @ParameterizedTest() @MethodSource() - void testDefaultAppSpanNameFromPath(SpanPathTestInfo spanPathTestInfo) { + void testDefaultAppSpanNameFromPath(SpanPathTestInfo spanPathTestInfo) throws UnsupportedEncodingException { + testSpanNameFromPath(spanPathTestInfo); + + // @Deprecated(forRemoval = true) in 5.1 remove the following: + assertThat("Log output", + memoryLogHandler.logAsString(), + containsString("does not set " + HelidonTelemetryContainerFilter.SPAN_NAME_INCLUDES_METHOD)); + // end of removal + + } static Stream testDefaultAppSpanNameFromPath() { return Stream.of(new SpanPathTestInfo("traced", "/traced"), new SpanPathTestInfo("traced/sub/data", "/traced/sub/{name}")); } + } diff --git a/microprofile/telemetry/src/test/resources/logging-test.properties b/microprofile/telemetry/src/test/resources/logging-test.properties new file mode 100644 index 00000000000..767131e25a9 --- /dev/null +++ b/microprofile/telemetry/src/test/resources/logging-test.properties @@ -0,0 +1,27 @@ +# +# Copyright (c) 2025 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. +# 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. +# +handlers=java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.level=FINEST +java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format=%1$tH:%1$tM:%1$tS %4$s %3$s %5$s%6$s%n +# Global logging level. Can be overridden by specific loggers +.level=INFO + +io.helidon.microprofile.telemetry.MemoryLogHandler.level=INFO +io.helidon.microprofile.telemetry.MemoryLogHandler.append=false +io.helidon.microprofile.telemetry.HelidonTelemetryContainerFilter.level=INFO +io.helidon.microprofile.telemetry.HelidonTelemetryContainerFilter.useParentHandlers=false +io.helidon.microprofile.telemetry.HelidonTelemetryContainerFilter.handlers=io.helidon.microprofile.telemetry.MemoryLogHandler