From 49aba739b0cd55650728e768456871f8d2015f66 Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Tue, 21 May 2024 17:55:39 +0200 Subject: [PATCH 1/6] Replace Plexus APIs by JSR 330 APIs for Dependency Injection --- maven-extension/build.gradle.kts | 13 ++-- .../maven/OpenTelemetrySdkService.java | 72 +++++++++---------- .../maven/OtelExecutionListener.java | 58 +++------------ .../maven/OtelLifecycleParticipant.java | 44 ++++++++---- .../io/opentelemetry/maven/SpanRegistry.java | 6 +- .../maven/handler/MavenDeployHandler.java | 5 +- .../io/opentelemetry/maven/package-info.java | 13 ---- .../resources/META-INF/maven/extension.xml | 3 +- .../resources/META-INF/plexus/components.xml | 56 --------------- .../META-INF/sisu/javax.inject.Named | 3 + 10 files changed, 93 insertions(+), 180 deletions(-) delete mode 100644 maven-extension/src/main/java/io/opentelemetry/maven/package-info.java delete mode 100644 maven-extension/src/main/resources/META-INF/plexus/components.xml create mode 100644 maven-extension/src/main/resources/META-INF/sisu/javax.inject.Named diff --git a/maven-extension/build.gradle.kts b/maven-extension/build.gradle.kts index 393ce187a..0923a9b5e 100644 --- a/maven-extension/build.gradle.kts +++ b/maven-extension/build.gradle.kts @@ -6,14 +6,14 @@ plugins { } // NOTE -// `META-INF/plexus/components.xml` is manually handled under src/main/resources because there is no Gradle -// equivalent to the Maven plugin `plexus-component-metadata:generate-metadata` +// `META-INF/sis/javax.inject.Named` is manually handled under src/main/resources because there is +// no Gradle equivalent to the Maven plugin `org.eclipse.sisu:sisu-maven-plugin` description = "Maven extension to observe Maven builds with distributed traces using OpenTelemetry SDK" otelJava.moduleName.set("io.opentelemetry.maven") dependencies { - implementation("org.codehaus.plexus:plexus-component-annotations:2.1.1") + implementation("javax.inject:javax.inject:1") implementation("io.opentelemetry:opentelemetry-api") implementation("io.opentelemetry:opentelemetry-sdk") @@ -27,11 +27,11 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - compileOnly("org.apache.maven:maven-core:3.5.0") // do not auto-update this version + compileOnly("org.apache.maven:maven-core:3.9.6") // do not auto-update this version compileOnly("org.slf4j:slf4j-api") compileOnly("org.sonatype.aether:aether-api:1.13.1") - testImplementation("org.apache.maven:maven-core:3.5.0") + testImplementation("org.apache.maven:maven-core:3.9.6") testImplementation("org.slf4j:slf4j-simple") } @@ -60,3 +60,6 @@ tasks { } tasks.getByName("test").dependsOn("shadowJar") +repositories { + mavenCentral() +} diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java index f9bcec913..abdcd88e9 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -16,57 +16,33 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import org.codehaus.plexus.component.annotations.Component; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; +import javax.annotation.PreDestroy; +import javax.inject.Named; +import javax.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Service to configure the {@link OpenTelemetry} instance. */ -@Component(role = OpenTelemetrySdkService.class, hint = "opentelemetry-service") -public final class OpenTelemetrySdkService implements Initializable, Disposable { +@Named +@Singleton +public final class OpenTelemetrySdkService { static final String VERSION = OpenTelemetrySdkService.class.getPackage().getImplementationVersion(); private static final Logger logger = LoggerFactory.getLogger(OpenTelemetrySdkService.class); - private OpenTelemetry openTelemetry = OpenTelemetry.noop(); - @Nullable private OpenTelemetrySdk openTelemetrySdk; + private final OpenTelemetry openTelemetry; - @Nullable private Tracer tracer; + private final OpenTelemetrySdk openTelemetrySdk; - private boolean mojosInstrumentationEnabled; + private final Tracer tracer; - /** Visible for testing */ - @Nullable AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk; + private final boolean mojosInstrumentationEnabled; - @Override - public synchronized void dispose() { - logger.debug("OpenTelemetry: dispose OpenTelemetrySdkService..."); - OpenTelemetrySdk openTelemetrySdk = this.openTelemetrySdk; - if (openTelemetrySdk != null) { - logger.debug("OpenTelemetry: Shutdown SDK Trace Provider..."); - CompletableResultCode sdkProviderShutdown = - openTelemetrySdk.getSdkTracerProvider().shutdown(); - sdkProviderShutdown.join(10, TimeUnit.SECONDS); - if (sdkProviderShutdown.isSuccess()) { - logger.debug("OpenTelemetry: SDK Trace Provider shut down"); - } else { - logger.warn( - "OpenTelemetry: Failure to shutdown SDK Trace Provider (done: {})", - sdkProviderShutdown.isDone()); - } - this.openTelemetrySdk = null; - } - this.openTelemetry = OpenTelemetry.noop(); - - this.autoConfiguredOpenTelemetrySdk = null; - logger.debug("OpenTelemetry: OpenTelemetrySdkService disposed"); - } + private boolean disposed; - @Override - public void initialize() { + public OpenTelemetrySdkService() { logger.debug("OpenTelemetry: Initialize OpenTelemetrySdkService v{}...", VERSION); // Change default of "otel.[traces,metrics,logs].exporter" from "otlp" to "none" @@ -80,7 +56,7 @@ public void initialize() { properties.put("otel.metrics.exporter", "none"); properties.put("otel.logs.exporter", "none"); - this.autoConfiguredOpenTelemetrySdk = + AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk = AutoConfiguredOpenTelemetrySdk.builder() .setServiceClassLoader(getClass().getClassLoader()) .addPropertiesSupplier(() -> properties) @@ -94,11 +70,31 @@ public void initialize() { this.openTelemetry = this.openTelemetrySdk; Boolean mojoSpansEnabled = getBooleanConfig("otel.instrumentation.maven.mojo.enabled"); - this.mojosInstrumentationEnabled = mojoSpansEnabled == null ? true : mojoSpansEnabled; + this.mojosInstrumentationEnabled = mojoSpansEnabled == null || mojoSpansEnabled; this.tracer = openTelemetry.getTracer("io.opentelemetry.contrib.maven", VERSION); } + @PreDestroy + public synchronized void preDestroy() { + logger.debug("OpenTelemetry: dispose OpenTelemetrySdkService..."); + if (!disposed) { + logger.debug("OpenTelemetry: Shutdown SDK Trace Provider..."); + CompletableResultCode sdkProviderShutdown = + this.openTelemetrySdk.getSdkTracerProvider().shutdown(); + sdkProviderShutdown.join(10, TimeUnit.SECONDS); + if (sdkProviderShutdown.isSuccess()) { + logger.debug("OpenTelemetry: SDK Trace Provider shut down"); + } else { + logger.warn( + "OpenTelemetry: Failure to shutdown SDK Trace Provider (done: {})", + sdkProviderShutdown.isDone()); + } + this.disposed = true; + } + logger.debug("OpenTelemetry: OpenTelemetrySdkService disposed"); + } + public Tracer getTracer() { Tracer tracer = this.tracer; if (tracer == null) { diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java index 4eb9eab0b..fd73312ce 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java @@ -21,28 +21,17 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.maven.execution.AbstractExecutionListener; import org.apache.maven.execution.ExecutionEvent; import org.apache.maven.execution.ExecutionListener; -import org.apache.maven.execution.MavenSession; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.component.annotations.Component; -import org.codehaus.plexus.component.annotations.Requirement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * Close the OpenTelemetry SDK (see {@link OpenTelemetrySdkService#dispose()}) on the end of - * execution of the last project ({@link #projectSucceeded(ExecutionEvent)} and {@link - * #projectFailed(ExecutionEvent)}) rather than on the end of the Maven session {@link - * #sessionEnded(ExecutionEvent)} because OpenTelemetry and GRPC classes are unloaded by the Maven - * classloader before {@link #sessionEnded(ExecutionEvent)} causing {@link NoClassDefFoundError} - * messages in the logs. - */ -@Component(role = ExecutionListener.class, hint = "otel-execution-listener") public final class OtelExecutionListener extends AbstractExecutionListener { private static final Logger logger = LoggerFactory.getLogger(OtelExecutionListener.class); @@ -56,17 +45,16 @@ public final class OtelExecutionListener extends AbstractExecutionListener { */ private static final ThreadLocal MOJO_EXECUTION_SCOPE = new ThreadLocal<>(); - @SuppressWarnings("NullAway") // Automatically initialized by DI - @Requirement - private SpanRegistry spanRegistry; + private final SpanRegistry spanRegistry; - @SuppressWarnings("NullAway") // Automatically initialized by DI - @Requirement - private OpenTelemetrySdkService openTelemetrySdkService; + private final OpenTelemetrySdkService openTelemetrySdkService; private final Map mojoGoalExecutionHandlers; - public OtelExecutionListener() { + OtelExecutionListener( + SpanRegistry spanRegistry, OpenTelemetrySdkService openTelemetrySdkService) { + this.spanRegistry = spanRegistry; + this.openTelemetrySdkService = openTelemetrySdkService; this.mojoGoalExecutionHandlers = MojoGoalExecutionHandlerConfiguration.loadMojoGoalExecutionHandler( OtelExecutionListener.class.getClassLoader()); @@ -102,36 +90,6 @@ public OtelExecutionListener() { } } - /** - * Register in given {@link OtelExecutionListener} to the lifecycle of the given {@link - * MavenSession} - * - * @see org.apache.maven.execution.MavenExecutionRequest#setExecutionListener(ExecutionListener) - */ - public static void registerOtelExecutionListener( - MavenSession session, OtelExecutionListener otelExecutionListener) { - - ExecutionListener initialExecutionListener = session.getRequest().getExecutionListener(); - if (initialExecutionListener instanceof ChainedExecutionListener - || initialExecutionListener instanceof OtelExecutionListener) { - // already initialized - logger.debug( - "OpenTelemetry: OpenTelemetry extension already registered as execution listener, skip."); - } else if (initialExecutionListener == null) { - session.getRequest().setExecutionListener(otelExecutionListener); - logger.debug( - "OpenTelemetry: OpenTelemetry extension registered as execution listener. No execution listener initially defined"); - } else { - session - .getRequest() - .setExecutionListener( - new ChainedExecutionListener(otelExecutionListener, initialExecutionListener)); - logger.debug( - "OpenTelemetry: OpenTelemetry extension registered as execution listener. InitialExecutionListener: " - + initialExecutionListener); - } - } - @Override public void sessionStarted(ExecutionEvent executionEvent) { MavenProject project = executionEvent.getSession().getTopLevelProject(); @@ -382,7 +340,7 @@ public Iterable keys(Map environmentVariables) { @Override @Nullable - public String get(@Nullable Map environmentVariables, String key) { + public String get(@Nullable Map environmentVariables, @Nonnull String key) { return environmentVariables == null ? null : environmentVariables.get(key.toUpperCase(Locale.ROOT)); diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java index 5f8b9e312..ecfaab213 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java @@ -5,23 +5,29 @@ package io.opentelemetry.maven; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; import org.apache.maven.AbstractMavenLifecycleParticipant; import org.apache.maven.execution.ExecutionListener; import org.apache.maven.execution.MavenSession; -import org.codehaus.plexus.component.annotations.Component; -import org.codehaus.plexus.component.annotations.Requirement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Add the {@link OtelExecutionListener} to the lifecycle of the Maven execution */ -@Component(role = AbstractMavenLifecycleParticipant.class) +@Named +@Singleton public final class OtelLifecycleParticipant extends AbstractMavenLifecycleParticipant { private static final Logger logger = LoggerFactory.getLogger(OtelLifecycleParticipant.class); - @SuppressWarnings("NullAway") // Automatically initialized by DI - @Requirement(role = ExecutionListener.class, hint = "otel-execution-listener") - private OtelExecutionListener otelExecutionListener; + private final OtelExecutionListener otelExecutionListener; + + @Inject + OtelLifecycleParticipant( + OpenTelemetrySdkService openTelemetrySdkService, SpanRegistry spanRegistry) { + this.otelExecutionListener = new OtelExecutionListener(spanRegistry, openTelemetrySdkService); + } /** * For an unknown reason, {@link #afterProjectsRead(MavenSession)} is invoked when the module is @@ -29,16 +35,28 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic */ @Override public void afterProjectsRead(MavenSession session) { - OtelExecutionListener.registerOtelExecutionListener(session, this.otelExecutionListener); + ExecutionListener initialExecutionListener = session.getRequest().getExecutionListener(); + if (initialExecutionListener instanceof ChainedExecutionListener + || initialExecutionListener instanceof OtelExecutionListener) { + // already initialized + logger.debug( + "OpenTelemetry: OpenTelemetry extension already registered as execution listener, skip."); + } else if (initialExecutionListener == null) { + session.getRequest().setExecutionListener(this.otelExecutionListener); + logger.debug( + "OpenTelemetry: OpenTelemetry extension registered as execution listener. No execution listener initially defined"); + } else { + session + .getRequest() + .setExecutionListener( + new ChainedExecutionListener(this.otelExecutionListener, initialExecutionListener)); + logger.debug( + "OpenTelemetry: OpenTelemetry extension registered as execution listener. InitialExecutionListener: " + + initialExecutionListener); + } logger.debug("OpenTelemetry: afterProjectsRead"); } - @Override - public void afterSessionStart(MavenSession session) { - OtelExecutionListener.registerOtelExecutionListener(session, this.otelExecutionListener); - logger.debug("OpenTelemetry: afterSessionStart"); - } - @Override public void afterSessionEnd(MavenSession session) { logger.debug("OpenTelemetry: afterSessionEnd"); diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/SpanRegistry.java b/maven-extension/src/main/java/io/opentelemetry/maven/SpanRegistry.java index c1c63e15b..276f1e116 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/SpanRegistry.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/SpanRegistry.java @@ -12,10 +12,11 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import javax.inject.Named; +import javax.inject.Singleton; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,7 +27,8 @@ * Daemon, can't execute multiple builds concurrently, there is no need to differentiate spans * per {@link org.apache.maven.execution.MavenSession}. */ -@Component(role = SpanRegistry.class) +@Singleton +@Named public final class SpanRegistry { private static final Logger logger = LoggerFactory.getLogger(SpanRegistry.class); diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/handler/MavenDeployHandler.java b/maven-extension/src/main/java/io/opentelemetry/maven/handler/MavenDeployHandler.java index 031fdc7b0..6fe985d47 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/handler/MavenDeployHandler.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/handler/MavenDeployHandler.java @@ -17,7 +17,6 @@ import java.util.Collections; import java.util.List; import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.execution.ExecutionEvent; import org.apache.maven.project.MavenProject; import org.slf4j.Logger; @@ -36,7 +35,9 @@ public void enrichSpan(SpanBuilder spanBuilder, ExecutionEvent execution) { spanBuilder.setSpanKind(SpanKind.CLIENT); MavenProject project = execution.getProject(); - ArtifactRepository optRepository = project.getDistributionManagementArtifactRepository(); + @SuppressWarnings("deprecation") // there is no alternative to o.a.m.a.r.ArtifactRepository + org.apache.maven.artifact.repository.ArtifactRepository optRepository = + project.getDistributionManagementArtifactRepository(); if (optRepository == null) { return; diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/package-info.java b/maven-extension/src/main/java/io/opentelemetry/maven/package-info.java deleted file mode 100644 index a33f62018..000000000 --- a/maven-extension/src/main/java/io/opentelemetry/maven/package-info.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.FIELD) -@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.PARAMETER) -@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.RETURN) -package io.opentelemetry.maven; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; -import org.checkerframework.framework.qual.TypeUseLocation; diff --git a/maven-extension/src/main/resources/META-INF/maven/extension.xml b/maven-extension/src/main/resources/META-INF/maven/extension.xml index 082c5a748..9dbca3f06 100644 --- a/maven-extension/src/main/resources/META-INF/maven/extension.xml +++ b/maven-extension/src/main/resources/META-INF/maven/extension.xml @@ -9,6 +9,7 @@ io.opentelemetry.api.internal io.opentelemetry.api.metrics io.opentelemetry.api.trace - io.opentelemetry.context + io.opentelemetry.context + io.opentelemetry.context.propagation diff --git a/maven-extension/src/main/resources/META-INF/plexus/components.xml b/maven-extension/src/main/resources/META-INF/plexus/components.xml deleted file mode 100644 index a461dee9e..000000000 --- a/maven-extension/src/main/resources/META-INF/plexus/components.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - io.opentelemetry.maven.OpenTelemetrySdkService - opentelemetry-service - io.opentelemetry.maven.OpenTelemetrySdkService - - false - - - org.apache.maven.rtinfo.RuntimeInformation - runtimeInformation - - - - - io.opentelemetry.maven.SpanRegistry - default - io.opentelemetry.maven.SpanRegistry - - false - - - org.apache.maven.AbstractMavenLifecycleParticipant - default - io.opentelemetry.maven.OtelLifecycleParticipant - - false - - - org.apache.maven.execution.ExecutionListener - otel-execution-listener - otelExecutionListener - - - - - org.apache.maven.execution.ExecutionListener - otel-execution-listener - io.opentelemetry.maven.OtelExecutionListener - - false - - - io.opentelemetry.maven.SpanRegistry - spanRegistry - - - io.opentelemetry.maven.OpenTelemetrySdkService - openTelemetrySdkService - - - - - diff --git a/maven-extension/src/main/resources/META-INF/sisu/javax.inject.Named b/maven-extension/src/main/resources/META-INF/sisu/javax.inject.Named new file mode 100644 index 000000000..10555de48 --- /dev/null +++ b/maven-extension/src/main/resources/META-INF/sisu/javax.inject.Named @@ -0,0 +1,3 @@ +io.opentelemetry.maven.OpenTelemetrySdkService +io.opentelemetry.maven.OtelLifecycleParticipant +io.opentelemetry.maven.SpanRegistry From fdab825c008885ba421b58b5d38047fd9ab231ca Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Tue, 21 May 2024 18:02:51 +0200 Subject: [PATCH 2/6] Replace Plexus APIs by JSR 330 APIs for Dependency Injection --- .../java/io/opentelemetry/maven/OtelExecutionListener.java | 7 +++++++ .../io/opentelemetry/maven/OtelLifecycleParticipant.java | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java index fd73312ce..4ba0c4b95 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java @@ -26,12 +26,19 @@ import org.apache.maven.execution.AbstractExecutionListener; import org.apache.maven.execution.ExecutionEvent; import org.apache.maven.execution.ExecutionListener; +import org.apache.maven.execution.MavenSession; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Don't mark this class as {@link javax.inject.Named} and {@link javax.inject.Singleton} because + * Maven Sisu doesn't automatically load instance of {@link ExecutionListener} as Maven Extension + * hooks the same way Maven Plexus did so we manually hook this instance of {@link + * ExecutionListener} through the {@link OtelLifecycleParticipant#afterProjectsRead(MavenSession)}. + */ public final class OtelExecutionListener extends AbstractExecutionListener { private static final Logger logger = LoggerFactory.getLogger(OtelExecutionListener.class); diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java index ecfaab213..44a629bad 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java @@ -23,6 +23,10 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic private final OtelExecutionListener otelExecutionListener; + /** + * Manually instantiate {@link OtelExecutionListener} and hook it in the Maven build lifecycle + * because Maven Sisu doesn't load it when Maven Plexus did. + */ @Inject OtelLifecycleParticipant( OpenTelemetrySdkService openTelemetrySdkService, SpanRegistry spanRegistry) { @@ -31,7 +35,8 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic /** * For an unknown reason, {@link #afterProjectsRead(MavenSession)} is invoked when the module is - * declared as an extension in pom.xml but {@link #afterSessionStart(MavenSession)} is not invoked + * declared as an extension in pom.xml but {@link #afterSessionStart(MavenSession)} is not + * invoked. */ @Override public void afterProjectsRead(MavenSession session) { From 4ffbd32632e8135db3451bd67c96ec5461d28220 Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Tue, 21 May 2024 23:37:36 +0200 Subject: [PATCH 3/6] Replace Plexus APIs by JSR 330 APIs for Dependency Injection --- maven-extension/build.gradle.kts | 2 +- .../io/opentelemetry/maven/OpenTelemetrySdkService.java | 5 ++++- .../maven/resources/MavenResourceProvider.java | 7 +++++++ .../maven/semconv/MavenOtelSemanticAttributes.java | 6 ++++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/maven-extension/build.gradle.kts b/maven-extension/build.gradle.kts index 0923a9b5e..7905d8641 100644 --- a/maven-extension/build.gradle.kts +++ b/maven-extension/build.gradle.kts @@ -13,7 +13,7 @@ description = "Maven extension to observe Maven builds with distributed traces u otelJava.moduleName.set("io.opentelemetry.maven") dependencies { - implementation("javax.inject:javax.inject:1") + compileOnly("javax.inject:javax.inject:1") implementation("io.opentelemetry:opentelemetry-api") implementation("io.opentelemetry:opentelemetry-sdk") diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java index abdcd88e9..c037fb243 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -8,6 +8,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.maven.semconv.MavenOtelSemanticAttributes; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.common.CompletableResultCode; @@ -43,7 +44,9 @@ public final class OpenTelemetrySdkService { private boolean disposed; public OpenTelemetrySdkService() { - logger.debug("OpenTelemetry: Initialize OpenTelemetrySdkService v{}...", VERSION); + logger.debug( + "OpenTelemetry: Initialize OpenTelemetrySdkService v{}...", + MavenOtelSemanticAttributes.TELEMETRY_DISTRO_VERSION_VALUE); // Change default of "otel.[traces,metrics,logs].exporter" from "otlp" to "none" // The impacts are diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/resources/MavenResourceProvider.java b/maven-extension/src/main/java/io/opentelemetry/maven/resources/MavenResourceProvider.java index 2fe6989d5..14af78c64 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/resources/MavenResourceProvider.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/resources/MavenResourceProvider.java @@ -10,6 +10,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.ServiceAttributes; +import io.opentelemetry.semconv.incubating.TelemetryIncubatingAttributes; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; @@ -22,6 +23,12 @@ public Resource createResource(ConfigProperties config) { return Resource.builder() .put(ServiceAttributes.SERVICE_NAME, MavenOtelSemanticAttributes.SERVICE_NAME_VALUE) .put(ServiceAttributes.SERVICE_VERSION, runtimeInformation.getMavenVersion()) + .put( + TelemetryIncubatingAttributes.TELEMETRY_DISTRO_NAME, + MavenOtelSemanticAttributes.TELEMETRY_DISTRO_NAME_VALUE) + .put( + TelemetryIncubatingAttributes.TELEMETRY_DISTRO_VERSION, + MavenOtelSemanticAttributes.TELEMETRY_DISTRO_VERSION_VALUE) .build(); } } diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/semconv/MavenOtelSemanticAttributes.java b/maven-extension/src/main/java/io/opentelemetry/maven/semconv/MavenOtelSemanticAttributes.java index a9599a0a8..353f30160 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/semconv/MavenOtelSemanticAttributes.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/semconv/MavenOtelSemanticAttributes.java @@ -9,6 +9,7 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey; import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.maven.OpenTelemetrySdkService; import io.opentelemetry.semconv.incubating.ContainerIncubatingAttributes; import java.util.List; @@ -55,5 +56,10 @@ public class MavenOtelSemanticAttributes { public static final String SERVICE_NAME_VALUE = "maven"; + public static final String TELEMETRY_DISTRO_NAME_VALUE = "opentelemetry-maven-extension"; + + public static final String TELEMETRY_DISTRO_VERSION_VALUE = + OpenTelemetrySdkService.class.getPackage().getImplementationVersion(); + private MavenOtelSemanticAttributes() {} } From 5755acc7cf87f8174571548303c52978fa5e1dfc Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Wed, 22 May 2024 10:51:25 +0200 Subject: [PATCH 4/6] Dependencies review + code cleanup --- maven-extension/build.gradle.kts | 9 ++-- .../maven/OpenTelemetrySdkService.java | 43 ++++++++----------- .../maven/OtelExecutionListener.java | 2 +- .../maven/OtelLifecycleParticipant.java | 6 --- .../maven/handler/package-info.java | 4 ++ .../io/opentelemetry/maven/package-info.java | 9 ++++ .../maven/resources/package-info.java | 9 ++++ 7 files changed, 45 insertions(+), 37 deletions(-) create mode 100644 maven-extension/src/main/java/io/opentelemetry/maven/handler/package-info.java create mode 100644 maven-extension/src/main/java/io/opentelemetry/maven/package-info.java create mode 100644 maven-extension/src/main/java/io/opentelemetry/maven/resources/package-info.java diff --git a/maven-extension/build.gradle.kts b/maven-extension/build.gradle.kts index 7905d8641..4a3725925 100644 --- a/maven-extension/build.gradle.kts +++ b/maven-extension/build.gradle.kts @@ -18,20 +18,21 @@ dependencies { implementation("io.opentelemetry:opentelemetry-api") implementation("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-sdk-trace") + implementation("io.opentelemetry:opentelemetry-sdk-metrics") + implementation("io.opentelemetry:opentelemetry-sdk-logs") implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + implementation("io.opentelemetry:opentelemetry-exporter-otlp") implementation("io.opentelemetry.semconv:opentelemetry-semconv") implementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.25.0-alpha") - implementation("io.opentelemetry:opentelemetry-exporter-otlp") annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - compileOnly("org.apache.maven:maven-core:3.9.6") // do not auto-update this version + compileOnly("org.apache.maven:maven-core:3.5.0") // do not auto-update, support older mvn versions compileOnly("org.slf4j:slf4j-api") - compileOnly("org.sonatype.aether:aether-api:1.13.1") - testImplementation("org.apache.maven:maven-core:3.9.6") + testImplementation("org.apache.maven:maven-core:3.5.0") testImplementation("org.slf4j:slf4j-simple") } diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java index c037fb243..af4fe9662 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -12,6 +12,7 @@ import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.common.CompletableResultCode; +import java.io.Closeable; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -26,15 +27,13 @@ /** Service to configure the {@link OpenTelemetry} instance. */ @Named @Singleton -public final class OpenTelemetrySdkService { +public final class OpenTelemetrySdkService implements Closeable { static final String VERSION = OpenTelemetrySdkService.class.getPackage().getImplementationVersion(); private static final Logger logger = LoggerFactory.getLogger(OpenTelemetrySdkService.class); - private final OpenTelemetry openTelemetry; - private final OpenTelemetrySdk openTelemetrySdk; private final Tracer tracer; @@ -66,49 +65,41 @@ public OpenTelemetrySdkService() { .disableShutdownHook() .build(); - if (logger.isDebugEnabled()) { - logger.debug("OpenTelemetry: OpenTelemetry SDK initialized"); - } this.openTelemetrySdk = autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk(); - this.openTelemetry = this.openTelemetrySdk; Boolean mojoSpansEnabled = getBooleanConfig("otel.instrumentation.maven.mojo.enabled"); this.mojosInstrumentationEnabled = mojoSpansEnabled == null || mojoSpansEnabled; - this.tracer = openTelemetry.getTracer("io.opentelemetry.contrib.maven", VERSION); + this.tracer = openTelemetrySdk.getTracer("io.opentelemetry.contrib.maven", VERSION); } @PreDestroy - public synchronized void preDestroy() { - logger.debug("OpenTelemetry: dispose OpenTelemetrySdkService..."); - if (!disposed) { - logger.debug("OpenTelemetry: Shutdown SDK Trace Provider..."); - CompletableResultCode sdkProviderShutdown = - this.openTelemetrySdk.getSdkTracerProvider().shutdown(); - sdkProviderShutdown.join(10, TimeUnit.SECONDS); - if (sdkProviderShutdown.isSuccess()) { - logger.debug("OpenTelemetry: SDK Trace Provider shut down"); + @Override + public synchronized void close() { + if (disposed) { + logger.debug("OpenTelemetry: OpenTelemetry SDK already shut down, ignore"); + } else { + logger.debug("OpenTelemetry: Shutdown OpenTelemetry SDK..."); + CompletableResultCode openTelemetrySdkShutdownResult = + this.openTelemetrySdk.shutdown().join(10, TimeUnit.SECONDS); + if (openTelemetrySdkShutdownResult.isSuccess()) { + logger.debug("OpenTelemetry: OpenTelemetry SDK successfully shut down"); } else { logger.warn( - "OpenTelemetry: Failure to shutdown SDK Trace Provider (done: {})", - sdkProviderShutdown.isDone()); + "OpenTelemetry: Failure to shutdown OpenTelemetry SDK (done: {})", + openTelemetrySdkShutdownResult.isDone()); } this.disposed = true; } - logger.debug("OpenTelemetry: OpenTelemetrySdkService disposed"); } public Tracer getTracer() { - Tracer tracer = this.tracer; - if (tracer == null) { - throw new IllegalStateException("Not initialized"); - } - return tracer; + return this.tracer; } /** Returns the {@link ContextPropagators} for this {@link OpenTelemetry}. */ public ContextPropagators getPropagators() { - return openTelemetry.getPropagators(); + return this.openTelemetrySdk.getPropagators(); } public boolean isMojosInstrumentationEnabled() { diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java index 4ba0c4b95..8da5c3acd 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java @@ -335,7 +335,7 @@ public void mojoFailed(ExecutionEvent executionEvent) { @Override public void sessionEnded(ExecutionEvent event) { - logger.debug("OpenTelemetry: Maven session ended"); + logger.debug("OpenTelemetry: Maven session ended, end root span"); spanRegistry.removeRootSpan().end(); } diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java index 44a629bad..6b910e15f 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java @@ -59,11 +59,5 @@ public void afterProjectsRead(MavenSession session) { "OpenTelemetry: OpenTelemetry extension registered as execution listener. InitialExecutionListener: " + initialExecutionListener); } - logger.debug("OpenTelemetry: afterProjectsRead"); - } - - @Override - public void afterSessionEnd(MavenSession session) { - logger.debug("OpenTelemetry: afterSessionEnd"); } } diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/handler/package-info.java b/maven-extension/src/main/java/io/opentelemetry/maven/handler/package-info.java new file mode 100644 index 000000000..b63bb69e5 --- /dev/null +++ b/maven-extension/src/main/java/io/opentelemetry/maven/handler/package-info.java @@ -0,0 +1,4 @@ +@ParametersAreNonnullByDefault +package io.opentelemetry.maven.handler; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/package-info.java b/maven-extension/src/main/java/io/opentelemetry/maven/package-info.java new file mode 100644 index 000000000..6cdf2bff4 --- /dev/null +++ b/maven-extension/src/main/java/io/opentelemetry/maven/package-info.java @@ -0,0 +1,9 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +@ParametersAreNonnullByDefault +package io.opentelemetry.maven; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/resources/package-info.java b/maven-extension/src/main/java/io/opentelemetry/maven/resources/package-info.java new file mode 100644 index 000000000..611203d85 --- /dev/null +++ b/maven-extension/src/main/java/io/opentelemetry/maven/resources/package-info.java @@ -0,0 +1,9 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +@ParametersAreNonnullByDefault +package io.opentelemetry.maven.resources; + +import javax.annotation.ParametersAreNonnullByDefault; From 5591bd431620aa11b0dee53d6ab4e74687ae253a Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Tue, 28 May 2024 10:52:56 +0200 Subject: [PATCH 5/6] Remove mistakenly added Gradle block --- maven-extension/build.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/maven-extension/build.gradle.kts b/maven-extension/build.gradle.kts index 4a3725925..94113398d 100644 --- a/maven-extension/build.gradle.kts +++ b/maven-extension/build.gradle.kts @@ -61,6 +61,3 @@ tasks { } tasks.getByName("test").dependsOn("shadowJar") -repositories { - mavenCentral() -} From ce225d23ffa183dface25cc4db0580e25fa62f6e Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Tue, 28 May 2024 10:53:13 +0200 Subject: [PATCH 6/6] Format --- .../src/main/resources/META-INF/maven/extension.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maven-extension/src/main/resources/META-INF/maven/extension.xml b/maven-extension/src/main/resources/META-INF/maven/extension.xml index 9dbca3f06..82afb8caf 100644 --- a/maven-extension/src/main/resources/META-INF/maven/extension.xml +++ b/maven-extension/src/main/resources/META-INF/maven/extension.xml @@ -9,7 +9,7 @@ io.opentelemetry.api.internal io.opentelemetry.api.metrics io.opentelemetry.api.trace - io.opentelemetry.context - io.opentelemetry.context.propagation + io.opentelemetry.context + io.opentelemetry.context.propagation