diff --git a/maven-extension/src/main/java/io/opentelemetry/maven/AutoConfigureUtil2.java b/maven-extension/src/main/java/io/opentelemetry/maven/AutoConfigureUtil2.java
new file mode 100644
index 000000000..6ebcf004b
--- /dev/null
+++ b/maven-extension/src/main/java/io/opentelemetry/maven/AutoConfigureUtil2.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.maven;
+
+import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
+import io.opentelemetry.sdk.resources.Resource;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/** Utility class to use the {@link AutoConfiguredOpenTelemetrySdk}. */
+public class AutoConfigureUtil2 {
+
+ private AutoConfigureUtil2() {}
+
+ /**
+ * Returns the {@link Resource} that was autoconfigured.
+ *
+ *
Inspired by {@link
+ * io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil#getConfig(AutoConfiguredOpenTelemetrySdk)}
+ */
+ public static Resource getResource(
+ AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
+ try {
+ Method method = AutoConfiguredOpenTelemetrySdk.class.getDeclaredMethod("getResource");
+ method.setAccessible(true);
+ return (Resource) method.invoke(autoConfiguredOpenTelemetrySdk);
+ } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+ throw new IllegalStateException(
+ "Error calling getResource on AutoConfiguredOpenTelemetrySdk", e);
+ }
+ }
+}
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 af4fe9662..a357b3177 100644
--- a/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java
+++ b/maven-extension/src/main/java/io/opentelemetry/maven/OpenTelemetrySdkService.java
@@ -5,19 +5,24 @@
package io.opentelemetry.maven;
+import com.google.common.annotations.VisibleForTesting;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.maven.semconv.MavenOtelSemanticAttributes;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
+import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
+import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.common.CompletableResultCode;
+import io.opentelemetry.sdk.resources.Resource;
import java.io.Closeable;
+import java.util.Collections;
import java.util.HashMap;
-import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.TimeUnit;
-import javax.annotation.Nullable;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import javax.inject.Singleton;
@@ -36,6 +41,10 @@ public final class OpenTelemetrySdkService implements Closeable {
private final OpenTelemetrySdk openTelemetrySdk;
+ @VisibleForTesting final Resource resource;
+
+ private final ConfigProperties configProperties;
+
private final Tracer tracer;
private final boolean mojosInstrumentationEnabled;
@@ -47,32 +56,68 @@ public OpenTelemetrySdkService() {
"OpenTelemetry: Initialize OpenTelemetrySdkService v{}...",
MavenOtelSemanticAttributes.TELEMETRY_DISTRO_VERSION_VALUE);
- // Change default of "otel.[traces,metrics,logs].exporter" from "otlp" to "none"
- // The impacts are
- // * If no otel exporter settings are passed, then the Maven extension will not export
- // rather than exporting on OTLP GRPC to http://localhost:4317
- // * If OTEL_EXPORTER_OTLP_ENDPOINT is defined but OTEL_[TRACES,METRICS,LOGS]_EXPORTER,
- // is not, then don't export
- Map properties = new HashMap<>();
- properties.put("otel.traces.exporter", "none");
- properties.put("otel.metrics.exporter", "none");
- properties.put("otel.logs.exporter", "none");
-
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk =
AutoConfiguredOpenTelemetrySdk.builder()
.setServiceClassLoader(getClass().getClassLoader())
- .addPropertiesSupplier(() -> properties)
+ .addPropertiesCustomizer(
+ OpenTelemetrySdkService::requireExplicitConfigOfTheOtlpExporter)
.disableShutdownHook()
.build();
this.openTelemetrySdk = autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
+ this.configProperties =
+ Optional.ofNullable(AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk))
+ .orElseGet(() -> DefaultConfigProperties.createFromMap(Collections.emptyMap()));
+
+ this.resource = AutoConfigureUtil2.getResource(autoConfiguredOpenTelemetrySdk);
+ // Display resource attributes in debug logs for troubleshooting when traces are not found in
+ // the observability backend, helping understand `service.name`, `service.namespace`, etc.
+ logger.debug("OpenTelemetry: OpenTelemetrySdkService initialized, resource:{}", resource);
- Boolean mojoSpansEnabled = getBooleanConfig("otel.instrumentation.maven.mojo.enabled");
- this.mojosInstrumentationEnabled = mojoSpansEnabled == null || mojoSpansEnabled;
+ this.mojosInstrumentationEnabled =
+ configProperties.getBoolean("otel.instrumentation.maven.mojo.enabled", true);
this.tracer = openTelemetrySdk.getTracer("io.opentelemetry.contrib.maven", VERSION);
}
+ /**
+ * The OTel SDK by default sends data to the OTLP gRPC endpoint localhost:4317 if no exporter and
+ * no OTLP exporter endpoint are defined. This is not suited for a build tool for which we want
+ * the OTel SDK to be disabled by default.
+ *
+ * Change the OTel SDL behavior: if none of the exporter and the OTLP exporter endpoint are
+ * defined, explicitly disable the exporter setting "{@code
+ * otel.[traces,metrics,logs].exporter=none}"
+ *
+ * @return The properties to be returned by {@link
+ * io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder#addPropertiesCustomizer(java.util.function.Function)}
+ */
+ static Map requireExplicitConfigOfTheOtlpExporter(
+ ConfigProperties configProperties) {
+
+ Map properties = new HashMap<>();
+ if (configProperties.getString("otel.exporter.otlp.endpoint") != null) {
+ logger.debug("OpenTelemetry: OTLP exporter endpoint is explicitly configured");
+ return properties;
+ }
+ String[] signalTypes = {"traces", "metrics", "logs"};
+ for (String signalType : signalTypes) {
+ boolean isExporterImplicitlyConfiguredToOtlp =
+ configProperties.getString("otel." + signalType + ".exporter") == null;
+ boolean isOtlpExporterEndpointSpecified =
+ configProperties.getString("otel.exporter.otlp." + signalType + ".endpoint") != null;
+
+ if (isExporterImplicitlyConfiguredToOtlp && !isOtlpExporterEndpointSpecified) {
+ logger.debug(
+ "OpenTelemetry: Disabling default OTLP exporter endpoint for signal {} exporter",
+ signalType);
+ properties.put("otel." + signalType + ".exporter", "none");
+ }
+ }
+
+ return properties;
+ }
+
@PreDestroy
@Override
public synchronized void close() {
@@ -97,6 +142,10 @@ public Tracer getTracer() {
return this.tracer;
}
+ public ConfigProperties getConfigProperties() {
+ return configProperties;
+ }
+
/** Returns the {@link ContextPropagators} for this {@link OpenTelemetry}. */
public ContextPropagators getPropagators() {
return this.openTelemetrySdk.getPropagators();
@@ -105,17 +154,4 @@ public ContextPropagators getPropagators() {
public boolean isMojosInstrumentationEnabled() {
return mojosInstrumentationEnabled;
}
-
- @Nullable
- private static Boolean getBooleanConfig(String name) {
- String value = System.getProperty(name);
- if (value != null) {
- return Boolean.parseBoolean(value);
- }
- value = System.getenv(name.toUpperCase(Locale.ROOT).replace('.', '_'));
- if (value != null) {
- return Boolean.parseBoolean(value);
- }
- return null;
- }
}
diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/AutoConfigureUtil2Test.java b/maven-extension/src/test/java/io/opentelemetry/maven/AutoConfigureUtil2Test.java
new file mode 100644
index 000000000..4a72de43e
--- /dev/null
+++ b/maven-extension/src/test/java/io/opentelemetry/maven/AutoConfigureUtil2Test.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.maven;
+
+import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
+import java.lang.reflect.Method;
+import org.junit.jupiter.api.Test;
+
+class AutoConfigureUtil2Test {
+
+ /**
+ * Verify the reflection call works with the current version of AutoConfiguredOpenTelemetrySdk.
+ *
+ * @throws NoSuchMethodException if the method does not exist
+ */
+ @Test
+ void test_getResource() throws NoSuchMethodException {
+ Method method = AutoConfiguredOpenTelemetrySdk.class.getDeclaredMethod("getResource");
+ method.setAccessible(true);
+ }
+}
diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java
index 0b7b41a31..0174a6283 100644
--- a/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java
+++ b/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java
@@ -5,42 +5,132 @@
package io.opentelemetry.maven;
-import org.junit.jupiter.api.Disabled;
+import static io.opentelemetry.api.common.AttributeKey.stringKey;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
+import io.opentelemetry.sdk.resources.Resource;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
+/**
+ * Note: if otel-java-contrib bumps to Java 11+, we could use junit-pioneer's
+ * {@code @SetSystemProperty} and {@code @ClearSystemProperty} but no bump is planned for now.
+ */
public class OpenTelemetrySdkServiceTest {
- /** Verify default `service.name` */
+ /** Verify default config */
@Test
- @Disabled
public void testDefaultConfiguration() {
- testConfiguration("maven");
+ System.clearProperty("otel.exporter.otlp.endpoint");
+ System.clearProperty("otel.service.name");
+ System.clearProperty("otel.resource.attributes");
+ try (OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService()) {
+
+ Resource resource = openTelemetrySdkService.resource;
+ assertThat(resource.getAttribute(stringKey("service.name"))).isEqualTo("maven");
+
+ ConfigProperties configProperties = openTelemetrySdkService.getConfigProperties();
+ assertThat(configProperties.getString("otel.exporter.otlp.endpoint")).isNull();
+ assertThat(configProperties.getString("otel.traces.exporter")).isEqualTo("none");
+ assertThat(configProperties.getString("otel.metrics.exporter")).isEqualTo("none");
+ assertThat(configProperties.getString("otel.logs.exporter")).isEqualTo("none");
+ }
}
- /** Verify overwritten `service.name` */
+ /** Verify overwritten `service.name`,`key1` and `key2` */
@Test
- @Disabled
- public void testOverwrittenConfiguration() {
+ public void testOverwrittenResourceAttributes() {
System.setProperty("otel.service.name", "my-maven");
- try {
- testConfiguration("my-maven");
+ System.setProperty("otel.resource.attributes", "key1=val1,key2=val2");
+
+ try (OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService()) {
+
+ Resource resource = openTelemetrySdkService.resource;
+ assertThat(resource.getAttribute(stringKey("service.name"))).isEqualTo("my-maven");
+ assertThat(resource.getAttribute(stringKey("key1"))).isEqualTo("val1");
+ assertThat(resource.getAttribute(stringKey("key2"))).isEqualTo("val2");
+
} finally {
System.clearProperty("otel.service.name");
+ System.clearProperty("otel.resource.attributes");
+ }
+ }
+
+ /** Verify defining `otel.exporter.otlp.endpoint` works */
+ @Test
+ public void testOverwrittenExporterConfiguration_1() {
+ System.setProperty("otel.exporter.otlp.endpoint", "https://example.com:4317");
+
+ try (OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService()) {
+
+ ConfigProperties configProperties = openTelemetrySdkService.getConfigProperties();
+ assertThat(configProperties.getString("otel.exporter.otlp.endpoint"))
+ .isEqualTo("https://example.com:4317");
+ assertThat(configProperties.getString("otel.traces.exporter")).isNull();
+ assertThat(configProperties.getString("otel.metrics.exporter")).isNull();
+ assertThat(configProperties.getString("otel.logs.exporter")).isNull();
+
+ } finally {
+ System.clearProperty("otel.exporter.otlp.endpoint");
+ }
+ }
+
+ /** Verify defining `otel.exporter.otlp.traces.endpoint` works */
+ @Test
+ public void testOverwrittenExporterConfiguration_2() {
+ System.clearProperty("otel.exporter.otlp.endpoint");
+ System.clearProperty("otel.traces.exporter");
+ System.setProperty("otel.exporter.otlp.traces.endpoint", "https://example.com:4317/");
+
+ try (OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService()) {
+
+ ConfigProperties configProperties = openTelemetrySdkService.getConfigProperties();
+ assertThat(configProperties.getString("otel.exporter.otlp.endpoint")).isNull();
+ assertThat(configProperties.getString("otel.exporter.otlp.traces.endpoint"))
+ .isEqualTo("https://example.com:4317/");
+ assertThat(configProperties.getString("otel.traces.exporter")).isNull();
+ assertThat(configProperties.getString("otel.metrics.exporter")).isEqualTo("none");
+ assertThat(configProperties.getString("otel.logs.exporter")).isEqualTo("none");
+
+ } finally {
+ System.clearProperty("otel.exporter.otlp.endpoint");
+ System.clearProperty("otel.traces.exporter");
+ System.clearProperty("otel.exporter.otlp.traces.endpoint");
+ }
+ }
+
+ /** Verify defining `otel.exporter.otlp.traces.endpoint` and `otel.traces.exporter` works */
+ @Test
+ public void testOverwrittenExporterConfiguration_3() {
+ System.clearProperty("otel.exporter.otlp.endpoint");
+ System.setProperty("otel.traces.exporter", "otlp");
+ System.setProperty("otel.exporter.otlp.traces.endpoint", "https://example.com:4317/");
+
+ try (OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService()) {
+
+ ConfigProperties configProperties = openTelemetrySdkService.getConfigProperties();
+ assertThat(configProperties.getString("otel.exporter.otlp.endpoint")).isNull();
+ assertThat(configProperties.getString("otel.exporter.otlp.traces.endpoint"))
+ .isEqualTo("https://example.com:4317/");
+ assertThat(configProperties.getString("otel.traces.exporter")).isEqualTo("otlp");
+ assertThat(configProperties.getString("otel.metrics.exporter")).isEqualTo("none");
+ assertThat(configProperties.getString("otel.logs.exporter")).isEqualTo("none");
+
+ } finally {
+ System.clearProperty("otel.exporter.otlp.endpoint");
+ System.clearProperty("otel.exporter.otlp.traces.endpoint");
+ System.clearProperty("otel.exporter.otlp.traces.protocol");
}
}
- void testConfiguration(String expectedServiceName) {
- // OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService();
- // openTelemetrySdkService.initialize();
- // try {
- // Resource resource =
- // openTelemetrySdkService.autoConfiguredOpenTelemetrySdk.getResource();
- // assertThat(resource.getAttribute(ResourceAttributes.SERVICE_NAME))
- // .isEqualTo(expectedServiceName);
- // } finally {
- // openTelemetrySdkService.dispose();
- // GlobalOpenTelemetry.resetForTest();
- // GlobalEventEmitterProvider.resetForTest();
- // }
+ @AfterAll
+ static void afterAll() {
+ System.clearProperty("otel.exporter.otlp.endpoint");
+ System.clearProperty("otel.exporter.otlp.traces.endpoint");
+ System.clearProperty("otel.exporter.otlp.traces.protocol");
+ System.clearProperty("otel.resource.attributes");
+ System.clearProperty("otel.service.name");
+ System.clearProperty("otel.traces.exporter");
}
}