From 907cde8b03cc2b5d0ee878294ed134315ac91492 Mon Sep 17 00:00:00 2001 From: Jan Engehausen Date: Sun, 4 May 2025 14:08:08 +0200 Subject: [PATCH 1/8] initial commit --- maven-extension/build.gradle.kts | 2 +- .../maven/ChainedTransferListener.java | 70 ++++++++ .../maven/OpenTelemetrySdkService.java | 9 + .../maven/OtelExecutionListener.java | 18 -- .../maven/OtelLifecycleParticipant.java | 57 +++++++ .../maven/OtelTransferListener.java | 156 ++++++++++++++++++ .../io/opentelemetry/maven/SpanRegistry.java | 38 +++++ .../maven/ToUpperCaseTextMapGetter.java | 28 ++++ .../semconv/MavenOtelSemanticAttributes.java | 7 + 9 files changed, 366 insertions(+), 19 deletions(-) create mode 100644 maven-extension/src/main/java/io/opentelemetry/maven/ChainedTransferListener.java create mode 100644 maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java create mode 100644 maven-extension/src/main/java/io/opentelemetry/maven/ToUpperCaseTextMapGetter.java diff --git a/maven-extension/build.gradle.kts b/maven-extension/build.gradle.kts index 4304534f8..0b3c4e993 100644 --- a/maven-extension/build.gradle.kts +++ b/maven-extension/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } // NOTE -// `META-INF/sis/javax.inject.Named` is manually handled under src/main/resources because there is +// `META-INF/sisu/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" diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/ChainedTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/ChainedTransferListener.java new file mode 100644 index 000000000..692d1aff3 --- /dev/null +++ b/maven-extension/src/main/java/io/opentelemetry/maven/ChainedTransferListener.java @@ -0,0 +1,70 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.maven; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.eclipse.aether.transfer.TransferCancelledException; +import org.eclipse.aether.transfer.TransferEvent; +import org.eclipse.aether.transfer.TransferListener; + +/** + * Util class to chain multiple {@link TransferListener} as Maven APIs don't offer this capability. + */ +final class ChainedTransferListener implements TransferListener { + + private final List listeners; + + /** + * @param listeners {@code null} values are filtered + */ + ChainedTransferListener(TransferListener... listeners) { + this.listeners = Arrays.stream(listeners).filter(e -> e != null).collect(Collectors.toList()); + } + + @Override + public void transferInitiated(TransferEvent event) throws TransferCancelledException { + for (TransferListener listener : this.listeners) { + listener.transferInitiated(event); + } + } + + @Override + public void transferStarted(TransferEvent event) throws TransferCancelledException { + for (TransferListener listener : this.listeners) { + listener.transferStarted(event); + } + } + + @Override + public void transferProgressed(TransferEvent event) throws TransferCancelledException { + for (TransferListener listener : this.listeners) { + listener.transferProgressed(event); + } + } + + @Override + public void transferCorrupted(TransferEvent event) throws TransferCancelledException { + for (TransferListener listener : this.listeners) { + listener.transferCorrupted(event); + } + } + + @Override + public void transferSucceeded(TransferEvent event) { + for (TransferListener listener : this.listeners) { + listener.transferSucceeded(event); + } + } + + @Override + public void transferFailed(TransferEvent event) { + for (TransferListener listener : this.listeners) { + listener.transferFailed(event); + } + } +} 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 a357b3177..a40a2c7b0 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -49,6 +49,8 @@ public final class OpenTelemetrySdkService implements Closeable { private final boolean mojosInstrumentationEnabled; + private final boolean transferInstrumentationEnabled; + private boolean disposed; public OpenTelemetrySdkService() { @@ -76,6 +78,9 @@ public OpenTelemetrySdkService() { this.mojosInstrumentationEnabled = configProperties.getBoolean("otel.instrumentation.maven.mojo.enabled", true); + // TODO maybe default would be false + this.transferInstrumentationEnabled = + configProperties.getBoolean("otel.instrumentation.maven.transfer.enabled", true); this.tracer = openTelemetrySdk.getTracer("io.opentelemetry.contrib.maven", VERSION); } @@ -154,4 +159,8 @@ public ContextPropagators getPropagators() { public boolean isMojosInstrumentationEnabled() { return mojosInstrumentationEnabled; } + + public boolean isTransferInstrumentationEnabled() { + return transferInstrumentationEnabled; + } } 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 8da5c3acd..830412f7f 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelExecutionListener.java @@ -17,12 +17,9 @@ import io.opentelemetry.maven.handler.MojoGoalExecutionHandler; import io.opentelemetry.maven.handler.MojoGoalExecutionHandlerConfiguration; import io.opentelemetry.maven.semconv.MavenOtelSemanticAttributes; -import java.util.Locale; 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; @@ -338,19 +335,4 @@ public void sessionEnded(ExecutionEvent event) { logger.debug("OpenTelemetry: Maven session ended, end root span"); spanRegistry.removeRootSpan().end(); } - - private static class ToUpperCaseTextMapGetter implements TextMapGetter> { - @Override - public Iterable keys(Map environmentVariables) { - return environmentVariables.keySet(); - } - - @Override - @Nullable - 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 d613f9607..9a2262f27 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java @@ -11,6 +11,9 @@ import org.apache.maven.AbstractMavenLifecycleParticipant; import org.apache.maven.execution.ExecutionListener; import org.apache.maven.execution.MavenSession; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.transfer.TransferListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +28,8 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic private final OtelExecutionListener otelExecutionListener; + private final OtelTransferListener otelTransferListener; + /** * Manually instantiate {@link OtelExecutionListener} and hook it in the Maven build lifecycle * because Maven Sisu doesn't load it when Maven Plexus did. @@ -34,6 +39,17 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic OpenTelemetrySdkService openTelemetrySdkService, SpanRegistry spanRegistry) { this.openTelemetrySdkService = openTelemetrySdkService; this.otelExecutionListener = new OtelExecutionListener(spanRegistry, openTelemetrySdkService); + this.otelTransferListener = new OtelTransferListener(spanRegistry, openTelemetrySdkService); + } + + @Override + public void afterSessionStart(MavenSession session) { + // TODO transfers happen before afterProjectsRead() - not sure I understand the issue in the + // comment of afterProjectsRead() + if (openTelemetrySdkService.isTransferInstrumentationEnabled()) { + registerTransferListener(session); + otelTransferListener.startTransferRoot(); + } } /** @@ -43,6 +59,13 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic */ @Override public void afterProjectsRead(MavenSession session) { + if (openTelemetrySdkService.isTransferInstrumentationEnabled()) { + otelTransferListener.endTransferRoot(); + } + registerExecutionListener(session); + } + + void registerExecutionListener(MavenSession session) { ExecutionListener initialExecutionListener = session.getRequest().getExecutionListener(); if (initialExecutionListener instanceof ChainedExecutionListener || initialExecutionListener instanceof OtelExecutionListener) { @@ -64,6 +87,40 @@ public void afterProjectsRead(MavenSession session) { } } + void registerTransferListener(MavenSession session) { + RepositorySystemSession repositorySession = session.getRepositorySession(); + TransferListener initialTransferListener = repositorySession.getTransferListener(); + if (initialTransferListener instanceof ChainedTransferListener + || initialTransferListener instanceof OtelTransferListener) { + // already initialized + logger.debug( + "OpenTelemetry: OpenTelemetry extension already registered as transfer listener, skip."); + } else if (initialTransferListener == null) { + setTransferListener(this.otelTransferListener, repositorySession, session); + logger.debug( + "OpenTelemetry: OpenTelemetry extension registered as transfer listener. No transfer listener initially defined"); + } else { + setTransferListener( + new ChainedTransferListener(this.otelTransferListener, initialTransferListener), + repositorySession, + session); + logger.debug( + "OpenTelemetry: OpenTelemetry extension registered as transfer listener. InitialTransferListener: {}", + initialTransferListener); + } + } + + void setTransferListener( + TransferListener transferListener, + RepositorySystemSession repositorySession, + MavenSession session) { + if (repositorySession instanceof DefaultRepositorySystemSession) { + ((DefaultRepositorySystemSession) repositorySession).setTransferListener(transferListener); + } else { + logger.warn("OpenTelemetry: Cannot set transfer listener"); + } + } + @Override public void afterSessionEnd(MavenSession session) { // Workaround https://issues.apache.org/jira/browse/MNG-8217 diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java new file mode 100644 index 000000000..2c0e1dbd2 --- /dev/null +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -0,0 +1,156 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.maven; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.context.Context; +import io.opentelemetry.maven.semconv.MavenOtelSemanticAttributes; +import java.util.Locale; +import java.util.Optional; +import org.apache.maven.execution.ExecutionListener; +import org.apache.maven.execution.MavenSession; +import org.eclipse.aether.transfer.AbstractTransferListener; +import org.eclipse.aether.transfer.TransferEvent; +import org.eclipse.aether.transfer.TransferResource; +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 OtelTransferListener extends AbstractTransferListener { + + private static final Logger logger = LoggerFactory.getLogger(OtelTransferListener.class); + + private final SpanRegistry spanRegistry; + + private final OpenTelemetrySdkService openTelemetrySdkService; + + OtelTransferListener(SpanRegistry spanRegistry, OpenTelemetrySdkService openTelemetrySdkService) { + this.spanRegistry = spanRegistry; + this.openTelemetrySdkService = openTelemetrySdkService; + } + + /** + * Starts a span to collect transfers that occur before regular execution spans can serve as + * parents. + */ + public void startTransferRoot() { + io.opentelemetry.context.Context context = + openTelemetrySdkService + .getPropagators() + .getTextMapPropagator() + .extract( + io.opentelemetry.context.Context.current(), + System.getenv(), + new ToUpperCaseTextMapGetter()); + + // TODO question: is this the root span name we want? + String spanName = "Transfer: global"; + logger.debug("OpenTelemetry: Start span: {}", spanName); + Span transferSpan = + this.openTelemetrySdkService + .getTracer() + .spanBuilder(spanName) + .setParent(context) + .setSpanKind(SpanKind.SERVER) + .startSpan(); + spanRegistry.setRootSpan(transferSpan); + } + + /** Ends the root span. */ + public void endTransferRoot() { + spanRegistry.getRootSpanNotNull().end(); + } + + @Override + public void transferInitiated(TransferEvent event) { + ResourceInformation info = createResourceInformation(event); + + logger.debug("OpenTelemetry: Maven transfer initiated: span {}:{}", info.type, info.url); + + SpanBuilder spanBuilder = + this.openTelemetrySdkService + .getTracer() + .spanBuilder(info.type + ":" + info.url) + .setParent( + Context.current() + .with(Span.wrap(spanRegistry.getRootSpanNotNull().getSpanContext()))) + .setAttribute(MavenOtelSemanticAttributes.MAVEN_TRANSFER_URL, info.url) + .setAttribute(MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, info.type); + + spanRegistry.putSpan(spanBuilder.startSpan(), event); + } + + @Override + public void transferSucceeded(TransferEvent event) { + ResourceInformation info = createResourceInformation(event); + + logger.debug("OpenTelemetry: Maven transfer succeeded: span {}:{}", info.type, info.url); + + Optional.ofNullable(spanRegistry.removeSpan(event)) + .ifPresent( + span -> { + span.setStatus(StatusCode.OK); + finish(span, event); + }); + } + + @Override + public void transferFailed(TransferEvent event) { + ResourceInformation info = createResourceInformation(event); + + logger.debug("OpenTelemetry: Maven transfer failed: span {}:{}", info.type, info.url); + + Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); + } + + @Override + public void transferCorrupted(TransferEvent event) { + ResourceInformation info = createResourceInformation(event); + + logger.debug("OpenTelemetry: Maven transfer corrupted: span {}:{}", info.type, info.url); + + Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); + } + + void finish(Span span, TransferEvent event) { + span.setAttribute( + MavenOtelSemanticAttributes.MAVEN_TRANSFER_SIZE, + Long.toString(event.getTransferredBytes())); + span.end(); + } + + void fail(Span span, TransferEvent event) { + span.setStatus( + StatusCode.ERROR, + Optional.ofNullable(event.getException()).map(Exception::getMessage).orElse("n/a")); + finish(span, event); + } + + ResourceInformation createResourceInformation(TransferEvent event) { + TransferResource resource = event.getResource(); + return new ResourceInformation( + resource.getRepositoryUrl() + resource.getResourceName(), + event.getRequestType().toString().toLowerCase(Locale.ROOT)); + } + + private static class ResourceInformation { + protected final String url; + protected final String type; + + ResourceInformation(String url, String type) { + this.url = url; + this.type = type; + } + } +} 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 276f1e116..85ef5c2e7 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/SpanRegistry.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/SpanRegistry.java @@ -17,6 +17,9 @@ import org.apache.maven.model.Plugin; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.transfer.TransferEvent; +import org.eclipse.aether.transfer.TransferResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +38,7 @@ public final class SpanRegistry { private final Map mojoExecutionKeySpanMap = new ConcurrentHashMap<>(); private final Map mavenProjectKeySpanMap = new ConcurrentHashMap<>(); + private final Map transferKeySpanMap = new ConcurrentHashMap<>(); @Nullable private Span rootSpan; /** @@ -113,6 +117,15 @@ public void putSpan(Span span, MojoExecution mojoExecution, MavenProject project } } + public void putSpan(Span span, TransferEvent event) { + TransferKey key = TransferKey.fromTransferEvent(event); + logger.debug("OpenTelemetry: putSpan({})", key); + Span previousSpanForKey = transferKeySpanMap.put(key, span); + if (previousSpanForKey != null) { + logger.warn("A span has already been started for " + key); + } + } + public Span removeSpan(MavenProject mavenProject) { logger.debug("OpenTelemetry: removeSpan({})", mavenProject); MavenProjectKey key = MavenProjectKey.fromMavenProject(mavenProject); @@ -136,6 +149,17 @@ public Span removeSpan(MojoExecution mojoExecution, MavenProject project) { return span; } + public Span removeSpan(TransferEvent event) { + TransferKey key = TransferKey.fromTransferEvent(event); + logger.debug("OpenTelemetry: removeSpan({})", key); + Span span = transferKeySpanMap.remove(key); + if (span == null) { + logger.warn("No span found for " + key); + return Span.getInvalid(); + } + return span; + } + @AutoValue abstract static class MavenProjectKey { abstract String groupId(); @@ -185,4 +209,18 @@ static MojoExecutionKey fromMojoExecution(MojoExecution mojoExecution, MavenProj MavenProjectKey.fromMavenProject(project)); } } + + @AutoValue + abstract static class TransferKey { + abstract String resourceName(); + + abstract String sessionId(); + + public static TransferKey fromTransferEvent(@Nonnull TransferEvent event) { + TransferResource resource = event.getResource(); + RepositorySystemSession session = event.getSession(); + return new AutoValue_SpanRegistry_TransferKey( + resource.getResourceName(), "session-" + System.identityHashCode(session)); + } + } } diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/ToUpperCaseTextMapGetter.java b/maven-extension/src/main/java/io/opentelemetry/maven/ToUpperCaseTextMapGetter.java new file mode 100644 index 000000000..e02b7b3e0 --- /dev/null +++ b/maven-extension/src/main/java/io/opentelemetry/maven/ToUpperCaseTextMapGetter.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.maven; + +import io.opentelemetry.context.propagation.TextMapGetter; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +final class ToUpperCaseTextMapGetter implements TextMapGetter> { + @Override + public Set keys(Map environmentVariables) { + return environmentVariables.keySet(); + } + + @Override + @Nullable + 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/semconv/MavenOtelSemanticAttributes.java b/maven-extension/src/main/java/io/opentelemetry/maven/semconv/MavenOtelSemanticAttributes.java index c5d821e31..016adfe29 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 @@ -36,6 +36,7 @@ public class MavenOtelSemanticAttributes { stringKey("maven.build.repository.id"); public static final AttributeKey MAVEN_BUILD_REPOSITORY_URL = stringKey("maven.build.repository.url"); + public static final AttributeKey MAVEN_EXECUTION_GOAL = stringKey("maven.execution.goal"); public static final AttributeKey MAVEN_EXECUTION_ID = stringKey("maven.execution.id"); @@ -52,6 +53,12 @@ public class MavenOtelSemanticAttributes { stringKey("maven.project.groupId"); public static final AttributeKey MAVEN_PROJECT_VERSION = stringKey("maven.project.version"); + public static final AttributeKey MAVEN_TRANSFER_URL = + AttributeKey.stringKey("maven.transfer.url"); + public static final AttributeKey MAVEN_TRANSFER_TYPE = + AttributeKey.stringKey("maven.transfer.type"); + public static final AttributeKey MAVEN_TRANSFER_SIZE = + AttributeKey.stringKey("maven.transfer.size"); public static final String SERVICE_NAME_VALUE = "maven"; From a7eb849c930c1251cb436449bf2112bf33dcff1b Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Mon, 12 May 2025 09:24:41 +0200 Subject: [PATCH 2/8] Iterate on OtelTransferListener --- maven-extension/build.gradle.kts | 2 +- .../maven/OpenTelemetrySdkService.java | 2 +- .../maven/OtelLifecycleParticipant.java | 4 - .../maven/OtelTransferListener.java | 143 +++++++++--------- .../semconv/MavenOtelSemanticAttributes.java | 8 +- 5 files changed, 77 insertions(+), 82 deletions(-) diff --git a/maven-extension/build.gradle.kts b/maven-extension/build.gradle.kts index 0b3c4e993..d14faa992 100644 --- a/maven-extension/build.gradle.kts +++ b/maven-extension/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") implementation("io.opentelemetry:opentelemetry-exporter-otlp") implementation("io.opentelemetry.semconv:opentelemetry-semconv") - testImplementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") + implementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") 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 a40a2c7b0..240117f53 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -54,7 +54,7 @@ public final class OpenTelemetrySdkService implements Closeable { private boolean disposed; public OpenTelemetrySdkService() { - logger.debug( + logger.info( "OpenTelemetry: Initialize OpenTelemetrySdkService v{}...", MavenOtelSemanticAttributes.TELEMETRY_DISTRO_VERSION_VALUE); 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 9a2262f27..b673e34d0 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java @@ -48,7 +48,6 @@ public void afterSessionStart(MavenSession session) { // comment of afterProjectsRead() if (openTelemetrySdkService.isTransferInstrumentationEnabled()) { registerTransferListener(session); - otelTransferListener.startTransferRoot(); } } @@ -59,9 +58,6 @@ public void afterSessionStart(MavenSession session) { */ @Override public void afterProjectsRead(MavenSession session) { - if (openTelemetrySdkService.isTransferInstrumentationEnabled()) { - otelTransferListener.endTransferRoot(); - } registerExecutionListener(session); } diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java index 2c0e1dbd2..f87eefd81 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -9,15 +9,19 @@ import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.context.Context; import io.opentelemetry.maven.semconv.MavenOtelSemanticAttributes; -import java.util.Locale; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.incubating.HttpIncubatingAttributes; +import io.opentelemetry.semconv.incubating.UrlIncubatingAttributes; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Optional; import org.apache.maven.execution.ExecutionListener; import org.apache.maven.execution.MavenSession; import org.eclipse.aether.transfer.AbstractTransferListener; import org.eclipse.aether.transfer.TransferEvent; -import org.eclipse.aether.transfer.TransferResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,62 +44,67 @@ public final class OtelTransferListener extends AbstractTransferListener { this.openTelemetrySdkService = openTelemetrySdkService; } - /** - * Starts a span to collect transfers that occur before regular execution spans can serve as - * parents. - */ - public void startTransferRoot() { - io.opentelemetry.context.Context context = - openTelemetrySdkService - .getPropagators() - .getTextMapPropagator() - .extract( - io.opentelemetry.context.Context.current(), - System.getenv(), - new ToUpperCaseTextMapGetter()); - - // TODO question: is this the root span name we want? - String spanName = "Transfer: global"; - logger.debug("OpenTelemetry: Start span: {}", spanName); - Span transferSpan = - this.openTelemetrySdkService - .getTracer() - .spanBuilder(spanName) - .setParent(context) - .setSpanKind(SpanKind.SERVER) - .startSpan(); - spanRegistry.setRootSpan(transferSpan); - } - - /** Ends the root span. */ - public void endTransferRoot() { - spanRegistry.getRootSpanNotNull().end(); - } - @Override public void transferInitiated(TransferEvent event) { - ResourceInformation info = createResourceInformation(event); + logger.info("OpenTelemetry: OtelTransferListener#transferInitiated({})", event); + + String httpRequestMethod; + switch (event.getRequestType()) { + case PUT: + httpRequestMethod = "PUT"; + break; + case GET: + httpRequestMethod = "GET"; + break; + case GET_EXISTENCE: + httpRequestMethod = "HEAD"; + break; + default: + logger.warn("OpenTelemetry: Unknown request type {}", event.getRequestType()); + httpRequestMethod = event.getRequestType().name(); + } + + String urlTemplate = event.getResource().getRepositoryUrl() + + "$groupId/$version/$artifactId-$version.$classifier"; - logger.debug("OpenTelemetry: Maven transfer initiated: span {}:{}", info.type, info.url); + String spanName = httpRequestMethod + " " + urlTemplate; SpanBuilder spanBuilder = this.openTelemetrySdkService .getTracer() - .spanBuilder(info.type + ":" + info.url) - .setParent( - Context.current() - .with(Span.wrap(spanRegistry.getRootSpanNotNull().getSpanContext()))) - .setAttribute(MavenOtelSemanticAttributes.MAVEN_TRANSFER_URL, info.url) - .setAttribute(MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, info.type); - + .spanBuilder(spanName) + .setSpanKind(SpanKind.CLIENT) + .setAttribute(HttpAttributes.HTTP_REQUEST_METHOD, httpRequestMethod) + .setAttribute(UrlAttributes.URL_PATH, + event.getResource().getRepositoryUrl() + event.getResource().getResourceName()) + .setAttribute(UrlIncubatingAttributes.URL_TEMPLATE, urlTemplate) + .setAttribute(MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, + event.getRequestType().name()); + + // TODO keep in cache the repositoryUrl parsing + Optional.ofNullable(event.getResource().getRepositoryUrl()) + .filter(url -> !url.isEmpty()) + .map(str -> { + try { + return new URI(str); + } catch (URISyntaxException e) { + return null; + } + }) + .ifPresent( + uri -> { + spanBuilder + .setAttribute(ServerAttributes.SERVER_ADDRESS, uri.getHost()); + if (uri.getPort() != -1) { + spanBuilder.setAttribute(ServerAttributes.SERVER_PORT, uri.getPort()); + } + }); spanRegistry.putSpan(spanBuilder.startSpan(), event); } @Override public void transferSucceeded(TransferEvent event) { - ResourceInformation info = createResourceInformation(event); - - logger.debug("OpenTelemetry: Maven transfer succeeded: span {}:{}", info.type, info.url); + logger.info("OpenTelemetry: OtelTransferListener#transferSucceeded({})", event); Optional.ofNullable(spanRegistry.removeSpan(event)) .ifPresent( @@ -107,26 +116,32 @@ public void transferSucceeded(TransferEvent event) { @Override public void transferFailed(TransferEvent event) { - ResourceInformation info = createResourceInformation(event); + logger.info("OpenTelemetry: OtelTransferListener#transferFailed({})", event); - logger.debug("OpenTelemetry: Maven transfer failed: span {}:{}", info.type, info.url); + Optional.ofNullable(spanRegistry.removeSpan(event)) + .ifPresent(span -> fail(span, event)); - Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); } @Override public void transferCorrupted(TransferEvent event) { - ResourceInformation info = createResourceInformation(event); - - logger.debug("OpenTelemetry: Maven transfer corrupted: span {}:{}", info.type, info.url); + logger.info("OpenTelemetry: OtelTransferListener#transferCorrupted({})", event); Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); } void finish(Span span, TransferEvent event) { - span.setAttribute( - MavenOtelSemanticAttributes.MAVEN_TRANSFER_SIZE, - Long.toString(event.getTransferredBytes())); + switch (event.getRequestType()) { + case PUT: + span.setAttribute(HttpIncubatingAttributes.HTTP_REQUEST_BODY_SIZE, + event.getTransferredBytes()); + break; + case GET: + case GET_EXISTENCE: + span.setAttribute(HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE, + event.getTransferredBytes()); + break; + } span.end(); } @@ -137,20 +152,4 @@ void fail(Span span, TransferEvent event) { finish(span, event); } - ResourceInformation createResourceInformation(TransferEvent event) { - TransferResource resource = event.getResource(); - return new ResourceInformation( - resource.getRepositoryUrl() + resource.getResourceName(), - event.getRequestType().toString().toLowerCase(Locale.ROOT)); - } - - private static class ResourceInformation { - protected final String url; - protected final String type; - - ResourceInformation(String url, String type) { - this.url = url; - this.type = type; - } - } } 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 016adfe29..bec4ca726 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 @@ -10,6 +10,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.maven.OpenTelemetrySdkService; +import org.eclipse.aether.transfer.TransferEvent; import java.util.List; /** @@ -53,12 +54,11 @@ public class MavenOtelSemanticAttributes { stringKey("maven.project.groupId"); public static final AttributeKey MAVEN_PROJECT_VERSION = stringKey("maven.project.version"); - public static final AttributeKey MAVEN_TRANSFER_URL = - AttributeKey.stringKey("maven.transfer.url"); + /** + * See {@link TransferEvent.RequestType}. + */ public static final AttributeKey MAVEN_TRANSFER_TYPE = AttributeKey.stringKey("maven.transfer.type"); - public static final AttributeKey MAVEN_TRANSFER_SIZE = - AttributeKey.stringKey("maven.transfer.size"); public static final String SERVICE_NAME_VALUE = "maven"; From 0aab2482c04464c4b1a61f53fe6753c840df586d Mon Sep 17 00:00:00 2001 From: Jan Engehausen Date: Mon, 12 May 2025 18:16:19 +0200 Subject: [PATCH 3/8] cosmetics --- .../maven/OtelTransferListener.java | 58 ++++++++++--------- .../semconv/MavenOtelSemanticAttributes.java | 7 +-- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java index f87eefd81..fdee18d1e 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -17,7 +17,9 @@ import io.opentelemetry.semconv.incubating.UrlIncubatingAttributes; import java.net.URI; import java.net.URISyntaxException; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import org.apache.maven.execution.ExecutionListener; import org.apache.maven.execution.MavenSession; import org.eclipse.aether.transfer.AbstractTransferListener; @@ -39,6 +41,8 @@ public final class OtelTransferListener extends AbstractTransferListener { private final OpenTelemetrySdkService openTelemetrySdkService; + private final Map> repositoryURIs = new ConcurrentHashMap<>(); + OtelTransferListener(SpanRegistry spanRegistry, OpenTelemetrySdkService openTelemetrySdkService) { this.spanRegistry = spanRegistry; this.openTelemetrySdkService = openTelemetrySdkService; @@ -64,8 +68,9 @@ public void transferInitiated(TransferEvent event) { httpRequestMethod = event.getRequestType().name(); } - String urlTemplate = event.getResource().getRepositoryUrl() - + "$groupId/$version/$artifactId-$version.$classifier"; + String urlTemplate = + event.getResource().getRepositoryUrl() + + "$groupId/$artifactId/$version/$artifactId-$version.$classifier"; String spanName = httpRequestMethod + " " + urlTemplate; @@ -75,29 +80,33 @@ public void transferInitiated(TransferEvent event) { .spanBuilder(spanName) .setSpanKind(SpanKind.CLIENT) .setAttribute(HttpAttributes.HTTP_REQUEST_METHOD, httpRequestMethod) - .setAttribute(UrlAttributes.URL_PATH, + .setAttribute( + UrlAttributes.URL_PATH, event.getResource().getRepositoryUrl() + event.getResource().getResourceName()) .setAttribute(UrlIncubatingAttributes.URL_TEMPLATE, urlTemplate) - .setAttribute(MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, - event.getRequestType().name()); - - // TODO keep in cache the repositoryUrl parsing - Optional.ofNullable(event.getResource().getRepositoryUrl()) - .filter(url -> !url.isEmpty()) - .map(str -> { - try { - return new URI(str); - } catch (URISyntaxException e) { - return null; - } - }) + .setAttribute( + MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, event.getRequestType().name()); + + repositoryURIs + .computeIfAbsent( + event.getResource().getRepositoryUrl(), + str -> { + try { + return str.isBlank() ? Optional.empty() : Optional.of(new URI(str)); + } catch (URISyntaxException e) { + return Optional.empty(); + } + }) .ifPresent( uri -> { - spanBuilder - .setAttribute(ServerAttributes.SERVER_ADDRESS, uri.getHost()); + spanBuilder.setAttribute(ServerAttributes.SERVER_ADDRESS, uri.getHost()); if (uri.getPort() != -1) { spanBuilder.setAttribute(ServerAttributes.SERVER_PORT, uri.getPort()); } + // prevent ever increasing size + if (repositoryURIs.size() > 128) { + repositoryURIs.clear(); + } }); spanRegistry.putSpan(spanBuilder.startSpan(), event); } @@ -118,9 +127,7 @@ public void transferSucceeded(TransferEvent event) { public void transferFailed(TransferEvent event) { logger.info("OpenTelemetry: OtelTransferListener#transferFailed({})", event); - Optional.ofNullable(spanRegistry.removeSpan(event)) - .ifPresent(span -> fail(span, event)); - + Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); } @Override @@ -133,13 +140,13 @@ public void transferCorrupted(TransferEvent event) { void finish(Span span, TransferEvent event) { switch (event.getRequestType()) { case PUT: - span.setAttribute(HttpIncubatingAttributes.HTTP_REQUEST_BODY_SIZE, - event.getTransferredBytes()); + span.setAttribute( + HttpIncubatingAttributes.HTTP_REQUEST_BODY_SIZE, event.getTransferredBytes()); break; case GET: case GET_EXISTENCE: - span.setAttribute(HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE, - event.getTransferredBytes()); + span.setAttribute( + HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE, event.getTransferredBytes()); break; } span.end(); @@ -151,5 +158,4 @@ void fail(Span span, TransferEvent event) { Optional.ofNullable(event.getException()).map(Exception::getMessage).orElse("n/a")); finish(span, event); } - } 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 bec4ca726..075bb4a49 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 @@ -10,8 +10,8 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.maven.OpenTelemetrySdkService; -import org.eclipse.aether.transfer.TransferEvent; import java.util.List; +import org.eclipse.aether.transfer.TransferEvent; /** * Semantic attributes for Maven executions. @@ -54,9 +54,8 @@ public class MavenOtelSemanticAttributes { stringKey("maven.project.groupId"); public static final AttributeKey MAVEN_PROJECT_VERSION = stringKey("maven.project.version"); - /** - * See {@link TransferEvent.RequestType}. - */ + + /** See {@link TransferEvent.RequestType}. */ public static final AttributeKey MAVEN_TRANSFER_TYPE = AttributeKey.stringKey("maven.transfer.type"); From 88142d227f0544f1edf49c2782c123db8429159e Mon Sep 17 00:00:00 2001 From: Jan Engehausen Date: Mon, 12 May 2025 18:20:32 +0200 Subject: [PATCH 4/8] cosmetics --- .../main/java/io/opentelemetry/maven/OtelTransferListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java index fdee18d1e..772bcc90d 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -92,7 +92,7 @@ public void transferInitiated(TransferEvent event) { event.getResource().getRepositoryUrl(), str -> { try { - return str.isBlank() ? Optional.empty() : Optional.of(new URI(str)); + return str.isEmpty() ? Optional.empty() : Optional.of(new URI(str)); } catch (URISyntaxException e) { return Optional.empty(); } From 25951df78efb96748326fb8fb8619dda71b704ca Mon Sep 17 00:00:00 2001 From: Jan Engehausen Date: Mon, 12 May 2025 18:24:34 +0200 Subject: [PATCH 5/8] fix variable naming --- .../java/io/opentelemetry/maven/OtelTransferListener.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java index 772bcc90d..655d42a53 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -41,7 +41,7 @@ public final class OtelTransferListener extends AbstractTransferListener { private final OpenTelemetrySdkService openTelemetrySdkService; - private final Map> repositoryURIs = new ConcurrentHashMap<>(); + private final Map> repositoryUriMapping = new ConcurrentHashMap<>(); OtelTransferListener(SpanRegistry spanRegistry, OpenTelemetrySdkService openTelemetrySdkService) { this.spanRegistry = spanRegistry; @@ -87,7 +87,7 @@ public void transferInitiated(TransferEvent event) { .setAttribute( MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, event.getRequestType().name()); - repositoryURIs + repositoryUriMapping .computeIfAbsent( event.getResource().getRepositoryUrl(), str -> { @@ -104,8 +104,8 @@ public void transferInitiated(TransferEvent event) { spanBuilder.setAttribute(ServerAttributes.SERVER_PORT, uri.getPort()); } // prevent ever increasing size - if (repositoryURIs.size() > 128) { - repositoryURIs.clear(); + if (repositoryUriMapping.size() > 128) { + repositoryUriMapping.clear(); } }); spanRegistry.putSpan(spanBuilder.startSpan(), event); From 41caafc46773e3ef7086e10ae65e679055ad0fba Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Mon, 12 May 2025 23:30:47 +0200 Subject: [PATCH 6/8] Iterate on OtelTransferListener --- maven-extension/README.md | 17 +++++++++-------- .../maven/OpenTelemetrySdkService.java | 2 +- .../maven/OtelTransferListener.java | 14 ++++++++------ .../semconv/MavenOtelSemanticAttributes.java | 3 +++ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/maven-extension/README.md b/maven-extension/README.md index 3ae23c7f9..91ec71744 100644 --- a/maven-extension/README.md +++ b/maven-extension/README.md @@ -61,14 +61,15 @@ Without this setting, the traces won't be exported and the OpenTelemetry Maven E The Maven OpenTelemetry Extension supports a subset of the [OpenTelemetry autoconfiguration environment variables and JVM system properties](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure). -| System property
Environment variable | Default value | Description | -|--------------------------------------------------------------------------------------------|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------| -| `otel.traces.exporter`
`OTEL_TRACES_EXPORTER` | `none` | Select the OpenTelemetry exporter for tracing, the currently only supported values are `none` and `otlp`. `none` makes the instrumentation NoOp | -| `otel.exporter.otlp.endpoint`
`OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4317` | The OTLP traces and metrics endpoint to connect to. Must be a URL with a scheme of either `http` or `https` based on the use of TLS. | -| `otel.exporter.otlp.headers`
`OTEL_EXPORTER_OTLP_HEADERS` | | Key-value pairs separated by commas to pass as request headers on OTLP trace and metrics requests. | -| `otel.exporter.otlp.timeout`
`OTEL_EXPORTER_OTLP_TIMEOUT` | `10000` | The maximum waiting time, in milliseconds, allowed to send each OTLP trace and metric batch. | -| `otel.resource.attributes`
`OTEL_RESOURCE_ATTRIBUTES` | | Specify resource attributes in the following format: key1=val1,key2=val2,key3=val3 | -| `otel.instrumentation.maven.mojo.enabled`
`OTEL_INSTRUMENTATION_MAVEN_MOJO_ENABLED` | `true` | Whether to create spans for mojo goal executions, `true` or `false`. Can be configured to reduce the number of spans created for large builds. | +| System property
Environment variable | Default value | Description | +|----------------------------------------------------------------------------------------------------|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `otel.traces.exporter`
`OTEL_TRACES_EXPORTER` | `none` | Select the OpenTelemetry exporter for tracing, the currently only supported values are `none` and `otlp`. `none` makes the instrumentation NoOp | +| `otel.exporter.otlp.endpoint`
`OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4317` | The OTLP traces and metrics endpoint to connect to. Must be a URL with a scheme of either `http` or `https` based on the use of TLS. | +| `otel.exporter.otlp.headers`
`OTEL_EXPORTER_OTLP_HEADERS` | | Key-value pairs separated by commas to pass as request headers on OTLP trace and metrics requests. | +| `otel.exporter.otlp.timeout`
`OTEL_EXPORTER_OTLP_TIMEOUT` | `10000` | The maximum waiting time, in milliseconds, allowed to send each OTLP trace and metric batch. | +| `otel.resource.attributes`
`OTEL_RESOURCE_ATTRIBUTES` | | Specify resource attributes in the following format: key1=val1,key2=val2,key3=val3 | +| `otel.instrumentation.maven.mojo.enabled`
`OTEL_INSTRUMENTATION_MAVEN_MOJO_ENABLED` | `true` | Whether to create spans for mojo goal executions, `true` or `false`. Can be configured to reduce the number of spans created for large builds. | +| `otel.instrumentation.maven.transfer.enabled`
`OTEL_INSTRUMENTATION_MAVEN_TRANSFER_ENABLED` | `false` | Whether to create spans for artifact transfers, `true` or `false`. Can be activated to understand impact of artifact transfers on performances. | ℹ️ The `service.name` is set to `maven` and the `service.version` to the version of the Maven runtime in use. 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 240117f53..4f548579c 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -80,7 +80,7 @@ public OpenTelemetrySdkService() { configProperties.getBoolean("otel.instrumentation.maven.mojo.enabled", true); // TODO maybe default would be false this.transferInstrumentationEnabled = - configProperties.getBoolean("otel.instrumentation.maven.transfer.enabled", true); + configProperties.getBoolean("otel.instrumentation.maven.transfer.enabled", false); this.tracer = openTelemetrySdk.getTracer("io.opentelemetry.contrib.maven", VERSION); } diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java index 655d42a53..4e038b3df 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -50,7 +50,7 @@ public final class OtelTransferListener extends AbstractTransferListener { @Override public void transferInitiated(TransferEvent event) { - logger.info("OpenTelemetry: OtelTransferListener#transferInitiated({})", event); + logger.debug("OpenTelemetry: OtelTransferListener#transferInitiated({})", event); String httpRequestMethod; switch (event.getRequestType()) { @@ -64,7 +64,7 @@ public void transferInitiated(TransferEvent event) { httpRequestMethod = "HEAD"; break; default: - logger.warn("OpenTelemetry: Unknown request type {}", event.getRequestType()); + logger.warn("OpenTelemetry: Unknown request type {} for event {}", event.getRequestType(), event); httpRequestMethod = event.getRequestType().name(); } @@ -74,6 +74,7 @@ public void transferInitiated(TransferEvent event) { String spanName = httpRequestMethod + " " + urlTemplate; + // Build an HTTP client span as the http call itself is not instrumented. SpanBuilder spanBuilder = this.openTelemetrySdkService .getTracer() @@ -85,7 +86,8 @@ public void transferInitiated(TransferEvent event) { event.getResource().getRepositoryUrl() + event.getResource().getResourceName()) .setAttribute(UrlIncubatingAttributes.URL_TEMPLATE, urlTemplate) .setAttribute( - MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, event.getRequestType().name()); + MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, event.getRequestType().name()) + .setAttribute(MavenOtelSemanticAttributes.MAVEN_RESOURCE_NAME, event.getResource().getResourceName()); repositoryUriMapping .computeIfAbsent( @@ -113,7 +115,7 @@ public void transferInitiated(TransferEvent event) { @Override public void transferSucceeded(TransferEvent event) { - logger.info("OpenTelemetry: OtelTransferListener#transferSucceeded({})", event); + logger.debug("OpenTelemetry: OtelTransferListener#transferSucceeded({})", event); Optional.ofNullable(spanRegistry.removeSpan(event)) .ifPresent( @@ -125,14 +127,14 @@ public void transferSucceeded(TransferEvent event) { @Override public void transferFailed(TransferEvent event) { - logger.info("OpenTelemetry: OtelTransferListener#transferFailed({})", event); + logger.debug("OpenTelemetry: OtelTransferListener#transferFailed({})", event); Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); } @Override public void transferCorrupted(TransferEvent event) { - logger.info("OpenTelemetry: OtelTransferListener#transferCorrupted({})", event); + logger.debug("OpenTelemetry: OtelTransferListener#transferCorrupted({})", event); Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); } 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 075bb4a49..d5148e667 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 @@ -58,6 +58,9 @@ public class MavenOtelSemanticAttributes { /** See {@link TransferEvent.RequestType}. */ public static final AttributeKey MAVEN_TRANSFER_TYPE = AttributeKey.stringKey("maven.transfer.type"); + /** See {@link org.eclipse.aether.transfer.TransferResource}. */ + public static final AttributeKey MAVEN_RESOURCE_NAME = + AttributeKey.stringKey("maven.resource.name"); public static final String SERVICE_NAME_VALUE = "maven"; From 2b43900f58f2ef9cd0937985c32b2ce42a275536 Mon Sep 17 00:00:00 2001 From: Jan Engehausen Date: Wed, 14 May 2025 17:49:46 +0200 Subject: [PATCH 7/8] drop leftover TODOs --- .../java/io/opentelemetry/maven/OpenTelemetrySdkService.java | 1 - .../java/io/opentelemetry/maven/OtelLifecycleParticipant.java | 2 -- 2 files changed, 3 deletions(-) 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 4f548579c..0d2e5150e 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -78,7 +78,6 @@ public OpenTelemetrySdkService() { this.mojosInstrumentationEnabled = configProperties.getBoolean("otel.instrumentation.maven.mojo.enabled", true); - // TODO maybe default would be false this.transferInstrumentationEnabled = configProperties.getBoolean("otel.instrumentation.maven.transfer.enabled", false); 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 b673e34d0..692a70650 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelLifecycleParticipant.java @@ -44,8 +44,6 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic @Override public void afterSessionStart(MavenSession session) { - // TODO transfers happen before afterProjectsRead() - not sure I understand the issue in the - // comment of afterProjectsRead() if (openTelemetrySdkService.isTransferInstrumentationEnabled()) { registerTransferListener(session); } From cbbc2d7f30a014e2a0b1d0f5ddf487c60cee63e8 Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Thu, 15 May 2025 09:13:44 +0200 Subject: [PATCH 8/8] spotlessApply --- .../java/io/opentelemetry/maven/OtelTransferListener.java | 7 +++++-- .../maven/semconv/MavenOtelSemanticAttributes.java | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java index 4e038b3df..53c2aa729 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -64,7 +64,8 @@ public void transferInitiated(TransferEvent event) { httpRequestMethod = "HEAD"; break; default: - logger.warn("OpenTelemetry: Unknown request type {} for event {}", event.getRequestType(), event); + logger.warn( + "OpenTelemetry: Unknown request type {} for event {}", event.getRequestType(), event); httpRequestMethod = event.getRequestType().name(); } @@ -87,7 +88,9 @@ public void transferInitiated(TransferEvent event) { .setAttribute(UrlIncubatingAttributes.URL_TEMPLATE, urlTemplate) .setAttribute( MavenOtelSemanticAttributes.MAVEN_TRANSFER_TYPE, event.getRequestType().name()) - .setAttribute(MavenOtelSemanticAttributes.MAVEN_RESOURCE_NAME, event.getResource().getResourceName()); + .setAttribute( + MavenOtelSemanticAttributes.MAVEN_RESOURCE_NAME, + event.getResource().getResourceName()); repositoryUriMapping .computeIfAbsent( 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 d5148e667..446e9b87d 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 @@ -58,6 +58,7 @@ public class MavenOtelSemanticAttributes { /** See {@link TransferEvent.RequestType}. */ public static final AttributeKey MAVEN_TRANSFER_TYPE = AttributeKey.stringKey("maven.transfer.type"); + /** See {@link org.eclipse.aether.transfer.TransferResource}. */ public static final AttributeKey MAVEN_RESOURCE_NAME = AttributeKey.stringKey("maven.resource.name");