[Maven Extension] Migrate from Plexus to JSR 330 dependency injection APIs (#1320)
This commit is contained in:
parent
14c385e374
commit
516aed9fdf
|
@ -6,30 +6,31 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE
|
// NOTE
|
||||||
// `META-INF/plexus/components.xml` is manually handled under src/main/resources because there is no Gradle
|
// `META-INF/sis/javax.inject.Named` is manually handled under src/main/resources because there is
|
||||||
// equivalent to the Maven plugin `plexus-component-metadata:generate-metadata`
|
// 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"
|
description = "Maven extension to observe Maven builds with distributed traces using OpenTelemetry SDK"
|
||||||
otelJava.moduleName.set("io.opentelemetry.maven")
|
otelJava.moduleName.set("io.opentelemetry.maven")
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.codehaus.plexus:plexus-component-annotations:2.1.1")
|
compileOnly("javax.inject:javax.inject:1")
|
||||||
|
|
||||||
implementation("io.opentelemetry:opentelemetry-api")
|
implementation("io.opentelemetry:opentelemetry-api")
|
||||||
implementation("io.opentelemetry:opentelemetry-sdk")
|
implementation("io.opentelemetry:opentelemetry-sdk")
|
||||||
implementation("io.opentelemetry:opentelemetry-sdk-trace")
|
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-spi")
|
||||||
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
|
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")
|
||||||
implementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.25.0-alpha")
|
implementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.25.0-alpha")
|
||||||
implementation("io.opentelemetry:opentelemetry-exporter-otlp")
|
|
||||||
|
|
||||||
annotationProcessor("com.google.auto.value:auto-value")
|
annotationProcessor("com.google.auto.value:auto-value")
|
||||||
compileOnly("com.google.auto.value:auto-value-annotations")
|
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.5.0") // do not auto-update, support older mvn versions
|
||||||
compileOnly("org.slf4j:slf4j-api")
|
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.5.0")
|
||||||
testImplementation("org.slf4j:slf4j-simple")
|
testImplementation("org.slf4j:slf4j-simple")
|
||||||
|
|
|
@ -8,66 +8,44 @@ package io.opentelemetry.maven;
|
||||||
import io.opentelemetry.api.OpenTelemetry;
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
import io.opentelemetry.api.trace.Tracer;
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.context.propagation.ContextPropagators;
|
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||||
|
import io.opentelemetry.maven.semconv.MavenOtelSemanticAttributes;
|
||||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||||
|
import java.io.Closeable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.codehaus.plexus.component.annotations.Component;
|
import javax.annotation.PreDestroy;
|
||||||
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
|
import javax.inject.Named;
|
||||||
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
|
import javax.inject.Singleton;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/** Service to configure the {@link OpenTelemetry} instance. */
|
/** Service to configure the {@link OpenTelemetry} instance. */
|
||||||
@Component(role = OpenTelemetrySdkService.class, hint = "opentelemetry-service")
|
@Named
|
||||||
public final class OpenTelemetrySdkService implements Initializable, Disposable {
|
@Singleton
|
||||||
|
public final class OpenTelemetrySdkService implements Closeable {
|
||||||
|
|
||||||
static final String VERSION =
|
static final String VERSION =
|
||||||
OpenTelemetrySdkService.class.getPackage().getImplementationVersion();
|
OpenTelemetrySdkService.class.getPackage().getImplementationVersion();
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(OpenTelemetrySdkService.class);
|
private static final Logger logger = LoggerFactory.getLogger(OpenTelemetrySdkService.class);
|
||||||
|
|
||||||
private OpenTelemetry openTelemetry = OpenTelemetry.noop();
|
private final OpenTelemetrySdk openTelemetrySdk;
|
||||||
@Nullable private OpenTelemetrySdk openTelemetrySdk;
|
|
||||||
|
|
||||||
@Nullable private Tracer tracer;
|
private final Tracer tracer;
|
||||||
|
|
||||||
private boolean mojosInstrumentationEnabled;
|
private final boolean mojosInstrumentationEnabled;
|
||||||
|
|
||||||
/** Visible for testing */
|
private boolean disposed;
|
||||||
@Nullable AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk;
|
|
||||||
|
|
||||||
@Override
|
public OpenTelemetrySdkService() {
|
||||||
public synchronized void dispose() {
|
logger.debug(
|
||||||
logger.debug("OpenTelemetry: dispose OpenTelemetrySdkService...");
|
"OpenTelemetry: Initialize OpenTelemetrySdkService v{}...",
|
||||||
OpenTelemetrySdk openTelemetrySdk = this.openTelemetrySdk;
|
MavenOtelSemanticAttributes.TELEMETRY_DISTRO_VERSION_VALUE);
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize() {
|
|
||||||
logger.debug("OpenTelemetry: Initialize OpenTelemetrySdkService v{}...", VERSION);
|
|
||||||
|
|
||||||
// Change default of "otel.[traces,metrics,logs].exporter" from "otlp" to "none"
|
// Change default of "otel.[traces,metrics,logs].exporter" from "otlp" to "none"
|
||||||
// The impacts are
|
// The impacts are
|
||||||
|
@ -80,36 +58,48 @@ public final class OpenTelemetrySdkService implements Initializable, Disposable
|
||||||
properties.put("otel.metrics.exporter", "none");
|
properties.put("otel.metrics.exporter", "none");
|
||||||
properties.put("otel.logs.exporter", "none");
|
properties.put("otel.logs.exporter", "none");
|
||||||
|
|
||||||
this.autoConfiguredOpenTelemetrySdk =
|
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk =
|
||||||
AutoConfiguredOpenTelemetrySdk.builder()
|
AutoConfiguredOpenTelemetrySdk.builder()
|
||||||
.setServiceClassLoader(getClass().getClassLoader())
|
.setServiceClassLoader(getClass().getClassLoader())
|
||||||
.addPropertiesSupplier(() -> properties)
|
.addPropertiesSupplier(() -> properties)
|
||||||
.disableShutdownHook()
|
.disableShutdownHook()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("OpenTelemetry: OpenTelemetry SDK initialized");
|
|
||||||
}
|
|
||||||
this.openTelemetrySdk = autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
|
this.openTelemetrySdk = autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
|
||||||
this.openTelemetry = this.openTelemetrySdk;
|
|
||||||
|
|
||||||
Boolean mojoSpansEnabled = getBooleanConfig("otel.instrumentation.maven.mojo.enabled");
|
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);
|
this.tracer = openTelemetrySdk.getTracer("io.opentelemetry.contrib.maven", VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
@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 OpenTelemetry SDK (done: {})",
|
||||||
|
openTelemetrySdkShutdownResult.isDone());
|
||||||
|
}
|
||||||
|
this.disposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tracer getTracer() {
|
public Tracer getTracer() {
|
||||||
Tracer tracer = this.tracer;
|
return this.tracer;
|
||||||
if (tracer == null) {
|
|
||||||
throw new IllegalStateException("Not initialized");
|
|
||||||
}
|
|
||||||
return tracer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link ContextPropagators} for this {@link OpenTelemetry}. */
|
/** Returns the {@link ContextPropagators} for this {@link OpenTelemetry}. */
|
||||||
public ContextPropagators getPropagators() {
|
public ContextPropagators getPropagators() {
|
||||||
return openTelemetry.getPropagators();
|
return this.openTelemetrySdk.getPropagators();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMojosInstrumentationEnabled() {
|
public boolean isMojosInstrumentationEnabled() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.apache.maven.execution.AbstractExecutionListener;
|
import org.apache.maven.execution.AbstractExecutionListener;
|
||||||
import org.apache.maven.execution.ExecutionEvent;
|
import org.apache.maven.execution.ExecutionEvent;
|
||||||
|
@ -29,20 +30,15 @@ import org.apache.maven.execution.MavenSession;
|
||||||
import org.apache.maven.lifecycle.LifecycleExecutionException;
|
import org.apache.maven.lifecycle.LifecycleExecutionException;
|
||||||
import org.apache.maven.plugin.MojoExecution;
|
import org.apache.maven.plugin.MojoExecution;
|
||||||
import org.apache.maven.project.MavenProject;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the OpenTelemetry SDK (see {@link OpenTelemetrySdkService#dispose()}) on the end of
|
* Don't mark this class as {@link javax.inject.Named} and {@link javax.inject.Singleton} because
|
||||||
* execution of the last project ({@link #projectSucceeded(ExecutionEvent)} and {@link
|
* Maven Sisu doesn't automatically load instance of {@link ExecutionListener} as Maven Extension
|
||||||
* #projectFailed(ExecutionEvent)}) rather than on the end of the Maven session {@link
|
* hooks the same way Maven Plexus did so we manually hook this instance of {@link
|
||||||
* #sessionEnded(ExecutionEvent)} because OpenTelemetry and GRPC classes are unloaded by the Maven
|
* ExecutionListener} through the {@link OtelLifecycleParticipant#afterProjectsRead(MavenSession)}.
|
||||||
* 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 {
|
public final class OtelExecutionListener extends AbstractExecutionListener {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(OtelExecutionListener.class);
|
private static final Logger logger = LoggerFactory.getLogger(OtelExecutionListener.class);
|
||||||
|
@ -56,17 +52,16 @@ public final class OtelExecutionListener extends AbstractExecutionListener {
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<Scope> MOJO_EXECUTION_SCOPE = new ThreadLocal<>();
|
private static final ThreadLocal<Scope> MOJO_EXECUTION_SCOPE = new ThreadLocal<>();
|
||||||
|
|
||||||
@SuppressWarnings("NullAway") // Automatically initialized by DI
|
private final SpanRegistry spanRegistry;
|
||||||
@Requirement
|
|
||||||
private SpanRegistry spanRegistry;
|
|
||||||
|
|
||||||
@SuppressWarnings("NullAway") // Automatically initialized by DI
|
private final OpenTelemetrySdkService openTelemetrySdkService;
|
||||||
@Requirement
|
|
||||||
private OpenTelemetrySdkService openTelemetrySdkService;
|
|
||||||
|
|
||||||
private final Map<MavenGoal, MojoGoalExecutionHandler> mojoGoalExecutionHandlers;
|
private final Map<MavenGoal, MojoGoalExecutionHandler> mojoGoalExecutionHandlers;
|
||||||
|
|
||||||
public OtelExecutionListener() {
|
OtelExecutionListener(
|
||||||
|
SpanRegistry spanRegistry, OpenTelemetrySdkService openTelemetrySdkService) {
|
||||||
|
this.spanRegistry = spanRegistry;
|
||||||
|
this.openTelemetrySdkService = openTelemetrySdkService;
|
||||||
this.mojoGoalExecutionHandlers =
|
this.mojoGoalExecutionHandlers =
|
||||||
MojoGoalExecutionHandlerConfiguration.loadMojoGoalExecutionHandler(
|
MojoGoalExecutionHandlerConfiguration.loadMojoGoalExecutionHandler(
|
||||||
OtelExecutionListener.class.getClassLoader());
|
OtelExecutionListener.class.getClassLoader());
|
||||||
|
@ -102,36 +97,6 @@ public final class OtelExecutionListener extends AbstractExecutionListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
@Override
|
||||||
public void sessionStarted(ExecutionEvent executionEvent) {
|
public void sessionStarted(ExecutionEvent executionEvent) {
|
||||||
MavenProject project = executionEvent.getSession().getTopLevelProject();
|
MavenProject project = executionEvent.getSession().getTopLevelProject();
|
||||||
|
@ -370,7 +335,7 @@ public final class OtelExecutionListener extends AbstractExecutionListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sessionEnded(ExecutionEvent event) {
|
public void sessionEnded(ExecutionEvent event) {
|
||||||
logger.debug("OpenTelemetry: Maven session ended");
|
logger.debug("OpenTelemetry: Maven session ended, end root span");
|
||||||
spanRegistry.removeRootSpan().end();
|
spanRegistry.removeRootSpan().end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +347,7 @@ public final class OtelExecutionListener extends AbstractExecutionListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public String get(@Nullable Map<String, String> environmentVariables, String key) {
|
public String get(@Nullable Map<String, String> environmentVariables, @Nonnull String key) {
|
||||||
return environmentVariables == null
|
return environmentVariables == null
|
||||||
? null
|
? null
|
||||||
: environmentVariables.get(key.toUpperCase(Locale.ROOT));
|
: environmentVariables.get(key.toUpperCase(Locale.ROOT));
|
||||||
|
|
|
@ -5,42 +5,59 @@
|
||||||
|
|
||||||
package io.opentelemetry.maven;
|
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.AbstractMavenLifecycleParticipant;
|
||||||
import org.apache.maven.execution.ExecutionListener;
|
import org.apache.maven.execution.ExecutionListener;
|
||||||
import org.apache.maven.execution.MavenSession;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/** Add the {@link OtelExecutionListener} to the lifecycle of the Maven execution */
|
/** Add the {@link OtelExecutionListener} to the lifecycle of the Maven execution */
|
||||||
@Component(role = AbstractMavenLifecycleParticipant.class)
|
@Named
|
||||||
|
@Singleton
|
||||||
public final class OtelLifecycleParticipant extends AbstractMavenLifecycleParticipant {
|
public final class OtelLifecycleParticipant extends AbstractMavenLifecycleParticipant {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(OtelLifecycleParticipant.class);
|
private static final Logger logger = LoggerFactory.getLogger(OtelLifecycleParticipant.class);
|
||||||
|
|
||||||
@SuppressWarnings("NullAway") // Automatically initialized by DI
|
private final OtelExecutionListener otelExecutionListener;
|
||||||
@Requirement(role = ExecutionListener.class, hint = "otel-execution-listener")
|
|
||||||
private 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) {
|
||||||
|
this.otelExecutionListener = new OtelExecutionListener(spanRegistry, openTelemetrySdkService);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For an unknown reason, {@link #afterProjectsRead(MavenSession)} is invoked when the module is
|
* 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
|
@Override
|
||||||
public void afterProjectsRead(MavenSession session) {
|
public void afterProjectsRead(MavenSession session) {
|
||||||
OtelExecutionListener.registerOtelExecutionListener(session, this.otelExecutionListener);
|
ExecutionListener initialExecutionListener = session.getRequest().getExecutionListener();
|
||||||
logger.debug("OpenTelemetry: afterProjectsRead");
|
if (initialExecutionListener instanceof ChainedExecutionListener
|
||||||
}
|
|| initialExecutionListener instanceof OtelExecutionListener) {
|
||||||
|
// already initialized
|
||||||
@Override
|
logger.debug(
|
||||||
public void afterSessionStart(MavenSession session) {
|
"OpenTelemetry: OpenTelemetry extension already registered as execution listener, skip.");
|
||||||
OtelExecutionListener.registerOtelExecutionListener(session, this.otelExecutionListener);
|
} else if (initialExecutionListener == null) {
|
||||||
logger.debug("OpenTelemetry: afterSessionStart");
|
session.getRequest().setExecutionListener(this.otelExecutionListener);
|
||||||
}
|
logger.debug(
|
||||||
|
"OpenTelemetry: OpenTelemetry extension registered as execution listener. No execution listener initially defined");
|
||||||
@Override
|
} else {
|
||||||
public void afterSessionEnd(MavenSession session) {
|
session
|
||||||
logger.debug("OpenTelemetry: afterSessionEnd");
|
.getRequest()
|
||||||
|
.setExecutionListener(
|
||||||
|
new ChainedExecutionListener(this.otelExecutionListener, initialExecutionListener));
|
||||||
|
logger.debug(
|
||||||
|
"OpenTelemetry: OpenTelemetry extension registered as execution listener. InitialExecutionListener: "
|
||||||
|
+ initialExecutionListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
import org.apache.maven.model.Plugin;
|
import org.apache.maven.model.Plugin;
|
||||||
import org.apache.maven.plugin.MojoExecution;
|
import org.apache.maven.plugin.MojoExecution;
|
||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
import org.codehaus.plexus.component.annotations.Component;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -26,7 +27,8 @@ import org.slf4j.LoggerFactory;
|
||||||
* Daemon</a>, can't execute multiple builds concurrently, there is no need to differentiate spans
|
* Daemon</a>, can't execute multiple builds concurrently, there is no need to differentiate spans
|
||||||
* per {@link org.apache.maven.execution.MavenSession}.
|
* per {@link org.apache.maven.execution.MavenSession}.
|
||||||
*/
|
*/
|
||||||
@Component(role = SpanRegistry.class)
|
@Singleton
|
||||||
|
@Named
|
||||||
public final class SpanRegistry {
|
public final class SpanRegistry {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SpanRegistry.class);
|
private static final Logger logger = LoggerFactory.getLogger(SpanRegistry.class);
|
||||||
|
|
|
@ -17,7 +17,6 @@ import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.artifact.repository.ArtifactRepository;
|
|
||||||
import org.apache.maven.execution.ExecutionEvent;
|
import org.apache.maven.execution.ExecutionEvent;
|
||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -36,7 +35,9 @@ final class MavenDeployHandler implements MojoGoalExecutionHandler {
|
||||||
spanBuilder.setSpanKind(SpanKind.CLIENT);
|
spanBuilder.setSpanKind(SpanKind.CLIENT);
|
||||||
|
|
||||||
MavenProject project = execution.getProject();
|
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) {
|
if (optRepository == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
package io.opentelemetry.maven.handler;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
|
@ -3,11 +3,7 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.FIELD)
|
@ParametersAreNonnullByDefault
|
||||||
@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.PARAMETER)
|
|
||||||
@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.RETURN)
|
|
||||||
package io.opentelemetry.maven;
|
package io.opentelemetry.maven;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
import org.checkerframework.framework.qual.TypeUseLocation;
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||||
import io.opentelemetry.sdk.resources.Resource;
|
import io.opentelemetry.sdk.resources.Resource;
|
||||||
import io.opentelemetry.semconv.ServiceAttributes;
|
import io.opentelemetry.semconv.ServiceAttributes;
|
||||||
|
import io.opentelemetry.semconv.incubating.TelemetryIncubatingAttributes;
|
||||||
import org.apache.maven.rtinfo.RuntimeInformation;
|
import org.apache.maven.rtinfo.RuntimeInformation;
|
||||||
import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation;
|
import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation;
|
||||||
|
|
||||||
|
@ -22,6 +23,12 @@ public class MavenResourceProvider implements ResourceProvider {
|
||||||
return Resource.builder()
|
return Resource.builder()
|
||||||
.put(ServiceAttributes.SERVICE_NAME, MavenOtelSemanticAttributes.SERVICE_NAME_VALUE)
|
.put(ServiceAttributes.SERVICE_NAME, MavenOtelSemanticAttributes.SERVICE_NAME_VALUE)
|
||||||
.put(ServiceAttributes.SERVICE_VERSION, runtimeInformation.getMavenVersion())
|
.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();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
package io.opentelemetry.maven.resources;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
|
@ -9,6 +9,7 @@ import static io.opentelemetry.api.common.AttributeKey.stringArrayKey;
|
||||||
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||||
|
|
||||||
import io.opentelemetry.api.common.AttributeKey;
|
import io.opentelemetry.api.common.AttributeKey;
|
||||||
|
import io.opentelemetry.maven.OpenTelemetrySdkService;
|
||||||
import io.opentelemetry.semconv.incubating.ContainerIncubatingAttributes;
|
import io.opentelemetry.semconv.incubating.ContainerIncubatingAttributes;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -55,5 +56,10 @@ public class MavenOtelSemanticAttributes {
|
||||||
|
|
||||||
public static final String SERVICE_NAME_VALUE = "maven";
|
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() {}
|
private MavenOtelSemanticAttributes() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,6 @@
|
||||||
<exportedPackage>io.opentelemetry.api.metrics</exportedPackage>
|
<exportedPackage>io.opentelemetry.api.metrics</exportedPackage>
|
||||||
<exportedPackage>io.opentelemetry.api.trace</exportedPackage>
|
<exportedPackage>io.opentelemetry.api.trace</exportedPackage>
|
||||||
<exportedPackage>io.opentelemetry.context</exportedPackage>
|
<exportedPackage>io.opentelemetry.context</exportedPackage>
|
||||||
|
<exportedPackage>io.opentelemetry.context.propagation</exportedPackage>
|
||||||
</exportedPackages>
|
</exportedPackages>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<component-set>
|
|
||||||
<components>
|
|
||||||
<component>
|
|
||||||
<role>io.opentelemetry.maven.OpenTelemetrySdkService</role>
|
|
||||||
<role-hint>opentelemetry-service</role-hint>
|
|
||||||
<implementation>io.opentelemetry.maven.OpenTelemetrySdkService</implementation>
|
|
||||||
<description />
|
|
||||||
<isolated-realm>false</isolated-realm>
|
|
||||||
<requirements>
|
|
||||||
<requirement>
|
|
||||||
<role>org.apache.maven.rtinfo.RuntimeInformation</role>
|
|
||||||
<field-name>runtimeInformation</field-name>
|
|
||||||
</requirement>
|
|
||||||
</requirements>
|
|
||||||
</component>
|
|
||||||
<component>
|
|
||||||
<role>io.opentelemetry.maven.SpanRegistry</role>
|
|
||||||
<role-hint>default</role-hint>
|
|
||||||
<implementation>io.opentelemetry.maven.SpanRegistry</implementation>
|
|
||||||
<description />
|
|
||||||
<isolated-realm>false</isolated-realm>
|
|
||||||
</component>
|
|
||||||
<component>
|
|
||||||
<role>org.apache.maven.AbstractMavenLifecycleParticipant</role>
|
|
||||||
<role-hint>default</role-hint>
|
|
||||||
<implementation>io.opentelemetry.maven.OtelLifecycleParticipant</implementation>
|
|
||||||
<description />
|
|
||||||
<isolated-realm>false</isolated-realm>
|
|
||||||
<requirements>
|
|
||||||
<requirement>
|
|
||||||
<role>org.apache.maven.execution.ExecutionListener</role>
|
|
||||||
<role-hint>otel-execution-listener</role-hint>
|
|
||||||
<field-name>otelExecutionListener</field-name>
|
|
||||||
</requirement>
|
|
||||||
</requirements>
|
|
||||||
</component>
|
|
||||||
<component>
|
|
||||||
<role>org.apache.maven.execution.ExecutionListener</role>
|
|
||||||
<role-hint>otel-execution-listener</role-hint>
|
|
||||||
<implementation>io.opentelemetry.maven.OtelExecutionListener</implementation>
|
|
||||||
<description />
|
|
||||||
<isolated-realm>false</isolated-realm>
|
|
||||||
<requirements>
|
|
||||||
<requirement>
|
|
||||||
<role>io.opentelemetry.maven.SpanRegistry</role>
|
|
||||||
<field-name>spanRegistry</field-name>
|
|
||||||
</requirement>
|
|
||||||
<requirement>
|
|
||||||
<role>io.opentelemetry.maven.OpenTelemetrySdkService</role>
|
|
||||||
<field-name>openTelemetrySdkService</field-name>
|
|
||||||
</requirement>
|
|
||||||
</requirements>
|
|
||||||
</component>
|
|
||||||
</components>
|
|
||||||
</component-set>
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
io.opentelemetry.maven.OpenTelemetrySdkService
|
||||||
|
io.opentelemetry.maven.OtelLifecycleParticipant
|
||||||
|
io.opentelemetry.maven.SpanRegistry
|
Loading…
Reference in New Issue