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/build.gradle.kts b/maven-extension/build.gradle.kts index 4304534f8..d14faa992 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" @@ -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/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..0d2e5150e 100644 --- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java @@ -49,10 +49,12 @@ public final class OpenTelemetrySdkService implements Closeable { private final boolean mojosInstrumentationEnabled; + private final boolean transferInstrumentationEnabled; + private boolean disposed; public OpenTelemetrySdkService() { - logger.debug( + logger.info( "OpenTelemetry: Initialize OpenTelemetrySdkService v{}...", MavenOtelSemanticAttributes.TELEMETRY_DISTRO_VERSION_VALUE); @@ -76,6 +78,8 @@ public OpenTelemetrySdkService() { this.mojosInstrumentationEnabled = configProperties.getBoolean("otel.instrumentation.maven.mojo.enabled", true); + this.transferInstrumentationEnabled = + configProperties.getBoolean("otel.instrumentation.maven.transfer.enabled", false); this.tracer = openTelemetrySdk.getTracer("io.opentelemetry.contrib.maven", VERSION); } @@ -154,4 +158,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..692a70650 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,14 @@ 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) { + if (openTelemetrySdkService.isTransferInstrumentationEnabled()) { + registerTransferListener(session); + } } /** @@ -43,6 +56,10 @@ public final class OtelLifecycleParticipant extends AbstractMavenLifecyclePartic */ @Override public void afterProjectsRead(MavenSession session) { + registerExecutionListener(session); + } + + void registerExecutionListener(MavenSession session) { ExecutionListener initialExecutionListener = session.getRequest().getExecutionListener(); if (initialExecutionListener instanceof ChainedExecutionListener || initialExecutionListener instanceof OtelExecutionListener) { @@ -64,6 +81,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..53c2aa729 --- /dev/null +++ b/maven-extension/src/main/java/io/opentelemetry/maven/OtelTransferListener.java @@ -0,0 +1,166 @@ +/* + * 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.maven.semconv.MavenOtelSemanticAttributes; +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.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; +import org.eclipse.aether.transfer.TransferEvent; +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; + + private final Map> repositoryUriMapping = new ConcurrentHashMap<>(); + + OtelTransferListener(SpanRegistry spanRegistry, OpenTelemetrySdkService openTelemetrySdkService) { + this.spanRegistry = spanRegistry; + this.openTelemetrySdkService = openTelemetrySdkService; + } + + @Override + public void transferInitiated(TransferEvent event) { + logger.debug("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 {} for event {}", event.getRequestType(), event); + httpRequestMethod = event.getRequestType().name(); + } + + String urlTemplate = + event.getResource().getRepositoryUrl() + + "$groupId/$artifactId/$version/$artifactId-$version.$classifier"; + + String spanName = httpRequestMethod + " " + urlTemplate; + + // Build an HTTP client span as the http call itself is not instrumented. + SpanBuilder spanBuilder = + this.openTelemetrySdkService + .getTracer() + .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()) + .setAttribute( + MavenOtelSemanticAttributes.MAVEN_RESOURCE_NAME, + event.getResource().getResourceName()); + + repositoryUriMapping + .computeIfAbsent( + event.getResource().getRepositoryUrl(), + str -> { + try { + return str.isEmpty() ? Optional.empty() : Optional.of(new URI(str)); + } catch (URISyntaxException e) { + return Optional.empty(); + } + }) + .ifPresent( + uri -> { + spanBuilder.setAttribute(ServerAttributes.SERVER_ADDRESS, uri.getHost()); + if (uri.getPort() != -1) { + spanBuilder.setAttribute(ServerAttributes.SERVER_PORT, uri.getPort()); + } + // prevent ever increasing size + if (repositoryUriMapping.size() > 128) { + repositoryUriMapping.clear(); + } + }); + spanRegistry.putSpan(spanBuilder.startSpan(), event); + } + + @Override + public void transferSucceeded(TransferEvent event) { + logger.debug("OpenTelemetry: OtelTransferListener#transferSucceeded({})", event); + + Optional.ofNullable(spanRegistry.removeSpan(event)) + .ifPresent( + span -> { + span.setStatus(StatusCode.OK); + finish(span, event); + }); + } + + @Override + public void transferFailed(TransferEvent event) { + logger.debug("OpenTelemetry: OtelTransferListener#transferFailed({})", event); + + Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); + } + + @Override + public void transferCorrupted(TransferEvent event) { + logger.debug("OpenTelemetry: OtelTransferListener#transferCorrupted({})", event); + + Optional.ofNullable(spanRegistry.removeSpan(event)).ifPresent(span -> fail(span, event)); + } + + void finish(Span span, TransferEvent event) { + 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(); + } + + void fail(Span span, TransferEvent event) { + span.setStatus( + StatusCode.ERROR, + Optional.ofNullable(event.getException()).map(Exception::getMessage).orElse("n/a")); + finish(span, event); + } +} 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..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 @@ -11,6 +11,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.maven.OpenTelemetrySdkService; import java.util.List; +import org.eclipse.aether.transfer.TransferEvent; /** * Semantic attributes for Maven executions. @@ -36,6 +37,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"); @@ -53,6 +55,14 @@ public class MavenOtelSemanticAttributes { public static final AttributeKey MAVEN_PROJECT_VERSION = stringKey("maven.project.version"); + /** 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"; // inlined incubating attribute to prevent direct dependency on incubating semconv