From a0dfdc3ef1673575785d1a1dca10f4c3e738d041 Mon Sep 17 00:00:00 2001 From: Nemanja Mikic Date: Tue, 6 Sep 2022 12:41:06 +0200 Subject: [PATCH] fix: issue with GlobalOpenTelemetry in tests (#152) * add predestroy to opentelemetry factory it will trigger resetForTest if Environment is Environment.TEST * add predestroy to opentelemetry factory it will trigger resetForTest if Environment is Environment.TEST * Avoid bean pollution - Don't use ReactorHttpClient - Use @Requires spec.name to avoid bean pollution - Annotate controller with @produces(MediaType.TEXT_PLAIN) and accept. Co-authored-by: Sergio del Amo --- .../DefaultOpenTelemetryFactory.java | 10 +++ .../util/HttpClientResetForTestSpec.groovy | 71 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tracing-opentelemetry/src/test/groovy/io/micronaut/tracing/instrument/util/HttpClientResetForTestSpec.groovy diff --git a/tracing-opentelemetry/src/main/java/io/micronaut/tracing/opentelemetry/DefaultOpenTelemetryFactory.java b/tracing-opentelemetry/src/main/java/io/micronaut/tracing/opentelemetry/DefaultOpenTelemetryFactory.java index 88f999ec2..37e480312 100644 --- a/tracing-opentelemetry/src/main/java/io/micronaut/tracing/opentelemetry/DefaultOpenTelemetryFactory.java +++ b/tracing-opentelemetry/src/main/java/io/micronaut/tracing/opentelemetry/DefaultOpenTelemetryFactory.java @@ -17,15 +17,18 @@ import io.micronaut.context.annotation.Factory; import io.micronaut.context.annotation.Property; +import io.micronaut.context.env.Environment; import io.micronaut.core.annotation.Nullable; import io.micronaut.core.convert.format.MapFormat; import io.micronaut.core.util.StringUtils; import io.micronaut.runtime.ApplicationConfiguration; +import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder; import io.opentelemetry.sdk.trace.IdGenerator; import io.opentelemetry.sdk.trace.SpanProcessor; +import jakarta.annotation.PreDestroy; import jakarta.inject.Singleton; import java.util.Map; @@ -98,4 +101,11 @@ protected OpenTelemetry defaultOpenTelemetry(ApplicationConfiguration applicatio } + @PreDestroy + void resetForTest(Environment environment) { + if (environment.getActiveNames().contains(Environment.TEST)) { + GlobalOpenTelemetry.resetForTest(); + } + } + } diff --git a/tracing-opentelemetry/src/test/groovy/io/micronaut/tracing/instrument/util/HttpClientResetForTestSpec.groovy b/tracing-opentelemetry/src/test/groovy/io/micronaut/tracing/instrument/util/HttpClientResetForTestSpec.groovy new file mode 100644 index 000000000..4c328a30a --- /dev/null +++ b/tracing-opentelemetry/src/test/groovy/io/micronaut/tracing/instrument/util/HttpClientResetForTestSpec.groovy @@ -0,0 +1,71 @@ +package io.micronaut.tracing.instrument.util + +import groovy.util.logging.Slf4j +import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires +import io.micronaut.http.HttpRequest +import io.micronaut.http.MediaType +import io.micronaut.http.annotation.Controller +import io.micronaut.http.annotation.Get +import io.micronaut.http.annotation.Header +import io.micronaut.http.annotation.Produces +import io.micronaut.http.client.HttpClient +import io.micronaut.reactor.http.client.ReactorHttpClient +import io.micronaut.runtime.server.EmbeddedServer +import io.micronaut.scheduling.annotation.ExecuteOn +import io.micronaut.tracing.annotation.ContinueSpan +import io.opentelemetry.extension.annotations.SpanAttribute +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter +import reactor.core.publisher.Mono +import spock.lang.AutoCleanup +import spock.lang.Shared +import spock.lang.Specification +import spock.util.concurrent.PollingConditions + +import static io.micronaut.scheduling.TaskExecutors.IO + +@Slf4j("LOG") +class HttpClientResetForTestSpec extends Specification { + + @Shared + @AutoCleanup + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, [ + 'micronaut.application.name': 'test-app', + 'spec.name': 'HttpClientResetForTestSpec' + ]) + + @Shared + @AutoCleanup + HttpClient httpClient = HttpClient.create(embeddedServer.URL) + + void 'test pre destroy resetForTest'() { + given: + String tracingId = UUID.randomUUID() + + when: + HttpRequest request = HttpRequest + .GET("/test/test") + .accept(MediaType.TEXT_PLAIN) + .header("X-TrackingId", tracingId) + String resp = httpClient.toBlocking().retrieve(request) + + then: + noExceptionThrown() + resp == tracingId + } + + @Requires(property = "spec.name", value = "HttpClientResetForTestSpec") + @Controller("/test") + static class TestController { + + @ExecuteOn(IO) + @Produces(MediaType.TEXT_PLAIN) + @Get("/test") + @ContinueSpan + Mono test(@SpanAttribute("tracing-annotation-span-attribute") + @Header("X-TrackingId") String tracingId) { + LOG.debug("test") + return Mono.just(tracingId) + } + } +}