This method is a convenience method for a common instrumentation library workflow:
+ *
+ *
+ *
During initialization, an instrumentation library is given an {@link ConfigProvider} and
+ * must initialize according to the relevant config
+ *
It checks if the user has provided configuration for it, and if so...
+ *
It converts the configuration to an in-memory model representing all of its relevant
+ * properties
+ *
It initializes using the strongly typed in-memory model
+ *
+ *
+ *
Conversion is done using {@link ObjectMapper#convertValue(Object, Class)} from {@code
+ * com.fasterxml.jackson.databind}, and assumes the {@code modelType} is a POJO written /
+ * annotated to support jackson databinding.
+ *
+ *
NOTE: callers MUST add their own dependency on {@code
+ * com.fasterxml.jackson.core:jackson-databind}. This module's dependency is {@code compileOnly}
+ * since jackson is a large dependency that many users will not require. It's very possible to
+ * convert between {@link DeclarativeConfigProperties} (or a map representation from {@link
+ * DeclarativeConfigProperties#toMap(DeclarativeConfigProperties)}) and a target model type
+ * without jackson. This method is provided as an optional convenience method.
+ *
+ * @throws IllegalArgumentException if conversion fails. See {@link
+ * ObjectMapper#convertValue(Object, Class)} for details.
+ */
+ @Nullable
+ public static T getInstrumentationConfigModel(
+ ConfigProvider configProvider,
+ String instrumentationName,
+ ObjectMapper objectMapper,
+ Class modelType) {
+ DeclarativeConfigProperties properties =
+ javaInstrumentationConfig(configProvider, instrumentationName);
+ if (properties == null) {
+ return null;
+ }
+ Map configPropertiesMap = DeclarativeConfigProperties.toMap(properties);
+ return objectMapper.convertValue(configPropertiesMap, modelType);
+ }
}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java
index 239f42d7aa..1473149560 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java
@@ -27,6 +27,11 @@ class ExtendedDefaultLogger implements ExtendedLogger {
return INSTANCE;
}
+ @Override
+ public boolean isEnabled(Severity severity, Context context) {
+ return false;
+ }
+
@Override
public ExtendedLogRecordBuilder logRecordBuilder() {
return NOOP_LOG_RECORD_BUILDER;
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
index de159406c0..60f3668590 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
@@ -6,21 +6,41 @@
package io.opentelemetry.api.incubator.logs;
import io.opentelemetry.api.logs.Logger;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.context.Context;
/** Extended {@link Logger} with experimental APIs. */
public interface ExtendedLogger extends Logger {
/**
- * Returns {@code true} if the logger is enabled.
+ * Returns {@code true} if the logger is enabled for the given {@code context} and {@code
+ * severity}.
*
*
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
* the response is subject to change over the application, callers should call this before each
* call to {@link #logRecordBuilder()}.
*/
- default boolean isEnabled() {
+ default boolean isEnabled(Severity severity, Context context) {
return true;
}
+ /** Overload of {@link #isEnabled(Severity, Context)} assuming {@link Context#current()}. */
+ default boolean isEnabled(Severity severity) {
+ return isEnabled(severity, Context.current());
+ }
+
+ /**
+ * Overload of {@link #isEnabled(Severity, Context)} assuming {@link
+ * Severity#UNDEFINED_SEVERITY_NUMBER} and {@link Context#current()}.
+ *
+ * @deprecated for removal after 1.55.0. Use {@link #isEnabled(Severity, Context)} or {@link
+ * #isEnabled(Severity)} instead.
+ */
+ @Deprecated
+ default boolean isEnabled() {
+ return isEnabled(Severity.UNDEFINED_SEVERITY_NUMBER);
+ }
+
@Override
ExtendedLogRecordBuilder logRecordBuilder();
}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeter.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeter.java
index de1ec1fdef..8283c7bb0b 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeter.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeter.java
@@ -94,6 +94,11 @@ class ExtendedDefaultMeter implements Meter {
private ExtendedDefaultMeter() {}
private static class NoopLongCounter implements ExtendedLongCounter {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void add(long value, Attributes attributes, Context context) {}
@@ -105,6 +110,11 @@ class ExtendedDefaultMeter implements Meter {
}
private static class NoopDoubleCounter implements ExtendedDoubleCounter {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void add(double value, Attributes attributes, Context context) {}
@@ -186,6 +196,11 @@ class ExtendedDefaultMeter implements Meter {
}
private static class NoopLongUpDownCounter implements ExtendedLongUpDownCounter {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void add(long value, Attributes attributes, Context context) {}
@@ -197,6 +212,11 @@ class ExtendedDefaultMeter implements Meter {
}
private static class NoopDoubleUpDownCounter implements ExtendedDoubleUpDownCounter {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void add(double value, Attributes attributes, Context context) {}
@@ -281,6 +301,11 @@ class ExtendedDefaultMeter implements Meter {
}
private static class NoopDoubleHistogram implements ExtendedDoubleHistogram {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void record(double value, Attributes attributes, Context context) {}
@@ -292,6 +317,11 @@ class ExtendedDefaultMeter implements Meter {
}
private static class NoopLongHistogram implements ExtendedLongHistogram {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void record(long value, Attributes attributes, Context context) {}
@@ -385,6 +415,11 @@ class ExtendedDefaultMeter implements Meter {
}
private static class NoopDoubleGauge implements ExtendedDoubleGauge {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void set(double value) {}
@@ -426,6 +461,11 @@ class ExtendedDefaultMeter implements Meter {
}
private static class NoopLongGauge implements ExtendedLongGauge {
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public void set(long value) {}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracer.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracer.java
index 45346099a5..fe35d64666 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracer.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracer.java
@@ -31,6 +31,11 @@ final class ExtendedDefaultTracer implements ExtendedTracer {
return INSTANCE;
}
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
@Override
public ExtendedSpanBuilder spanBuilder(String spanName) {
return NoopSpanBuilder.create();
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/config/InstrumentationConfigUtilTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/config/InstrumentationConfigUtilTest.java
index d31001397a..8cb76972e7 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/config/InstrumentationConfigUtilTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/config/InstrumentationConfigUtilTest.java
@@ -150,7 +150,8 @@ class InstrumentationConfigUtilTest {
.isInstanceOfSatisfying(
YamlDeclarativeConfigProperties.class,
exampleConfig ->
- assertThat(exampleConfig.toMap()).isEqualTo(ImmutableMap.of("property", "value")));
+ assertThat(DeclarativeConfigProperties.toMap(exampleConfig))
+ .isEqualTo(ImmutableMap.of("property", "value")));
assertThat(
InstrumentationConfigUtil.javaInstrumentationConfig(kitchenSinkConfigProvider, "foo"))
.isNull();
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLoggerTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLoggerTest.java
index e92a3c160a..ef20161077 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLoggerTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLoggerTest.java
@@ -10,7 +10,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.common.Value;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.api.logs.LoggerProvider;
+import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.api.testing.internal.AbstractDefaultLoggerTest;
+import io.opentelemetry.context.Context;
import org.junit.jupiter.api.Test;
class ExtendedDefaultLoggerTest extends AbstractDefaultLoggerTest {
@@ -26,10 +28,18 @@ class ExtendedDefaultLoggerTest extends AbstractDefaultLoggerTest {
}
@Test
+ @SuppressWarnings("deprecation") // testing deprecated code
void incubatingApiIsLoaded() {
Logger logger = LoggerProvider.noop().get("test");
- assertThat(logger).isInstanceOf(ExtendedLogger.class);
+ assertThat(logger)
+ .isInstanceOfSatisfying(
+ ExtendedLogger.class,
+ extendedLogger -> {
+ assertThat(extendedLogger.isEnabled(Severity.ERROR, Context.current())).isFalse();
+ assertThat(extendedLogger.isEnabled(Severity.ERROR)).isFalse();
+ assertThat(extendedLogger.isEnabled()).isFalse();
+ });
ExtendedLogRecordBuilder builder = (ExtendedLogRecordBuilder) logger.logRecordBuilder();
assertThat(builder).isInstanceOf(ExtendedLogRecordBuilder.class);
assertThat(builder.setBody(Value.of(0))).isSameAs(builder);
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java
index f7fdb51128..05c3e65f85 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java
@@ -14,6 +14,7 @@ import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.incubator.common.ExtendedAttributeKey;
import io.opentelemetry.api.incubator.common.ExtendedAttributes;
import io.opentelemetry.api.logs.Logger;
+import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
@@ -53,24 +54,26 @@ class ExtendedLogsBridgeApiUsageTest {
ExtendedLogger loggerB = (ExtendedLogger) loggerProvider.get("loggerB");
// Check if logger is enabled before emitting log and avoid unnecessary computation
- if (loggerA.isEnabled()) {
+ if (loggerA.isEnabled(Severity.INFO)) {
loggerA
.logRecordBuilder()
+ .setSeverity(Severity.INFO)
.setBody("hello world!")
.setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
.emit();
}
- if (loggerB.isEnabled()) {
+ if (loggerB.isEnabled(Severity.INFO)) {
loggerB
.logRecordBuilder()
+ .setSeverity(Severity.INFO)
.setBody("hello world!")
.setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
.emit();
}
// loggerA is enabled, loggerB is disabled
- assertThat(loggerA.isEnabled()).isTrue();
- assertThat(loggerB.isEnabled()).isFalse();
+ assertThat(loggerA.isEnabled(Severity.INFO)).isTrue();
+ assertThat(loggerB.isEnabled(Severity.INFO)).isFalse();
// Collected data only consists of logs from loggerA. Note, loggerB's logs would be
// omitted from the results even if logs were emitted. The check if enabled simply avoids
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeterTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeterTest.java
index a56a8740b0..f864c5d44a 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeterTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedDefaultMeterTest.java
@@ -11,7 +11,6 @@ import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.api.testing.internal.AbstractDefaultMeterTest;
-import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
class ExtendedDefaultMeterTest extends AbstractDefaultMeterTest {
@@ -27,44 +26,53 @@ class ExtendedDefaultMeterTest extends AbstractDefaultMeterTest {
}
@Test
- public void incubatingApiIsLoaded() {
+ void incubatingApiIsLoaded() {
Meter meter = MeterProvider.noop().get("test");
assertThat(meter).isSameAs(OpenTelemetry.noop().getMeter("test"));
- Assertions.assertThat(meter.gaugeBuilder("test").ofLongs())
- .isInstanceOf(ExtendedLongGaugeBuilder.class);
- Assertions.assertThat(meter.gaugeBuilder("test").ofLongs().build())
- .isInstanceOf(ExtendedLongGauge.class);
- Assertions.assertThat(meter.gaugeBuilder("test"))
- .isInstanceOf(ExtendedDoubleGaugeBuilder.class);
- Assertions.assertThat(meter.gaugeBuilder("test").build())
- .isInstanceOf(ExtendedDoubleGauge.class);
+ assertThat(meter.gaugeBuilder("test").ofLongs()).isInstanceOf(ExtendedLongGaugeBuilder.class);
+ assertThat(meter.gaugeBuilder("test").ofLongs().build())
+ .isInstanceOfSatisfying(
+ ExtendedLongGauge.class, instrument -> assertThat(instrument.isEnabled()).isFalse());
+ assertThat(meter.gaugeBuilder("test")).isInstanceOf(ExtendedDoubleGaugeBuilder.class);
+ assertThat(meter.gaugeBuilder("test").build())
+ .isInstanceOfSatisfying(
+ ExtendedDoubleGauge.class, instrument -> assertThat(instrument.isEnabled()).isFalse());
- Assertions.assertThat(meter.histogramBuilder("test").ofLongs())
+ assertThat(meter.histogramBuilder("test").ofLongs())
.isInstanceOf(ExtendedLongHistogramBuilder.class);
- Assertions.assertThat(meter.histogramBuilder("test").ofLongs().build())
- .isInstanceOf(ExtendedLongHistogram.class);
- Assertions.assertThat(meter.histogramBuilder("test"))
- .isInstanceOf(ExtendedDoubleHistogramBuilder.class);
- Assertions.assertThat(meter.histogramBuilder("test").build())
- .isInstanceOf(ExtendedDoubleHistogram.class);
+ assertThat(meter.histogramBuilder("test").ofLongs().build())
+ .isInstanceOfSatisfying(
+ ExtendedLongHistogram.class,
+ instrument -> assertThat(instrument.isEnabled()).isFalse());
+ assertThat(meter.histogramBuilder("test")).isInstanceOf(ExtendedDoubleHistogramBuilder.class);
+ assertThat(meter.histogramBuilder("test").build())
+ .isInstanceOfSatisfying(
+ ExtendedDoubleHistogram.class,
+ instrument -> assertThat(instrument.isEnabled()).isFalse());
- Assertions.assertThat(meter.counterBuilder("test"))
- .isInstanceOf(ExtendedLongCounterBuilder.class);
- Assertions.assertThat(meter.counterBuilder("test").build())
- .isInstanceOf(ExtendedLongCounter.class);
- Assertions.assertThat(meter.counterBuilder("test").ofDoubles())
+ assertThat(meter.counterBuilder("test")).isInstanceOf(ExtendedLongCounterBuilder.class);
+ assertThat(meter.counterBuilder("test").build())
+ .isInstanceOfSatisfying(
+ ExtendedLongCounter.class, instrument -> assertThat(instrument.isEnabled()).isFalse());
+ assertThat(meter.counterBuilder("test").ofDoubles())
.isInstanceOf(ExtendedDoubleCounterBuilder.class);
- Assertions.assertThat(meter.counterBuilder("test").ofDoubles().build())
- .isInstanceOf(ExtendedDoubleCounter.class);
+ assertThat(meter.counterBuilder("test").ofDoubles().build())
+ .isInstanceOfSatisfying(
+ ExtendedDoubleCounter.class,
+ instrument -> assertThat(instrument.isEnabled()).isFalse());
- Assertions.assertThat(meter.upDownCounterBuilder("test"))
+ assertThat(meter.upDownCounterBuilder("test"))
.isInstanceOf(ExtendedLongUpDownCounterBuilder.class);
- Assertions.assertThat(meter.upDownCounterBuilder("test").build())
- .isInstanceOf(ExtendedLongUpDownCounter.class);
- Assertions.assertThat(meter.upDownCounterBuilder("test").ofDoubles())
+ assertThat(meter.upDownCounterBuilder("test").build())
+ .isInstanceOfSatisfying(
+ ExtendedLongUpDownCounter.class,
+ instrument -> assertThat(instrument.isEnabled()).isFalse());
+ assertThat(meter.upDownCounterBuilder("test").ofDoubles())
.isInstanceOf(ExtendedDoubleUpDownCounterBuilder.class);
- Assertions.assertThat(meter.upDownCounterBuilder("test").ofDoubles().build())
- .isInstanceOf(ExtendedDoubleUpDownCounter.class);
+ assertThat(meter.upDownCounterBuilder("test").ofDoubles().build())
+ .isInstanceOfSatisfying(
+ ExtendedDoubleUpDownCounter.class,
+ instrument -> assertThat(instrument.isEnabled()).isFalse());
}
}
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracerTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracerTest.java
index 791c6b7d47..f13d072e43 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracerTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedDefaultTracerTest.java
@@ -6,6 +6,8 @@
package io.opentelemetry.api.incubator.trace;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.testing.internal.AbstractDefaultTracerTest;
@@ -27,17 +29,20 @@ class ExtendedDefaultTracerTest extends AbstractDefaultTracerTest {
}
@Test
- public void incubatingApiIsLoaded() {
+ void incubatingApiIsLoaded() {
Tracer tracer = TracerProvider.noop().get("test");
assertThat(tracer).isSameAs(OpenTelemetry.noop().getTracer("test"));
- assertThat(tracer).isInstanceOf(ExtendedTracer.class);
+ assertThat(tracer)
+ .isInstanceOfSatisfying(
+ ExtendedTracer.class,
+ extendedTracer -> assertThat(extendedTracer.isEnabled()).isFalse());
assertThat(tracer.spanBuilder("test")).isInstanceOf(ExtendedSpanBuilder.class);
}
@SuppressWarnings("unchecked")
@Test
- public void incubatingApi() {
+ void incubatingApi() {
ExtendedSpanBuilder spanBuilder =
(ExtendedSpanBuilder) ExtendedDefaultTracer.getNoop().spanBuilder("test");
assertThat(spanBuilder.setParentFrom(null, null)).isSameAs(spanBuilder);
@@ -45,21 +50,21 @@ class ExtendedDefaultTracerTest extends AbstractDefaultTracerTest {
SpanRunnable spanRunnable = Mockito.mock(SpanRunnable.class);
spanBuilder.startAndRun(spanRunnable);
- Mockito.verify(spanRunnable).runInSpan();
- Mockito.reset(spanRunnable);
+ verify(spanRunnable).runInSpan();
+ reset(spanRunnable);
spanBuilder.startAndRun(spanRunnable, null);
- Mockito.verify(spanRunnable).runInSpan();
- Mockito.reset(spanRunnable);
+ verify(spanRunnable).runInSpan();
+ reset(spanRunnable);
SpanCallable spanCallable = Mockito.mock(SpanCallable.class);
spanBuilder.startAndCall(spanCallable);
- Mockito.verify(spanCallable).callInSpan();
- Mockito.reset(spanCallable);
+ verify(spanCallable).callInSpan();
+ reset(spanCallable);
spanBuilder.startAndCall(spanCallable, null);
- Mockito.verify(spanCallable).callInSpan();
- Mockito.reset(spanCallable);
+ verify(spanCallable).callInSpan();
+ reset(spanCallable);
}
}
diff --git a/api/incubator/src/testConvertToModel/java/io/opentelemetry/api/incubator/InstrumentationConfigUtilTest.java b/api/incubator/src/testConvertToModel/java/io/opentelemetry/api/incubator/InstrumentationConfigUtilTest.java
new file mode 100644
index 0000000000..ef936a5fd5
--- /dev/null
+++ b/api/incubator/src/testConvertToModel/java/io/opentelemetry/api/incubator/InstrumentationConfigUtilTest.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableMap;
+import io.opentelemetry.api.incubator.config.ConfigProvider;
+import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
+import io.opentelemetry.api.incubator.config.InstrumentationConfigUtil;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalLanguageSpecificInstrumentationModel;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.InstrumentationModel;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.junit.jupiter.api.Test;
+
+class InstrumentationConfigUtilTest {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ @Test
+ void toMap_RoundTrip() throws JsonProcessingException {
+ Map map = new HashMap<>();
+ map.put("string", "val");
+ map.put("boolean", true);
+ map.put("long", 1L);
+ map.put("double", 1.1);
+ map.put("null", null);
+ map.put("stringList", Arrays.asList("val1", "val2"));
+ map.put("boolList", Arrays.asList(true, false));
+ map.put("longList", Arrays.asList(1L, 2L));
+ map.put("doubleList", Arrays.asList(1.1d, 2.2d));
+ map.put(
+ "structuredList", Collections.singletonList(Collections.singletonMap("childKey", "val")));
+ map.put("emptyList", Collections.emptyList());
+ map.put("structured", Collections.singletonMap("childKey", "val"));
+ map.put("emptyStructured", Collections.emptyMap());
+
+ String mapJson = MAPPER.writeValueAsString(map);
+ DeclarativeConfigProperties properties =
+ DeclarativeConfiguration.toConfigProperties(
+ new ByteArrayInputStream(mapJson.getBytes(StandardCharsets.UTF_8)));
+
+ assertThat(DeclarativeConfigProperties.toMap(properties)).isEqualTo(map);
+ }
+
+ @Test
+ void getInstrumentationConfigModel_UnsetConfig() {
+ ConfigProvider configProvider = () -> null;
+
+ assertThat(
+ InstrumentationConfigUtil.getInstrumentationConfigModel(
+ configProvider, "my_instrumentation_library", MAPPER, Model.class))
+ .isEqualTo(null);
+ }
+
+ @Test
+ void getInstrumentationConfigModel_EmptyConfig() {
+ ConfigProvider configProvider =
+ withInstrumentationConfig("my_instrumentation_library", Collections.emptyMap());
+
+ assertThat(
+ InstrumentationConfigUtil.getInstrumentationConfigModel(
+ configProvider, "my_instrumentation_library", MAPPER, Model.class))
+ .isEqualTo(new Model());
+ }
+
+ @Test
+ void getInstrumentationConfigModel_KitchenSink() {
+ ConfigProvider configProvider =
+ withInstrumentationConfig(
+ "my_instrumentation_library",
+ ImmutableMap.builder()
+ .put("string_property", "value")
+ .put("boolean_property", true)
+ .put("long_property", 1L)
+ .put("double_property", 1.1d)
+ .put("string_list_property", Arrays.asList("val1", "val2"))
+ .put("boolean_list_property", Arrays.asList(true, false))
+ .put("long_list_property", Arrays.asList(1L, 2L))
+ .put("double_list_property", Arrays.asList(1.1d, 2.2d))
+ .put("map_property", Collections.singletonMap("childKey", "val"))
+ .put(
+ "structured_list_property",
+ Collections.singletonList(
+ ImmutableMap.of("key", "the_key", "value", "the_value")))
+ .build());
+
+ Model expected = new Model();
+ expected.stringProperty = "value";
+ expected.booleanProperty = true;
+ expected.longProperty = 1L;
+ expected.doubleProperty = 1.1d;
+ expected.stringListProperty = Arrays.asList("val1", "val2");
+ expected.booleanListProperty = Arrays.asList(true, false);
+ expected.longListProperty = Arrays.asList(1L, 2L);
+ expected.doubleListProperty = Arrays.asList(1.1d, 2.2d);
+ expected.mapProperty = Collections.singletonMap("childKey", "val");
+ ListEntryModel listEntryModel = new ListEntryModel();
+ listEntryModel.key = "the_key";
+ listEntryModel.value = "the_value";
+ expected.structuredListProperty = Collections.singletonList(listEntryModel);
+
+ assertThat(
+ InstrumentationConfigUtil.getInstrumentationConfigModel(
+ configProvider, "my_instrumentation_library", MAPPER, Model.class))
+ .isEqualTo(expected);
+ }
+
+ private static ConfigProvider withInstrumentationConfig(
+ String instrumentationName, Map instrumentationConfig) {
+ ExperimentalLanguageSpecificInstrumentationModel javaConfig =
+ new ExperimentalLanguageSpecificInstrumentationModel();
+ javaConfig.setAdditionalProperty(instrumentationName, instrumentationConfig);
+
+ return SdkConfigProvider.create(
+ new OpenTelemetryConfigurationModel()
+ .withInstrumentationDevelopment(new InstrumentationModel().withJava(javaConfig)));
+ }
+
+ private static class Model {
+ @JsonProperty("string_property")
+ private String stringProperty;
+
+ @JsonProperty("boolean_property")
+ private Boolean booleanProperty;
+
+ @JsonProperty("long_property")
+ private Long longProperty;
+
+ @JsonProperty("double_property")
+ private Double doubleProperty;
+
+ @JsonProperty("string_list_property")
+ private List stringListProperty;
+
+ @JsonProperty("boolean_list_property")
+ private List booleanListProperty;
+
+ @JsonProperty("long_list_property")
+ private List longListProperty;
+
+ @JsonProperty("double_list_property")
+ private List doubleListProperty;
+
+ ;
+
+ @JsonProperty("map_property")
+ private Map mapProperty;
+
+ @JsonProperty("structured_list_property")
+ private List structuredListProperty;
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Model)) {
+ return false;
+ }
+ Model model = (Model) o;
+ return Objects.equals(stringProperty, model.stringProperty)
+ && Objects.equals(booleanProperty, model.booleanProperty)
+ && Objects.equals(longProperty, model.longProperty)
+ && Objects.equals(doubleProperty, model.doubleProperty)
+ && Objects.equals(stringListProperty, model.stringListProperty)
+ && Objects.equals(booleanListProperty, model.booleanListProperty)
+ && Objects.equals(longListProperty, model.longListProperty)
+ && Objects.equals(doubleListProperty, model.doubleListProperty)
+ && Objects.equals(mapProperty, model.mapProperty)
+ && Objects.equals(structuredListProperty, model.structuredListProperty);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ stringProperty,
+ booleanProperty,
+ longProperty,
+ doubleProperty,
+ stringListProperty,
+ booleanListProperty,
+ longListProperty,
+ doubleListProperty,
+ mapProperty,
+ structuredListProperty);
+ }
+
+ @Override
+ public String toString() {
+ return "Model{"
+ + "stringProperty='"
+ + stringProperty
+ + '\''
+ + ", booleanProperty='"
+ + booleanProperty
+ + '\''
+ + ", longProperty='"
+ + longProperty
+ + '\''
+ + ", doubleProperty='"
+ + doubleProperty
+ + '\''
+ + ", stringListProperty="
+ + stringListProperty
+ + ", booleanListProperty="
+ + booleanListProperty
+ + ", longListProperty="
+ + longListProperty
+ + ", doubleListProperty="
+ + doubleListProperty
+ + ", mapProperty="
+ + mapProperty
+ + ", structuredListProperty="
+ + structuredListProperty
+ + '}';
+ }
+ }
+
+ private static final class ListEntryModel {
+ @JsonProperty("key")
+ private String key;
+
+ @JsonProperty("value")
+ private String value;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ListEntryModel that = (ListEntryModel) o;
+ return Objects.equals(key, that.key) && Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(key, value);
+ }
+
+ @Override
+ public String toString() {
+ return "ListEntryModel{" + "key='" + key + '\'' + ", value='" + value + '\'' + '}';
+ }
+ }
+}
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 2f8e81d1f1..d81397ebeb 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
`kotlin-dsl`
// When updating, update below in dependencies too
- id("com.diffplug.spotless") version "7.0.4"
+ id("com.diffplug.spotless") version "7.1.0"
}
if (!hasLauncherForJavaVersion(17)) {
@@ -50,10 +50,10 @@ repositories {
}
dependencies {
- implementation(enforcedPlatform("com.squareup.wire:wire-bom:5.3.3"))
+ implementation(enforcedPlatform("com.squareup.wire:wire-bom:5.3.5"))
implementation("com.google.auto.value:auto-value-annotations:1.11.0")
// When updating, update above in plugins too
- implementation("com.diffplug.spotless:spotless-plugin-gradle:7.0.4")
+ implementation("com.diffplug.spotless:spotless-plugin-gradle:7.1.0")
implementation("com.gradle.develocity:com.gradle.develocity.gradle.plugin:4.0.2")
implementation("com.squareup:javapoet:1.13.0")
implementation("com.squareup.wire:wire-compiler")
diff --git a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
index 54b6269d81..55998eb4f3 100644
--- a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
@@ -42,7 +42,7 @@ java {
checkstyle {
configDirectory.set(file("$rootDir/buildscripts/"))
- toolVersion = "10.26.0"
+ toolVersion = "10.26.1"
isIgnoreFailures = false
configProperties["rootDir"] = rootDir
}
diff --git a/common/build.gradle.kts b/common/build.gradle.kts
new file mode 100644
index 0000000000..ffeef6877f
--- /dev/null
+++ b/common/build.gradle.kts
@@ -0,0 +1,12 @@
+plugins {
+ id("otel.java-conventions")
+ id("otel.publish-conventions")
+
+ id("otel.animalsniffer-conventions")
+}
+
+description = "OpenTelemetry API Common"
+otelJava.moduleName.set("io.opentelemetry.common")
+
+dependencies {
+}
diff --git a/common/src/main/java/io/opentelemetry/common/ComponentLoader.java b/common/src/main/java/io/opentelemetry/common/ComponentLoader.java
new file mode 100644
index 0000000000..17dab36a1b
--- /dev/null
+++ b/common/src/main/java/io/opentelemetry/common/ComponentLoader.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.common;
+
+import java.util.ServiceLoader;
+
+/** A loader for components that are discovered via SPI. */
+public interface ComponentLoader {
+ /**
+ * Load implementations of an SPI.
+ *
+ * @param spiClass the SPI class
+ * @param the SPI type
+ * @return iterable of SPI implementations
+ */
+ Iterable load(Class spiClass);
+
+ /**
+ * Create an instance for the {@code classLoader} using {@link ServiceLoader#load(Class,
+ * ClassLoader)}.
+ */
+ static ComponentLoader forClassLoader(ClassLoader classLoader) {
+ return new ServiceLoaderComponentLoader(classLoader);
+ }
+}
diff --git a/common/src/main/java/io/opentelemetry/common/ServiceLoaderComponentLoader.java b/common/src/main/java/io/opentelemetry/common/ServiceLoaderComponentLoader.java
new file mode 100644
index 0000000000..5f2d0c58cd
--- /dev/null
+++ b/common/src/main/java/io/opentelemetry/common/ServiceLoaderComponentLoader.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.common;
+
+import java.util.ServiceLoader;
+
+class ServiceLoaderComponentLoader implements ComponentLoader {
+
+ private final ClassLoader classLoader;
+
+ ServiceLoaderComponentLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public Iterable load(Class spiClass) {
+ return ServiceLoader.load(spiClass, classLoader);
+ }
+
+ @Override
+ public String toString() {
+ return "ServiceLoaderComponentLoader{classLoader=" + classLoader + "}";
+ }
+}
diff --git a/context/build.gradle.kts b/context/build.gradle.kts
index 6c8fa63837..b3a3562051 100644
--- a/context/build.gradle.kts
+++ b/context/build.gradle.kts
@@ -10,6 +10,7 @@ description = "OpenTelemetry Context (Incubator)"
otelJava.moduleName.set("io.opentelemetry.context")
dependencies {
+ api(project(":common"))
// MustBeClosed
compileOnly("com.google.errorprone:error_prone_annotations")
diff --git a/context/src/main/java/io/opentelemetry/context/LazyStorage.java b/context/src/main/java/io/opentelemetry/context/LazyStorage.java
index 5cce59d253..428b87dc48 100644
--- a/context/src/main/java/io/opentelemetry/context/LazyStorage.java
+++ b/context/src/main/java/io/opentelemetry/context/LazyStorage.java
@@ -37,9 +37,9 @@
package io.opentelemetry.context;
+import io.opentelemetry.common.ComponentLoader;
import java.util.ArrayList;
import java.util.List;
-import java.util.ServiceLoader;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.logging.Level;
@@ -103,9 +103,10 @@ final class LazyStorage {
return ContextStorage.defaultStorage();
}
+ ComponentLoader componentLoader =
+ ComponentLoader.forClassLoader(LazyStorage.class.getClassLoader());
List providers = new ArrayList<>();
- for (ContextStorageProvider provider :
- ServiceLoader.load(ContextStorageProvider.class, LazyStorage.class.getClassLoader())) {
+ for (ContextStorageProvider provider : componentLoader.load(ContextStorageProvider.class)) {
if (provider
.getClass()
.getName()
diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts
index b01c72f28a..bd1ba29e68 100644
--- a/dependencyManagement/build.gradle.kts
+++ b/dependencyManagement/build.gradle.kts
@@ -16,14 +16,14 @@ val DEPENDENCY_BOMS = listOf(
"com.fasterxml.jackson:jackson-bom:2.19.1",
"com.google.guava:guava-bom:33.4.8-jre",
"com.google.protobuf:protobuf-bom:4.31.1",
- "com.squareup.okhttp3:okhttp-bom:4.12.0",
- "com.squareup.okio:okio-bom:3.13.0", // applies to transitive dependencies of okhttp
+ "com.squareup.okhttp3:okhttp-bom:5.1.0",
+ "com.squareup.okio:okio-bom:3.15.0", // applies to transitive dependencies of okhttp
"io.grpc:grpc-bom:1.73.0",
"io.netty:netty-bom:4.2.2.Final",
"io.zipkin.brave:brave-bom:6.3.0",
"io.zipkin.reporter2:zipkin-reporter-bom:3.5.1",
"org.assertj:assertj-bom:3.27.3",
- "org.testcontainers:testcontainers-bom:1.21.2",
+ "org.testcontainers:testcontainers-bom:1.21.3",
"org.snakeyaml:snakeyaml-engine:2.9"
)
@@ -68,7 +68,7 @@ val DEPENDENCIES = listOf(
"io.prometheus:prometheus-metrics-exposition-formats-no-protobuf:${prometheusServerVersion}",
"javax.annotation:javax.annotation-api:1.3.2",
"com.github.stefanbirkner:system-rules:1.19.0",
- "com.google.api.grpc:proto-google-common-protos:2.58.2",
+ "com.google.api.grpc:proto-google-common-protos:2.59.1",
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.guava:guava-beta-checker:1.0",
"com.sun.net.httpserver:http:20070405",
@@ -78,7 +78,7 @@ val DEPENDENCIES = listOf(
"eu.rekawek.toxiproxy:toxiproxy-java:2.1.7",
"io.github.netmikey.logunit:logunit-jul:2.0.0",
"io.jaegertracing:jaeger-client:1.8.1",
- "io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.46.0-alpha",
+ "io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.47.0-alpha",
"io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.34.0-alpha",
"io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha",
"io.opentracing:opentracing-api:0.33.0",
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-api.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-api.txt
new file mode 100644
index 0000000000..ed3e1e076a
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-api.txt
@@ -0,0 +1,4 @@
+Comparing source compatibility of opentelemetry-api-1.52.0.jar against opentelemetry-api-1.51.0.jar
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.api.GlobalOpenTelemetry (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) void set(java.util.function.Supplier)
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-common.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-common.txt
new file mode 100644
index 0000000000..439922d61d
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-common.txt
@@ -0,0 +1,7 @@
+Comparing source compatibility of opentelemetry-common-1.52.0.jar against
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.common.ComponentLoader (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.common.ComponentLoader forClassLoader(java.lang.ClassLoader)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.Iterable load(java.lang.Class)
+ GENERIC TEMPLATES: +++ T:java.lang.Object
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-context.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-context.txt
new file mode 100644
index 0000000000..f628e7c6de
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-context.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-context-1.52.0.jar against opentelemetry-context-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-common.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-common.txt
new file mode 100644
index 0000000000..7ce59a2590
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-common.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-common-1.52.0.jar against opentelemetry-exporter-common-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-logging-otlp.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-logging-otlp.txt
new file mode 100644
index 0000000000..81183679a7
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-logging-otlp.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-logging-otlp-1.52.0.jar against opentelemetry-exporter-logging-otlp-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-logging.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-logging.txt
new file mode 100644
index 0000000000..3ce4ed1852
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-logging.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-logging-1.52.0.jar against opentelemetry-exporter-logging-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-otlp-common.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-otlp-common.txt
new file mode 100644
index 0000000000..12f0ce982e
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-otlp-common.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-otlp-common-1.52.0.jar against opentelemetry-exporter-otlp-common-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-otlp.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-otlp.txt
new file mode 100644
index 0000000000..d9395d450c
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-otlp.txt
@@ -0,0 +1,19 @@
+Comparing source compatibility of opentelemetry-exporter-otlp-1.52.0.jar against opentelemetry-exporter-otlp-1.51.0.jar
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder setComponentLoader(io.opentelemetry.common.ComponentLoader)
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder setComponentLoader(io.opentelemetry.common.ComponentLoader)
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder setComponentLoader(io.opentelemetry.common.ComponentLoader)
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder setComponentLoader(io.opentelemetry.common.ComponentLoader)
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder setComponentLoader(io.opentelemetry.common.ComponentLoader)
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder setComponentLoader(io.opentelemetry.common.ComponentLoader)
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-grpc-managed-channel.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-grpc-managed-channel.txt
new file mode 100644
index 0000000000..a4f7152db3
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-grpc-managed-channel.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-sender-grpc-managed-channel-1.52.0.jar against opentelemetry-exporter-sender-grpc-managed-channel-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-jdk.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-jdk.txt
new file mode 100644
index 0000000000..4f97d2b4cd
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-jdk.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-sender-jdk-1.52.0.jar against opentelemetry-exporter-sender-jdk-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-okhttp.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-okhttp.txt
new file mode 100644
index 0000000000..ec31b89a9e
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-sender-okhttp.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-sender-okhttp-1.52.0.jar against opentelemetry-exporter-sender-okhttp-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-zipkin.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-zipkin.txt
new file mode 100644
index 0000000000..08630dd1b7
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-exporter-zipkin.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-exporter-zipkin-1.52.0.jar against opentelemetry-exporter-zipkin-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-extension-kotlin.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-extension-kotlin.txt
new file mode 100644
index 0000000000..c7b73267ea
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-extension-kotlin.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-extension-kotlin-1.52.0.jar against opentelemetry-extension-kotlin-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-extension-trace-propagators.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-extension-trace-propagators.txt
new file mode 100644
index 0000000000..ae33ad2808
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-extension-trace-propagators.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-extension-trace-propagators-1.52.0.jar against opentelemetry-extension-trace-propagators-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-opentracing-shim.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-opentracing-shim.txt
new file mode 100644
index 0000000000..872c028cb3
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-opentracing-shim.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-opentracing-shim-1.52.0.jar against opentelemetry-opentracing-shim-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-common.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-common.txt
new file mode 100644
index 0000000000..eb715b8fdd
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-common.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-sdk-common-1.52.0.jar against opentelemetry-sdk-common-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-autoconfigure-spi.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-autoconfigure-spi.txt
new file mode 100644
index 0000000000..72353441e6
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-autoconfigure-spi.txt
@@ -0,0 +1,4 @@
+Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-spi-1.52.0.jar against opentelemetry-sdk-extension-autoconfigure-spi-1.51.0.jar
+*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.common.ComponentLoader getComponentLoader()
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-autoconfigure.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-autoconfigure.txt
new file mode 100644
index 0000000000..0b818e8d0f
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-autoconfigure.txt
@@ -0,0 +1,4 @@
+Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-1.52.0.jar against opentelemetry-sdk-extension-autoconfigure-1.51.0.jar
+*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder setComponentLoader(io.opentelemetry.common.ComponentLoader)
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-jaeger-remote-sampler.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-jaeger-remote-sampler.txt
new file mode 100644
index 0000000000..97b9523a61
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-extension-jaeger-remote-sampler.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.52.0.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-logs.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-logs.txt
new file mode 100644
index 0000000000..8cd9d9ff50
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-logs.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-sdk-logs-1.52.0.jar against opentelemetry-sdk-logs-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-metrics.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-metrics.txt
new file mode 100644
index 0000000000..f806e04900
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-metrics.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-sdk-metrics-1.52.0.jar against opentelemetry-sdk-metrics-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-testing.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-testing.txt
new file mode 100644
index 0000000000..bd6d78ab7d
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-testing.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-sdk-testing-1.52.0.jar against opentelemetry-sdk-testing-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-trace.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-trace.txt
new file mode 100644
index 0000000000..7aea6b071c
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk-trace.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-sdk-trace-1.52.0.jar against opentelemetry-sdk-trace-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk.txt b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk.txt
new file mode 100644
index 0000000000..31036408d0
--- /dev/null
+++ b/docs/apidiffs/1.52.0_vs_1.51.0/opentelemetry-sdk.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-sdk-1.52.0.jar against opentelemetry-sdk-1.51.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt
index 3a33f42b55..16a39e345a 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt
@@ -1,4 +1,2 @@
-Comparing source compatibility of opentelemetry-api-1.52.0-SNAPSHOT.jar against opentelemetry-api-1.51.0.jar
-*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.api.GlobalOpenTelemetry (not serializable)
- === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
- +++ NEW METHOD: PUBLIC(+) STATIC(+) void set(java.util.function.Supplier)
+Comparing source compatibility of opentelemetry-api-1.53.0-SNAPSHOT.jar against opentelemetry-api-1.52.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-common.txt
new file mode 100644
index 0000000000..fbf00f472b
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-common.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of opentelemetry-common-1.53.0-SNAPSHOT.jar against opentelemetry-common-1.52.0.jar
+No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-context.txt b/docs/apidiffs/current_vs_latest/opentelemetry-context.txt
index cb58011e0e..8f1bc99ad3 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-context.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-context.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-context-1.52.0-SNAPSHOT.jar against opentelemetry-context-1.51.0.jar
+Comparing source compatibility of opentelemetry-context-1.53.0-SNAPSHOT.jar against opentelemetry-context-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt
index 4adbdc7eab..8bf7d0f8ef 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-common-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-common-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-common-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-common-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt
index 87aceeae92..b1c7bbe5b9 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-logging-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-logging-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-logging-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-logging-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt
index 848c6d856a..a53541427a 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-otlp-common-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-common-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-otlp-common-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-common-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt
index 50c76ab468..49c16fd7d0 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-otlp-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-otlp-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt
index b38200896b..7abad03a3c 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-sender-grpc-managed-channel-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-sender-grpc-managed-channel-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-sender-grpc-managed-channel-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-sender-grpc-managed-channel-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt
index 85aede2379..aa1d482da5 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-sender-jdk-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-sender-jdk-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-sender-jdk-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-sender-jdk-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt
index 6ab8855cde..9f01583dcb 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-sender-okhttp-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-sender-okhttp-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-sender-okhttp-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-sender-okhttp-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt
index 76f764476b..64142ed242 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-exporter-zipkin-1.52.0-SNAPSHOT.jar against opentelemetry-exporter-zipkin-1.51.0.jar
+Comparing source compatibility of opentelemetry-exporter-zipkin-1.53.0-SNAPSHOT.jar against opentelemetry-exporter-zipkin-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt b/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt
index 9af4a4a8cc..6e45651ba6 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-extension-kotlin-1.52.0-SNAPSHOT.jar against opentelemetry-extension-kotlin-1.51.0.jar
+Comparing source compatibility of opentelemetry-extension-kotlin-1.53.0-SNAPSHOT.jar against opentelemetry-extension-kotlin-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt b/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt
index 891f62ba90..1ac8ae240e 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-extension-trace-propagators-1.52.0-SNAPSHOT.jar against opentelemetry-extension-trace-propagators-1.51.0.jar
+Comparing source compatibility of opentelemetry-extension-trace-propagators-1.53.0-SNAPSHOT.jar against opentelemetry-extension-trace-propagators-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt b/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt
index d6ab0403f9..548888915b 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-opentracing-shim-1.52.0-SNAPSHOT.jar against opentelemetry-opentracing-shim-1.51.0.jar
+Comparing source compatibility of opentelemetry-opentracing-shim-1.53.0-SNAPSHOT.jar against opentelemetry-opentracing-shim-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt
index 5d251deb80..ccf7dfc193 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-common-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-common-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-common-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-common-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt
index e39912ab8a..831fedd5bc 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-spi-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-spi-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-spi-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-spi-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt
index 6dcf9a630a..8e69e46ffe 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt
index a89cd3410c..b10c5dd623 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt
index a953ebebc8..7032490f7d 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-logs-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-logs-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-logs-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-logs-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt
index abe77806ba..0ad874a656 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-metrics-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-metrics-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-metrics-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-metrics-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt
index 2c87bd8600..e933234970 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-testing-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-testing-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-testing-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-testing-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt
index e4b6afee82..b02f275437 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-trace-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-trace-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt
index 2a991fb12f..407cc50046 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt
@@ -1,2 +1,2 @@
-Comparing source compatibility of opentelemetry-sdk-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-1.51.0.jar
+Comparing source compatibility of opentelemetry-sdk-1.53.0-SNAPSHOT.jar against opentelemetry-sdk-1.52.0.jar
No changes.
\ No newline at end of file
diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/compression/CompressorUtil.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/compression/CompressorUtil.java
index 9748ea508a..92b7d2d9c6 100644
--- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/compression/CompressorUtil.java
+++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/compression/CompressorUtil.java
@@ -8,9 +8,9 @@ package io.opentelemetry.exporter.internal.compression;
import static io.opentelemetry.api.internal.Utils.checkArgument;
import static java.util.stream.Collectors.joining;
+import io.opentelemetry.common.ComponentLoader;
import java.util.HashMap;
import java.util.Map;
-import java.util.ServiceLoader;
import java.util.Set;
import javax.annotation.Nullable;
@@ -24,7 +24,9 @@ import javax.annotation.Nullable;
*/
public final class CompressorUtil {
- private static final Map compressorRegistry = buildCompressorRegistry();
+ private static final Map compressorRegistry =
+ buildCompressorRegistry(
+ ComponentLoader.forClassLoader(CompressorUtil.class.getClassLoader()));
private CompressorUtil() {}
@@ -36,8 +38,26 @@ public final class CompressorUtil {
*/
@Nullable
public static Compressor validateAndResolveCompressor(String compressionMethod) {
- Set supportedEncodings = compressorRegistry.keySet();
- Compressor compressor = compressorRegistry.get(compressionMethod);
+ return validateAndResolveCompressor(compressionMethod, null);
+ }
+
+ /**
+ * Validate that the {@code compressionMethod} is "none" or matches a registered compressor.
+ *
+ * @param compressionMethod the compression method to validate and resolve
+ * @param componentLoader the component loader to use for loading SPI implementations, or null to
+ * use the default
+ * @return {@code null} if {@code compressionMethod} is "none" or the registered compressor
+ * @throws IllegalArgumentException if no match is found
+ */
+ @Nullable
+ public static Compressor validateAndResolveCompressor(
+ String compressionMethod, @Nullable ComponentLoader componentLoader) {
+ Map registry =
+ componentLoader == null ? compressorRegistry : buildCompressorRegistry(componentLoader);
+
+ Set supportedEncodings = registry.keySet();
+ Compressor compressor = registry.get(compressionMethod);
checkArgument(
"none".equals(compressionMethod) || compressor != null,
"Unsupported compressionMethod. Compression method must be \"none\" or one of: "
@@ -45,10 +65,9 @@ public final class CompressorUtil {
return compressor;
}
- private static Map buildCompressorRegistry() {
+ private static Map buildCompressorRegistry(ComponentLoader componentLoader) {
Map compressors = new HashMap<>();
- for (CompressorProvider spi :
- ServiceLoader.load(CompressorProvider.class, CompressorUtil.class.getClassLoader())) {
+ for (CompressorProvider spi : componentLoader.load(CompressorProvider.class)) {
Compressor compressor = spi.getInstance();
compressors.put(compressor.getEncoding(), compressor);
}
diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java
index 6f2ae64b86..27d06b7116 100644
--- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java
+++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java
@@ -10,9 +10,12 @@ import io.grpc.ManagedChannel;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.internal.ConfigUtil;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
import io.opentelemetry.exporter.internal.TlsConfigHelper;
import io.opentelemetry.exporter.internal.compression.Compressor;
+import io.opentelemetry.exporter.internal.compression.CompressorProvider;
+import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.sdk.common.InternalTelemetryVersion;
import io.opentelemetry.sdk.common.export.RetryPolicy;
@@ -26,7 +29,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.ServiceLoader;
import java.util.StringJoiner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
@@ -67,7 +69,8 @@ public class GrpcExporterBuilder {
private Supplier meterProviderSupplier = GlobalOpenTelemetry::getMeterProvider;
private InternalTelemetryVersion internalTelemetryVersion = InternalTelemetryVersion.LEGACY;
- private ClassLoader serviceClassLoader = GrpcExporterBuilder.class.getClassLoader();
+ private ComponentLoader componentLoader =
+ ComponentLoader.forClassLoader(GrpcExporterBuilder.class.getClassLoader());
@Nullable private ExecutorService executorService;
// Use Object type since gRPC may not be on the classpath.
@@ -115,6 +118,17 @@ public class GrpcExporterBuilder {
return this;
}
+ /**
+ * Sets the method used to compress payloads. If unset, compression is disabled. Compression
+ * method "gzip" and "none" are supported out of the box. Support for additional compression
+ * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ */
+ public GrpcExporterBuilder setCompression(String compressionMethod) {
+ Compressor compressor =
+ CompressorUtil.validateAndResolveCompressor(compressionMethod, componentLoader);
+ return setCompression(compressor);
+ }
+
public GrpcExporterBuilder setTrustManagerFromCerts(byte[] trustedCertificatesPem) {
tlsConfigHelper.setTrustManagerFromCerts(trustedCertificatesPem);
return this;
@@ -158,8 +172,8 @@ public class GrpcExporterBuilder {
return this;
}
- public GrpcExporterBuilder setServiceClassLoader(ClassLoader servieClassLoader) {
- this.serviceClassLoader = servieClassLoader;
+ public GrpcExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ this.componentLoader = componentLoader;
return this;
}
@@ -268,7 +282,7 @@ public class GrpcExporterBuilder {
if (grpcChannel != null) {
joiner.add("grpcChannel=" + grpcChannel);
}
- joiner.add("serviceClassLoader=" + serviceClassLoader);
+ joiner.add("componentLoader=" + componentLoader);
if (executorService != null) {
joiner.add("executorService=" + executorService);
}
@@ -302,8 +316,7 @@ public class GrpcExporterBuilder {
*/
private GrpcSenderProvider resolveGrpcSenderProvider() {
Map grpcSenderProviders = new HashMap<>();
- for (GrpcSenderProvider spi :
- ServiceLoader.load(GrpcSenderProvider.class, serviceClassLoader)) {
+ for (GrpcSenderProvider spi : componentLoader.load(GrpcSenderProvider.class)) {
grpcSenderProviders.put(spi.getClass().getName(), spi);
}
diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java
index 4cd671c32c..42d55cb0a2 100644
--- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java
+++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java
@@ -8,9 +8,12 @@ package io.opentelemetry.exporter.internal.http;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.internal.ConfigUtil;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
import io.opentelemetry.exporter.internal.TlsConfigHelper;
import io.opentelemetry.exporter.internal.compression.Compressor;
+import io.opentelemetry.exporter.internal.compression.CompressorProvider;
+import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.sdk.common.InternalTelemetryVersion;
import io.opentelemetry.sdk.common.export.ProxyOptions;
@@ -24,7 +27,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.ServiceLoader;
import java.util.StringJoiner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
@@ -64,7 +66,8 @@ public final class HttpExporterBuilder {
@Nullable private RetryPolicy retryPolicy = RetryPolicy.getDefault();
private Supplier meterProviderSupplier = GlobalOpenTelemetry::getMeterProvider;
private InternalTelemetryVersion internalTelemetryVersion = InternalTelemetryVersion.LEGACY;
- private ClassLoader serviceClassLoader = HttpExporterBuilder.class.getClassLoader();
+ private ComponentLoader componentLoader =
+ ComponentLoader.forClassLoader(HttpExporterBuilder.class.getClassLoader());
@Nullable private ExecutorService executorService;
public HttpExporterBuilder(
@@ -95,6 +98,17 @@ public final class HttpExporterBuilder {
return this;
}
+ /**
+ * Sets the method used to compress payloads. If unset, compression is disabled. Compression
+ * method "gzip" and "none" are supported out of the box. Support for additional compression
+ * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ */
+ public HttpExporterBuilder setCompression(String compressionMethod) {
+ Compressor compressor =
+ CompressorUtil.validateAndResolveCompressor(compressionMethod, componentLoader);
+ return setCompression(compressor);
+ }
+
public HttpExporterBuilder addConstantHeaders(String key, String value) {
constantHeaders.put(key, value);
return this;
@@ -143,8 +157,8 @@ public final class HttpExporterBuilder {
return this;
}
- public HttpExporterBuilder setServiceClassLoader(ClassLoader servieClassLoader) {
- this.serviceClassLoader = servieClassLoader;
+ public HttpExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ this.componentLoader = componentLoader;
return this;
}
@@ -265,7 +279,7 @@ public final class HttpExporterBuilder {
if (retryPolicy != null) {
joiner.add("retryPolicy=" + retryPolicy);
}
- joiner.add("serviceClassLoader=" + serviceClassLoader);
+ joiner.add("componentLoader=" + componentLoader);
if (executorService != null) {
joiner.add("executorService=" + executorService);
}
@@ -299,8 +313,7 @@ public final class HttpExporterBuilder {
*/
private HttpSenderProvider resolveHttpSenderProvider() {
Map httpSenderProviders = new HashMap<>();
- for (HttpSenderProvider spi :
- ServiceLoader.load(HttpSenderProvider.class, serviceClassLoader)) {
+ for (HttpSenderProvider spi : componentLoader.load(HttpSenderProvider.class)) {
httpSenderProviders.put(spi.getClass().getName(), spi);
}
diff --git a/exporters/common/src/test/java/io/opentelemetry/exporter/internal/compression/CompressorUtilTest.java b/exporters/common/src/test/java/io/opentelemetry/exporter/internal/compression/CompressorUtilTest.java
new file mode 100644
index 0000000000..d8dcffd3c4
--- /dev/null
+++ b/exporters/common/src/test/java/io/opentelemetry/exporter/internal/compression/CompressorUtilTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.exporter.internal.compression;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import io.opentelemetry.common.ComponentLoader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import org.junit.jupiter.api.Test;
+
+class CompressorUtilTest {
+
+ private final ComponentLoader componentLoader =
+ ComponentLoader.forClassLoader(CompressorUtilTest.class.getClassLoader());
+
+ @Test
+ void validateAndResolveCompressor_none() {
+ assertThat(CompressorUtil.validateAndResolveCompressor("none")).isNull();
+ }
+
+ @Test
+ void validateAndResolveCompressor_gzip() {
+ assertThat(CompressorUtil.validateAndResolveCompressor("gzip"))
+ .isEqualTo(GzipCompressor.getInstance());
+ }
+
+ @Test
+ void validateAndResolveCompressor_invalid() {
+ assertThatThrownBy(() -> CompressorUtil.validateAndResolveCompressor("invalid"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Unsupported compressionMethod");
+ }
+
+ @Test
+ void validateAndResolveCompressor_withClassLoader_none() {
+ assertThat(CompressorUtil.validateAndResolveCompressor("none", componentLoader)).isNull();
+ }
+
+ @Test
+ void validateAndResolveCompressor_withClassLoader_gzip() {
+ assertThat(CompressorUtil.validateAndResolveCompressor("gzip", componentLoader))
+ .isEqualTo(GzipCompressor.getInstance());
+ }
+
+ @Test
+ void validateAndResolveCompressor_withClassLoader_invalid() {
+ assertThatThrownBy(
+ () -> CompressorUtil.validateAndResolveCompressor("invalid", componentLoader))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Unsupported compressionMethod");
+ }
+
+ @Test
+ void validateAndResolveCompressor_emptyClassLoader() {
+ // Create a class loader that cannot load CompressorProvider services
+ ComponentLoader emptyComponentLoader =
+ ComponentLoader.forClassLoader(new URLClassLoader(new URL[0], null));
+
+ // Gzip should still work because it's hardcoded
+ assertThat(CompressorUtil.validateAndResolveCompressor("gzip", emptyComponentLoader))
+ .isEqualTo(GzipCompressor.getInstance());
+
+ // None should still work because it doesn't require loading services
+ assertThat(CompressorUtil.validateAndResolveCompressor("none", emptyComponentLoader)).isNull();
+
+ // Any SPI-based compressor should not be available
+ assertThatThrownBy(
+ () -> CompressorUtil.validateAndResolveCompressor("base64", emptyComponentLoader))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Unsupported compressionMethod");
+ }
+
+ @Test
+ void validateAndResolveCompressor_delegatesCorrectly() {
+ // Test that single-parameter method delegates to two-parameter method
+ assertThat(CompressorUtil.validateAndResolveCompressor("gzip"))
+ .isEqualTo(CompressorUtil.validateAndResolveCompressor("gzip", componentLoader));
+
+ assertThat(CompressorUtil.validateAndResolveCompressor("none"))
+ .isEqualTo(CompressorUtil.validateAndResolveCompressor("none", componentLoader));
+ }
+}
diff --git a/exporters/common/src/test/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilderTest.java b/exporters/common/src/test/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilderTest.java
index cdf797df32..b17f3cdb59 100644
--- a/exporters/common/src/test/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilderTest.java
+++ b/exporters/common/src/test/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilderTest.java
@@ -6,11 +6,16 @@
package io.opentelemetry.exporter.internal.grpc;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import io.opentelemetry.common.ComponentLoader;
+import io.opentelemetry.exporter.internal.compression.Compressor;
import io.opentelemetry.exporter.internal.compression.GzipCompressor;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.sdk.internal.StandardComponentId;
import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -36,7 +41,7 @@ class GrpcExporterBuilderTest {
@Test
void compressionNone() {
- builder.setCompression(null);
+ builder.setCompression((Compressor) null);
assertThat(builder).extracting("compressor").isNull();
}
@@ -50,8 +55,45 @@ class GrpcExporterBuilderTest {
@Test
void compressionEnabledAndDisabled() {
- builder.setCompression(GzipCompressor.getInstance()).setCompression(null);
+ builder.setCompression(GzipCompressor.getInstance()).setCompression((Compressor) null);
assertThat(builder).extracting("compressor").isNull();
}
+
+ @Test
+ void compressionString_none() {
+ builder.setCompression("none");
+
+ assertThat(builder).extracting("compressor").isNull();
+ }
+
+ @Test
+ void compressionString_gzip() {
+ builder.setCompression("gzip");
+
+ assertThat(builder).extracting("compressor").isEqualTo(GzipCompressor.getInstance());
+ }
+
+ @Test
+ void compressionString_invalid() {
+ assertThatThrownBy(() -> builder.setCompression("invalid-compression"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Unsupported compressionMethod");
+ }
+
+ @Test
+ void compressionString_usesServiceClassLoader() {
+ // Create a class loader that cannot load CompressorProvider services
+ ComponentLoader emptyComponentLoader =
+ ComponentLoader.forClassLoader(new URLClassLoader(new URL[0], null));
+ builder.setComponentLoader(emptyComponentLoader);
+
+ // This should still work because gzip compressor is hardcoded
+ builder.setCompression("gzip");
+ assertThat(builder).extracting("compressor").isEqualTo(GzipCompressor.getInstance());
+
+ // This should still work because "none" doesn't require loading services
+ builder.setCompression("none");
+ assertThat(builder).extracting("compressor").isNull();
+ }
}
diff --git a/exporters/common/src/test/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilderTest.java b/exporters/common/src/test/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilderTest.java
new file mode 100644
index 0000000000..c924dcd9af
--- /dev/null
+++ b/exporters/common/src/test/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilderTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.exporter.internal.http;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import io.opentelemetry.common.ComponentLoader;
+import io.opentelemetry.exporter.internal.compression.Compressor;
+import io.opentelemetry.exporter.internal.compression.GzipCompressor;
+import io.opentelemetry.exporter.internal.marshal.Marshaler;
+import io.opentelemetry.sdk.internal.StandardComponentId;
+import java.net.URL;
+import java.net.URLClassLoader;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class HttpExporterBuilderTest {
+
+ private HttpExporterBuilder builder;
+
+ @BeforeEach
+ void setUp() {
+ builder =
+ new HttpExporterBuilder<>(
+ StandardComponentId.ExporterType.OTLP_HTTP_SPAN_EXPORTER, "http://localhost:4318");
+ }
+
+ @Test
+ void compressionDefault() {
+ assertThat(builder).extracting("compressor").isNull();
+ }
+
+ @Test
+ void compressionNone() {
+ builder.setCompression((Compressor) null);
+
+ assertThat(builder).extracting("compressor").isNull();
+ }
+
+ @Test
+ void compressionGzip() {
+ builder.setCompression(GzipCompressor.getInstance());
+
+ assertThat(builder).extracting("compressor").isEqualTo(GzipCompressor.getInstance());
+ }
+
+ @Test
+ void compressionEnabledAndDisabled() {
+ builder.setCompression(GzipCompressor.getInstance()).setCompression((Compressor) null);
+
+ assertThat(builder).extracting("compressor").isNull();
+ }
+
+ @Test
+ void compressionString_none() {
+ builder.setCompression("none");
+
+ assertThat(builder).extracting("compressor").isNull();
+ }
+
+ @Test
+ void compressionString_gzip() {
+ builder.setCompression("gzip");
+
+ assertThat(builder).extracting("compressor").isEqualTo(GzipCompressor.getInstance());
+ }
+
+ @Test
+ void compressionString_invalid() {
+ assertThatThrownBy(() -> builder.setCompression("invalid-compression"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Unsupported compressionMethod");
+ }
+
+ @Test
+ void compressionString_usesServiceClassLoader() {
+ // Create a class loader that cannot load CompressorProvider services
+ ComponentLoader emptyComponentLoader =
+ ComponentLoader.forClassLoader(new URLClassLoader(new URL[0], null));
+ builder.setComponentLoader(emptyComponentLoader);
+
+ // This should still work because gzip compressor is hardcoded
+ builder.setCompression("gzip");
+ assertThat(builder).extracting("compressor").isEqualTo(GzipCompressor.getInstance());
+
+ // This should still work because "none" doesn't require loading services
+ builder.setCompression("none");
+ assertThat(builder).extracting("compressor").isNull();
+ }
+}
diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java
index ed7b79f65e..44b046aca4 100644
--- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java
+++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java
@@ -9,11 +9,10 @@ import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Streams;
import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
@@ -29,10 +28,10 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.ServiceLoader;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import javax.annotation.Nullable;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -306,7 +305,7 @@ abstract class AbstractOtlpStdoutExporterTest {
@Test
void componentProviderConfig() {
- DeclarativeConfigProperties properties = mock(DeclarativeConfigProperties.class);
+ DeclarativeConfigProperties properties = spy(DeclarativeConfigProperties.empty());
T exporter = exporterFromComponentProvider(properties);
assertThat(exporter).extracting("wrapperJsonObject").isEqualTo(true);
@@ -330,22 +329,22 @@ abstract class AbstractOtlpStdoutExporterTest {
@SuppressWarnings("unchecked")
protected T exporterFromComponentProvider(DeclarativeConfigProperties properties) {
return (T)
- ((ComponentProvider>)
- loadSpi(ComponentProvider.class)
- .filter(
- p -> {
- ComponentProvider> c = (ComponentProvider>) p;
- return "otlp_file/development".equals(c.getName())
- && c.getType().equals(componentProviderType);
- })
- .findFirst()
- .orElseThrow(() -> new IllegalStateException("No provider found")))
+ StreamSupport.stream(
+ properties.getComponentLoader().load(ComponentProvider.class).spliterator(), false)
+ .filter(
+ p -> {
+ ComponentProvider> c = p;
+ return "otlp_file/development".equals(c.getName())
+ && c.getType().equals(componentProviderType);
+ })
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("No provider found"))
.create(properties);
}
@SuppressWarnings("unchecked")
protected T exporterFromProvider(ConfigProperties config) {
- Object provider = loadProvider();
+ Object provider = loadProvider(config);
try {
return (T)
@@ -358,8 +357,9 @@ abstract class AbstractOtlpStdoutExporterTest {
}
}
- private Object loadProvider() {
- return loadSpi(providerClass)
+ private Object loadProvider(ConfigProperties config) {
+ return StreamSupport.stream(
+ config.getComponentLoader().load(providerClass).spliterator(), false)
.filter(
p -> {
try {
@@ -372,8 +372,4 @@ abstract class AbstractOtlpStdoutExporterTest {
.findFirst()
.orElseThrow(() -> new IllegalStateException("No provider found"));
}
-
- protected static Stream> loadSpi(Class> type) {
- return Streams.stream(ServiceLoader.load(type, type.getClassLoader()).iterator());
- }
}
diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java
index df91f1e2cb..28b0b2e358 100644
--- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java
+++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java
@@ -7,7 +7,7 @@ package io.opentelemetry.exporter.logging.otlp;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
@@ -81,7 +81,7 @@ class OtlpStdoutMetricExporterTest
@Test
void componentProviderMetricConfig() {
- DeclarativeConfigProperties properties = mock(DeclarativeConfigProperties.class);
+ DeclarativeConfigProperties properties = spy(DeclarativeConfigProperties.empty());
when(properties.getString("temporality_preference")).thenReturn("DELTA");
when(properties.getString("default_histogram_aggregation"))
.thenReturn("BASE2_EXPONENTIAL_BUCKET_HISTOGRAM");
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java
index 7dfe6f7426..b960691907 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporterBuilder.java
@@ -10,9 +10,8 @@ import static java.util.Objects.requireNonNull;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.compression.Compressor;
-import io.opentelemetry.exporter.internal.compression.CompressorProvider;
-import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.http.HttpExporterBuilder;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
@@ -112,13 +111,12 @@ public final class OtlpHttpLogRecordExporterBuilder {
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
- * method "gzip" and "none" are supported out of the box. Support for additional compression
- * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ * method "gzip" and "none" are supported out of the box. Additional compression methods can be
+ * supported by providing custom {@link Compressor} implementations via the service loader.
*/
public OtlpHttpLogRecordExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
- Compressor compressor = CompressorUtil.validateAndResolveCompressor(compressionMethod);
- delegate.setCompression(compressor);
+ delegate.setCompression(compressionMethod);
return this;
}
@@ -245,13 +243,20 @@ public final class OtlpHttpLogRecordExporterBuilder {
}
/**
- * Set the {@link ClassLoader} used to load the sender API.
+ * Set the {@link ClassLoader} used to load the sender API. Variant of {@link
+ * #setComponentLoader(ComponentLoader)}.
*
* @since 1.48.0
*/
public OtlpHttpLogRecordExporterBuilder setServiceClassLoader(ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- delegate.setServiceClassLoader(serviceClassLoader);
+ return setComponentLoader(ComponentLoader.forClassLoader(serviceClassLoader));
+ }
+
+ /** Set the {@link ComponentLoader} used to load the sender API. */
+ public OtlpHttpLogRecordExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ requireNonNull(componentLoader, "componentLoader");
+ delegate.setComponentLoader(componentLoader);
return this;
}
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java
index 3d6e6b97e5..07f24dac91 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporterBuilder.java
@@ -10,9 +10,8 @@ import static java.util.Objects.requireNonNull;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.compression.Compressor;
-import io.opentelemetry.exporter.internal.compression.CompressorProvider;
-import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.http.HttpExporterBuilder;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
@@ -132,13 +131,12 @@ public final class OtlpHttpMetricExporterBuilder {
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
- * method "gzip" and "none" are supported out of the box. Support for additional compression
- * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ * method "gzip" and "none" are supported out of the box. Additional compression methods can be
+ * supported by providing custom {@link Compressor} implementations via the service loader.
*/
public OtlpHttpMetricExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
- Compressor compressor = CompressorUtil.validateAndResolveCompressor(compressionMethod);
- delegate.setCompression(compressor);
+ delegate.setCompression(compressionMethod);
return this;
}
@@ -304,13 +302,20 @@ public final class OtlpHttpMetricExporterBuilder {
}
/**
- * Set the {@link ClassLoader} used to load the sender API.
+ * Set the {@link ClassLoader} used to load the sender API. Variant of {@link
+ * #setComponentLoader(ComponentLoader)}.
*
* @since 1.48.0
*/
public OtlpHttpMetricExporterBuilder setServiceClassLoader(ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- delegate.setServiceClassLoader(serviceClassLoader);
+ return setComponentLoader(ComponentLoader.forClassLoader(serviceClassLoader));
+ }
+
+ /** Set the {@link ComponentLoader} used to load the sender API. */
+ public OtlpHttpMetricExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ requireNonNull(componentLoader, "componentLoader");
+ delegate.setComponentLoader(componentLoader);
return this;
}
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java
index 4c2737845d..f8289010b5 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterBuilder.java
@@ -10,9 +10,8 @@ import static java.util.Objects.requireNonNull;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.compression.Compressor;
-import io.opentelemetry.exporter.internal.compression.CompressorProvider;
-import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.http.HttpExporterBuilder;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
@@ -112,13 +111,12 @@ public final class OtlpHttpSpanExporterBuilder {
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
- * method "gzip" and "none" are supported out of the box. Support for additional compression
- * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ * method "gzip" and "none" are supported out of the box. Additional compression methods can be
+ * supported by providing custom {@link Compressor} implementations via the service loader.
*/
public OtlpHttpSpanExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
- Compressor compressor = CompressorUtil.validateAndResolveCompressor(compressionMethod);
- delegate.setCompression(compressor);
+ delegate.setCompression(compressionMethod);
return this;
}
@@ -246,13 +244,20 @@ public final class OtlpHttpSpanExporterBuilder {
}
/**
- * Set the {@link ClassLoader} used to load the sender API.
+ * Set the {@link ClassLoader} used to load the sender API. Variant of {@link
+ * #setComponentLoader(ComponentLoader)}.
*
* @since 1.48.0
*/
public OtlpHttpSpanExporterBuilder setServiceClassLoader(ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- delegate.setServiceClassLoader(serviceClassLoader);
+ return setComponentLoader(ComponentLoader.forClassLoader(serviceClassLoader));
+ }
+
+ /** Set the {@link ComponentLoader} used to load the sender API. */
+ public OtlpHttpSpanExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ requireNonNull(componentLoader, "componentLoader");
+ delegate.setComponentLoader(componentLoader);
return this;
}
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java
index 8bfcb4b396..427d79e7ac 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java
@@ -5,6 +5,7 @@
package io.opentelemetry.exporter.otlp.internal;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
@@ -53,6 +54,7 @@ public final class OtlpConfigUtil {
public static void configureOtlpExporterBuilder(
String dataType,
ConfigProperties config,
+ Consumer setComponentLoader,
Consumer setEndpoint,
BiConsumer addHeader,
Consumer setCompression,
@@ -61,6 +63,8 @@ public final class OtlpConfigUtil {
BiConsumer setClientTls,
Consumer setRetryPolicy,
Consumer setMemoryMode) {
+ setComponentLoader.accept(config.getComponentLoader());
+
String protocol = getOtlpProtocol(dataType, config);
boolean isHttpProtobuf = protocol.equals(PROTOCOL_HTTP_PROTOBUF);
URL endpoint =
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpDeclarativeConfigUtil.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpDeclarativeConfigUtil.java
index dfcd6740bf..b2f174ae3d 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpDeclarativeConfigUtil.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpDeclarativeConfigUtil.java
@@ -11,6 +11,7 @@ import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.readFileByt
import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.validateEndpoint;
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.IncubatingExporterBuilderUtil;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
@@ -47,6 +48,7 @@ public final class OtlpDeclarativeConfigUtil {
public static void configureOtlpExporterBuilder(
String dataType,
DeclarativeConfigProperties config,
+ Consumer setComponentLoader,
Consumer setEndpoint,
BiConsumer addHeader,
Consumer setCompression,
@@ -56,6 +58,8 @@ public final class OtlpDeclarativeConfigUtil {
Consumer setRetryPolicy,
Consumer setMemoryMode,
boolean isHttpProtobuf) {
+ setComponentLoader.accept(config.getComponentLoader());
+
URL endpoint = validateEndpoint(config.getString("endpoint"), isHttpProtobuf);
if (endpoint != null) {
setEndpoint.accept(endpoint.toString());
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcLogRecordExporterComponentProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcLogRecordExporterComponentProvider.java
index 08b6b65d30..f8faab7a00 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcLogRecordExporterComponentProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcLogRecordExporterComponentProvider.java
@@ -39,6 +39,7 @@ public class OtlpGrpcLogRecordExporterComponentProvider
OtlpDeclarativeConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_LOGS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcMetricExporterComponentProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcMetricExporterComponentProvider.java
index f55ab3795c..25f8341fb0 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcMetricExporterComponentProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcMetricExporterComponentProvider.java
@@ -39,6 +39,7 @@ public class OtlpGrpcMetricExporterComponentProvider implements ComponentProvide
OtlpDeclarativeConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_METRICS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcSpanExporterComponentProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcSpanExporterComponentProvider.java
index c84afce9e6..84e230ca51 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcSpanExporterComponentProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpGrpcSpanExporterComponentProvider.java
@@ -38,6 +38,7 @@ public class OtlpGrpcSpanExporterComponentProvider implements ComponentProvider<
OtlpDeclarativeConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_TRACES,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpLogRecordExporterComponentProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpLogRecordExporterComponentProvider.java
index eb9143b181..e6a513e898 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpLogRecordExporterComponentProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpLogRecordExporterComponentProvider.java
@@ -39,6 +39,7 @@ public class OtlpHttpLogRecordExporterComponentProvider
OtlpDeclarativeConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_LOGS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpMetricExporterComponentProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpMetricExporterComponentProvider.java
index f22059d9a7..d6cc1bf62d 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpMetricExporterComponentProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpMetricExporterComponentProvider.java
@@ -39,6 +39,7 @@ public class OtlpHttpMetricExporterComponentProvider implements ComponentProvide
OtlpDeclarativeConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_METRICS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpSpanExporterComponentProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpSpanExporterComponentProvider.java
index 2c9b876979..752e9698dc 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpSpanExporterComponentProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpHttpSpanExporterComponentProvider.java
@@ -38,6 +38,7 @@ public class OtlpHttpSpanExporterComponentProvider implements ComponentProvider<
OtlpDeclarativeConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_TRACES,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProvider.java
index 67ed44c754..1262bc7250 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProvider.java
@@ -45,6 +45,7 @@ public class OtlpLogRecordExporterProvider
OtlpConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_LOGS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
@@ -62,6 +63,7 @@ public class OtlpLogRecordExporterProvider
OtlpConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_LOGS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProvider.java
index a60f57a250..ebfaaacf29 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProvider.java
@@ -38,6 +38,7 @@ public class OtlpMetricExporterProvider implements ConfigurableMetricExporterPro
OtlpConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_METRICS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
@@ -58,6 +59,7 @@ public class OtlpMetricExporterProvider implements ConfigurableMetricExporterPro
OtlpConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_METRICS,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProvider.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProvider.java
index e6fad237d8..1561c057b2 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProvider.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProvider.java
@@ -44,6 +44,7 @@ public class OtlpSpanExporterProvider
OtlpConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_TRACES,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
@@ -61,6 +62,7 @@ public class OtlpSpanExporterProvider
OtlpConfigUtil.configureOtlpExporterBuilder(
DATA_TYPE_TRACES,
config,
+ builder::setComponentLoader,
builder::setEndpoint,
builder::addHeader,
builder::setCompression,
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java
index dbec072655..467aa0cd6a 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporterBuilder.java
@@ -11,9 +11,8 @@ import static java.util.Objects.requireNonNull;
import io.grpc.ManagedChannel;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.compression.Compressor;
-import io.opentelemetry.exporter.internal.compression.CompressorProvider;
-import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
@@ -145,13 +144,12 @@ public final class OtlpGrpcLogRecordExporterBuilder {
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
- * method "gzip" and "none" are supported out of the box. Support for additional compression
- * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ * method "gzip" and "none" are supported out of the box. Additional compression methods can be
+ * supported by providing custom {@link Compressor} implementations via the service loader.
*/
public OtlpGrpcLogRecordExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
- Compressor compressor = CompressorUtil.validateAndResolveCompressor(compressionMethod);
- delegate.setCompression(compressor);
+ delegate.setCompression(compressionMethod);
return this;
}
@@ -274,13 +272,20 @@ public final class OtlpGrpcLogRecordExporterBuilder {
}
/**
- * Set the {@link ClassLoader} used to load the sender API.
+ * Set the {@link ClassLoader} used to load the sender API. Variant of {@link
+ * #setComponentLoader(ComponentLoader)}.
*
* @since 1.48.0
*/
public OtlpGrpcLogRecordExporterBuilder setServiceClassLoader(ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- delegate.setServiceClassLoader(serviceClassLoader);
+ return setComponentLoader(ComponentLoader.forClassLoader(serviceClassLoader));
+ }
+
+ /** Set the {@link ComponentLoader} used to load the sender API. */
+ public OtlpGrpcLogRecordExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ requireNonNull(componentLoader, "componentLoader");
+ delegate.setComponentLoader(componentLoader);
return this;
}
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java
index 8a56a8188a..ef3403c735 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporterBuilder.java
@@ -11,9 +11,8 @@ import static java.util.Objects.requireNonNull;
import io.grpc.ManagedChannel;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.compression.Compressor;
-import io.opentelemetry.exporter.internal.compression.CompressorProvider;
-import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
@@ -164,13 +163,12 @@ public final class OtlpGrpcMetricExporterBuilder {
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
- * method "gzip" and "none" are supported out of the box. Support for additional compression
- * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ * method "gzip" and "none" are supported out of the box. Additional compression methods can be
+ * supported by providing custom {@link Compressor} implementations via the service loader.
*/
public OtlpGrpcMetricExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
- Compressor compressor = CompressorUtil.validateAndResolveCompressor(compressionMethod);
- delegate.setCompression(compressor);
+ delegate.setCompression(compressionMethod);
return this;
}
@@ -332,13 +330,20 @@ public final class OtlpGrpcMetricExporterBuilder {
}
/**
- * Set the {@link ClassLoader} used to load the sender API.
+ * Set the {@link ClassLoader} used to load the sender API. Variant of {@link
+ * #setComponentLoader(ComponentLoader)}.
*
* @since 1.48.0
*/
public OtlpGrpcMetricExporterBuilder setServiceClassLoader(ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- delegate.setServiceClassLoader(serviceClassLoader);
+ return setComponentLoader(ComponentLoader.forClassLoader(serviceClassLoader));
+ }
+
+ /** Set the {@link ComponentLoader} used to load the sender API. */
+ public OtlpGrpcMetricExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ requireNonNull(componentLoader, "componentLoader");
+ delegate.setComponentLoader(componentLoader);
return this;
}
diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java
index 8b0c8c1f9f..fa7523b5b9 100644
--- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java
+++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporterBuilder.java
@@ -11,9 +11,8 @@ import static java.util.Objects.requireNonNull;
import io.grpc.ManagedChannel;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.compression.Compressor;
-import io.opentelemetry.exporter.internal.compression.CompressorProvider;
-import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
@@ -141,13 +140,12 @@ public final class OtlpGrpcSpanExporterBuilder {
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
- * method "gzip" and "none" are supported out of the box. Support for additional compression
- * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ * method "gzip" and "none" are supported out of the box. Additional compression methods can be
+ * supported by providing custom {@link Compressor} implementations via the service loader.
*/
public OtlpGrpcSpanExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
- Compressor compressor = CompressorUtil.validateAndResolveCompressor(compressionMethod);
- delegate.setCompression(compressor);
+ delegate.setCompression(compressionMethod);
return this;
}
@@ -271,13 +269,20 @@ public final class OtlpGrpcSpanExporterBuilder {
}
/**
- * Set the {@link ClassLoader} used to load the sender API.
+ * Set the {@link ClassLoader} used to load the sender API. Variant of {@link
+ * #setComponentLoader(ComponentLoader)}.
*
* @since 1.48.0
*/
public OtlpGrpcSpanExporterBuilder setServiceClassLoader(ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- delegate.setServiceClassLoader(serviceClassLoader);
+ return setComponentLoader(ComponentLoader.forClassLoader(serviceClassLoader));
+ }
+
+ /** Set the {@link ComponentLoader} used to load the sender API. */
+ public OtlpGrpcSpanExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ requireNonNull(componentLoader, "componentLoader");
+ delegate.setComponentLoader(componentLoader);
return this;
}
diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtilTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtilTest.java
index 5716d604ec..fb1061ae3f 100644
--- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtilTest.java
+++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtilTest.java
@@ -371,6 +371,7 @@ class OtlpConfigUtilTest {
OtlpConfigUtil.configureOtlpExporterBuilder(
dataType,
DefaultConfigProperties.createFromMap(properties),
+ value -> {},
endpoint::set,
(value1, value2) -> {},
value -> {},
diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java
index 47ed7859cd..9fe5bad768 100644
--- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java
+++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java
@@ -122,6 +122,7 @@ class OtlpLogRecordExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(Collections.emptyMap()))) {
assertThat(exporter).isInstanceOf(OtlpGrpcLogRecordExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder, never()).setEndpoint(any());
verify(grpcBuilder, never()).addHeader(any(), any());
verify(grpcBuilder, never()).setCompression(any());
@@ -154,6 +155,7 @@ class OtlpLogRecordExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpGrpcLogRecordExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder).setEndpoint("https://localhost:443/");
verify(grpcBuilder).addHeader("header-key", "header-value");
verify(grpcBuilder).setCompression("gzip");
@@ -189,6 +191,7 @@ class OtlpLogRecordExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpGrpcLogRecordExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder).setEndpoint("https://localhost:443/");
verify(grpcBuilder).addHeader("header-key", "header-value");
verify(grpcBuilder).setCompression("gzip");
diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java
index 3d0a409832..e028c6a957 100644
--- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java
+++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpMetricExporterProviderTest.java
@@ -121,6 +121,7 @@ class OtlpMetricExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(Collections.emptyMap()))) {
assertThat(exporter).isInstanceOf(OtlpGrpcMetricExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder, never()).setEndpoint(any());
verify(grpcBuilder, never()).addHeader(any(), any());
verify(grpcBuilder, never()).setCompression(any());
@@ -149,6 +150,7 @@ class OtlpMetricExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpGrpcMetricExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder).setEndpoint("https://localhost:443/");
verify(grpcBuilder).addHeader("header-key", "header-value");
verify(grpcBuilder).setCompression("gzip");
@@ -184,6 +186,7 @@ class OtlpMetricExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpGrpcMetricExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder).setEndpoint("https://localhost:443/");
verify(grpcBuilder).addHeader("header-key", "header-value");
verify(grpcBuilder).setCompression("gzip");
@@ -205,6 +208,7 @@ class OtlpMetricExporterProviderTest {
"otel.exporter.otlp.metrics.protocol", "http/protobuf")))) {
assertThat(exporter).isInstanceOf(OtlpHttpMetricExporter.class);
verify(httpBuilder, times(1)).build();
+ verify(httpBuilder).setComponentLoader(any());
verify(httpBuilder, never()).setEndpoint(any());
verify(httpBuilder, never()).addHeader(any(), any());
verify(httpBuilder, never()).setCompression(any());
@@ -234,6 +238,7 @@ class OtlpMetricExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpHttpMetricExporter.class);
verify(httpBuilder, times(1)).build();
+ verify(httpBuilder).setComponentLoader(any());
verify(httpBuilder).setEndpoint("https://localhost:443/v1/metrics");
verify(httpBuilder).addHeader("header-key", "header-value");
verify(httpBuilder).setCompression("gzip");
@@ -271,6 +276,7 @@ class OtlpMetricExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpHttpMetricExporter.class);
verify(httpBuilder, times(1)).build();
+ verify(httpBuilder).setComponentLoader(any());
verify(httpBuilder).setEndpoint("https://localhost:443/v1/metrics");
verify(httpBuilder).addHeader("header-key", "header-value");
verify(httpBuilder).setCompression("gzip");
diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java
index 46d2e8ea21..1454d209da 100644
--- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java
+++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java
@@ -123,6 +123,7 @@ class OtlpSpanExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(Collections.emptyMap()))) {
assertThat(exporter).isInstanceOf(OtlpGrpcSpanExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder, never()).setEndpoint(any());
verify(grpcBuilder, never()).addHeader(any(), any());
verify(grpcBuilder, never()).setCompression(any());
@@ -155,6 +156,7 @@ class OtlpSpanExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpGrpcSpanExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder).setEndpoint("https://localhost:443/");
verify(grpcBuilder).addHeader("header-key", "header-value");
verify(grpcBuilder).setCompression("gzip");
@@ -190,6 +192,7 @@ class OtlpSpanExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpGrpcSpanExporter.class);
verify(grpcBuilder, times(1)).build();
+ verify(grpcBuilder).setComponentLoader(any());
verify(grpcBuilder).setEndpoint("https://localhost:443/");
verify(grpcBuilder).addHeader("header-key", "header-value");
verify(grpcBuilder).setCompression("gzip");
@@ -210,6 +213,7 @@ class OtlpSpanExporterProviderTest {
Collections.singletonMap("otel.exporter.otlp.traces.protocol", "http/protobuf")))) {
assertThat(exporter).isInstanceOf(OtlpHttpSpanExporter.class);
verify(httpBuilder, times(1)).build();
+ verify(httpBuilder).setComponentLoader(any());
verify(httpBuilder, never()).setEndpoint(any());
verify(httpBuilder, never()).addHeader(any(), any());
verify(httpBuilder, never()).setCompression(any());
@@ -240,6 +244,7 @@ class OtlpSpanExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpHttpSpanExporter.class);
verify(httpBuilder, times(1)).build();
+ verify(httpBuilder).setComponentLoader(any());
verify(httpBuilder).setEndpoint("https://localhost:443/v1/traces");
verify(httpBuilder).addHeader("header-key1", "header value1");
verify(httpBuilder).addHeader("header-key2", "header value2");
@@ -279,6 +284,7 @@ class OtlpSpanExporterProviderTest {
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(exporter).isInstanceOf(OtlpHttpSpanExporter.class);
verify(httpBuilder, times(1)).build();
+ verify(httpBuilder).setComponentLoader(any());
verify(httpBuilder).setEndpoint("https://localhost:443/v1/traces");
verify(httpBuilder).addHeader("header-key", "header-value");
verify(httpBuilder).setCompression("gzip");
diff --git a/exporters/otlp/profiles/src/main/java/io/opentelemetry/exporter/otlp/profiles/OtlpGrpcProfilesExporterBuilder.java b/exporters/otlp/profiles/src/main/java/io/opentelemetry/exporter/otlp/profiles/OtlpGrpcProfilesExporterBuilder.java
index 91d34b00e6..18e19ca51b 100644
--- a/exporters/otlp/profiles/src/main/java/io/opentelemetry/exporter/otlp/profiles/OtlpGrpcProfilesExporterBuilder.java
+++ b/exporters/otlp/profiles/src/main/java/io/opentelemetry/exporter/otlp/profiles/OtlpGrpcProfilesExporterBuilder.java
@@ -10,9 +10,8 @@ import static java.util.Objects.requireNonNull;
import io.grpc.ManagedChannel;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.exporter.internal.compression.Compressor;
-import io.opentelemetry.exporter.internal.compression.CompressorProvider;
-import io.opentelemetry.exporter.internal.compression.CompressorUtil;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
@@ -134,13 +133,12 @@ public final class OtlpGrpcProfilesExporterBuilder {
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
- * method "gzip" and "none" are supported out of the box. Support for additional compression
- * methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
+ * method "gzip" and "none" are supported out of the box. Additional compression methods can be
+ * supported by providing custom {@link Compressor} implementations via the service loader.
*/
public OtlpGrpcProfilesExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
- Compressor compressor = CompressorUtil.validateAndResolveCompressor(compressionMethod);
- delegate.setCompression(compressor);
+ delegate.setCompression(compressionMethod);
return this;
}
@@ -204,10 +202,19 @@ public final class OtlpGrpcProfilesExporterBuilder {
return this;
}
- /** Set the {@link ClassLoader} used to load the sender API. */
+ /**
+ * Set the {@link ClassLoader} used to load the sender API. Variant of {@link
+ * #setComponentLoader(ComponentLoader)}.
+ */
public OtlpGrpcProfilesExporterBuilder setServiceClassLoader(ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- delegate.setServiceClassLoader(serviceClassLoader);
+ return setComponentLoader(ComponentLoader.forClassLoader(serviceClassLoader));
+ }
+
+ /** Set the {@link ComponentLoader} used to load the sender API. */
+ public OtlpGrpcProfilesExporterBuilder setComponentLoader(ComponentLoader componentLoader) {
+ requireNonNull(componentLoader, "componentLoader");
+ delegate.setComponentLoader(componentLoader);
return this;
}
diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java
index 664ad1bd4c..afa04a8139 100644
--- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java
+++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java
@@ -77,6 +77,8 @@ final class Otel2PrometheusConverter {
private static final ThrottlingLogger THROTTLING_LOGGER = new ThrottlingLogger(LOGGER);
private static final String OTEL_SCOPE_NAME = "otel_scope_name";
private static final String OTEL_SCOPE_VERSION = "otel_scope_version";
+ private static final String OTEL_SCOPE_SCHEMA_URL = "otel_scope_schema_url";
+ private static final String OTEL_SCOPE_ATTRIBUTE_PREFIX = "otel_scope_";
private static final long NANOS_PER_MILLISECOND = TimeUnit.MILLISECONDS.toNanos(1);
static final int MAX_CACHE_SIZE = 10;
@@ -488,6 +490,16 @@ final class Otel2PrometheusConverter {
if (scope.getVersion() != null) {
labelNameToValue.putIfAbsent(OTEL_SCOPE_VERSION, scope.getVersion());
}
+ String schemaUrl = scope.getSchemaUrl();
+ if (schemaUrl != null) {
+ labelNameToValue.putIfAbsent(OTEL_SCOPE_SCHEMA_URL, schemaUrl);
+ }
+ scope
+ .getAttributes()
+ .forEach(
+ (key, value) ->
+ labelNameToValue.putIfAbsent(
+ OTEL_SCOPE_ATTRIBUTE_PREFIX + key.getKey(), value.toString()));
}
if (resource != null) {
diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java
index 7cd7c2bdb6..e7b28e42ac 100644
--- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java
+++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java
@@ -26,6 +26,7 @@ import io.prometheus.metrics.model.registry.PrometheusRegistry;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.InetSocketAddress;
+import java.util.StringJoiner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -39,13 +40,17 @@ import javax.annotation.Nullable;
*/
public final class PrometheusHttpServer implements MetricReader {
+ private final String host;
+ private final int port;
+ private final boolean otelScopeEnabled;
+ @Nullable private final Predicate allowedResourceAttributesFilter;
+ private final MemoryMode memoryMode;
+ private final DefaultAggregationSelector defaultAggregationSelector;
+
private final PrometheusHttpServerBuilder builder;
private final HTTPServer httpServer;
private final PrometheusMetricReader prometheusMetricReader;
private final PrometheusRegistry prometheusRegistry;
- private final String host;
- private final MemoryMode memoryMode;
- private final DefaultAggregationSelector defaultAggregationSelector;
/**
* Returns a new {@link PrometheusHttpServer} which can be registered to an {@link
@@ -73,11 +78,15 @@ public final class PrometheusHttpServer implements MetricReader {
@Nullable HttpHandler defaultHandler,
DefaultAggregationSelector defaultAggregationSelector,
@Nullable Authenticator authenticator) {
+ this.host = host;
+ this.port = port;
+ this.otelScopeEnabled = otelScopeEnabled;
+ this.allowedResourceAttributesFilter = allowedResourceAttributesFilter;
+ this.memoryMode = memoryMode;
+ this.defaultAggregationSelector = defaultAggregationSelector;
this.builder = builder;
this.prometheusMetricReader =
new PrometheusMetricReader(otelScopeEnabled, allowedResourceAttributesFilter);
- this.host = host;
- this.memoryMode = memoryMode;
this.prometheusRegistry = prometheusRegistry;
prometheusRegistry.register(prometheusMetricReader);
// When memory mode is REUSABLE_DATA, concurrent reads lead to data corruption. To prevent this,
@@ -106,7 +115,6 @@ public final class PrometheusHttpServer implements MetricReader {
} catch (IOException e) {
throw new UncheckedIOException("Could not create Prometheus HTTP server", e);
}
- this.defaultAggregationSelector = defaultAggregationSelector;
}
@Override
@@ -160,7 +168,16 @@ public final class PrometheusHttpServer implements MetricReader {
@Override
public String toString() {
- return "PrometheusHttpServer{address=" + getAddress() + "}";
+ StringJoiner joiner = new StringJoiner(",", "PrometheusHttpServer{", "}");
+ joiner.add("host=" + host);
+ joiner.add("port=" + port);
+ joiner.add("otelScopeEnabled=" + otelScopeEnabled);
+ joiner.add("allowedResourceAttributesFilter=" + allowedResourceAttributesFilter);
+ joiner.add("memoryMode=" + memoryMode);
+ joiner.add(
+ "defaultAggregationSelector="
+ + DefaultAggregationSelector.asString(defaultAggregationSelector));
+ return joiner.toString();
}
/**
diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java
index 04b8094608..25d069db7a 100644
--- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java
+++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java
@@ -9,7 +9,9 @@ import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
import io.opentelemetry.exporter.prometheus.PrometheusHttpServerBuilder;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
+import io.opentelemetry.sdk.internal.IncludeExcludePredicate;
import io.opentelemetry.sdk.metrics.export.MetricReader;
+import java.util.List;
/**
* Declarative configuration SPI implementation for {@link PrometheusHttpServer}.
@@ -37,11 +39,28 @@ public class PrometheusComponentProvider implements ComponentProvider included = withResourceConstantLabels.getScalarList("included", String.class);
+ List excluded = withResourceConstantLabels.getScalarList("excluded", String.class);
+ if (included != null || excluded != null) {
+ prometheusBuilder.setAllowedResourceAttributesFilter(
+ IncludeExcludePredicate.createPatternMatching(included, excluded));
+ }
+ }
+
return prometheusBuilder.build();
}
}
diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java
index 6395d60c75..4e718c7862 100644
--- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java
+++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java
@@ -38,7 +38,9 @@ import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryData;
import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryPointData;
import io.opentelemetry.sdk.resources.Resource;
import io.prometheus.metrics.expositionformats.ExpositionFormats;
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.Labels;
+import io.prometheus.metrics.model.snapshots.MetricSnapshot;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -47,9 +49,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -63,7 +65,9 @@ class Otel2PrometheusConverterTest {
private static final Pattern PATTERN =
Pattern.compile(
- "# HELP (?.*)\n# TYPE (?.*)\n(?.*)\\{otel_scope_name=\"scope\"}(.|\\n)*");
+ "(.|\\n)*# HELP (?.*)\n# TYPE (?.*)\n(?.*)\\{"
+ + "otel_scope_foo=\"bar\",otel_scope_name=\"scope\","
+ + "otel_scope_schema_url=\"schemaUrl\",otel_scope_version=\"version\"}(.|\\n)*");
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private final Otel2PrometheusConverter converter =
@@ -79,16 +83,17 @@ class Otel2PrometheusConverterTest {
ExpositionFormats.init().getPrometheusTextFormatWriter().write(out, snapshots);
String expositionFormat = new String(out.toByteArray(), StandardCharsets.UTF_8);
- // Uncomment to debug exposition format output
- // System.out.println(expositionFormat);
-
- Matcher matcher = PATTERN.matcher(expositionFormat);
- assertThat(matcher.matches()).isTrue();
- assertThat(matcher.group("help")).isEqualTo(expectedHelp);
- assertThat(matcher.group("type")).isEqualTo(expectedType);
- // Note: Summaries and histograms produce output which matches METRIC_NAME_PATTERN multiple
- // times. The pattern ends up matching against the first.
- assertThat(matcher.group("metricName")).isEqualTo(expectedMetricName);
+ assertThat(expositionFormat)
+ .matchesSatisfying(
+ PATTERN,
+ matcher -> {
+ assertThat(matcher.group("help")).isEqualTo(expectedHelp);
+ assertThat(matcher.group("type")).isEqualTo(expectedType);
+ // Note: Summaries and histograms produce output which matches METRIC_NAME_PATTERN
+ // multiple
+ // times. The pattern ends up matching against the first.
+ assertThat(matcher.group("metricName")).isEqualTo(expectedMetricName);
+ });
}
private static Stream metricMetadataArgs() {
@@ -239,7 +244,7 @@ class Otel2PrometheusConverterTest {
: "my_metric_units",
// "cluster" attribute is added (due to reg expr specified) and only it
- "cluster=\"mycluster\",foo1=\"bar1\",foo2=\"bar2\",otel_scope_name=\"scope\""));
+ "cluster=\"mycluster\",foo1=\"bar1\",foo2=\"bar2\",otel_scope_foo=\"bar\",otel_scope_name=\"scope\",otel_scope_schema_url=\"schemaUrl\",otel_scope_version=\"version\""));
}
// Resource attributes which also exists in the metric labels are not added twice
@@ -258,7 +263,7 @@ class Otel2PrometheusConverterTest {
// "cluster" attribute is present only once and the value is taken
// from the metric attributes and not the resource attributes
- "cluster=\"mycluster2\",foo2=\"bar2\",otel_scope_name=\"scope\""));
+ "cluster=\"mycluster2\",foo2=\"bar2\",otel_scope_foo=\"bar\",otel_scope_name=\"scope\",otel_scope_schema_url=\"schemaUrl\",otel_scope_version=\"version\""));
// Empty attributes
arguments.add(
@@ -273,7 +278,7 @@ class Otel2PrometheusConverterTest {
stringKey("host"), "localhost", stringKey("cluster"), "mycluster"))),
/* allowedResourceAttributesFilter= */ Predicates.startsWith("clu"),
"my_metric_units",
- "cluster=\"mycluster\",otel_scope_name=\"scope\""));
+ "cluster=\"mycluster\",otel_scope_foo=\"bar\",otel_scope_name=\"scope\",otel_scope_schema_url=\"schemaUrl\",otel_scope_version=\"version\""));
return arguments.stream();
}
@@ -314,7 +319,11 @@ class Otel2PrometheusConverterTest {
MetricSnapshots snapshots = converter.convert(Collections.singletonList(metricData));
- Labels labels = snapshots.get(0).getDataPoints().get(0).getLabels();
+ Optional metricSnapshot =
+ snapshots.stream().filter(snapshot -> snapshot instanceof CounterSnapshot).findFirst();
+ assertThat(metricSnapshot).isPresent();
+
+ Labels labels = metricSnapshot.get().getDataPoints().get(0).getLabels();
attributes.forEach(
(key, value) -> {
String labelValue = labels.get(key.getKey());
@@ -368,11 +377,17 @@ class Otel2PrometheusConverterTest {
Attributes attributesToUse = attributes == null ? Attributes.empty() : attributes;
Resource resourceToUse = resource == null ? Resource.getDefault() : resource;
+ InstrumentationScopeInfo scope =
+ InstrumentationScopeInfo.builder("scope")
+ .setVersion("version")
+ .setSchemaUrl("schemaUrl")
+ .setAttributes(Attributes.of(stringKey("foo"), "bar"))
+ .build();
switch (metricDataType) {
case SUMMARY:
return ImmutableMetricData.createDoubleSummary(
resourceToUse,
- InstrumentationScopeInfo.create("scope"),
+ scope,
metricName,
"description",
metricUnit,
@@ -383,7 +398,7 @@ class Otel2PrometheusConverterTest {
case LONG_SUM:
return ImmutableMetricData.createLongSum(
resourceToUse,
- InstrumentationScopeInfo.create("scope"),
+ scope,
metricName,
"description",
metricUnit,
@@ -395,7 +410,7 @@ class Otel2PrometheusConverterTest {
case DOUBLE_SUM:
return ImmutableMetricData.createDoubleSum(
resourceToUse,
- InstrumentationScopeInfo.create("scope"),
+ scope,
metricName,
"description",
metricUnit,
@@ -407,7 +422,7 @@ class Otel2PrometheusConverterTest {
case LONG_GAUGE:
return ImmutableMetricData.createLongGauge(
resourceToUse,
- InstrumentationScopeInfo.create("scope"),
+ scope,
metricName,
"description",
metricUnit,
@@ -417,7 +432,7 @@ class Otel2PrometheusConverterTest {
case DOUBLE_GAUGE:
return ImmutableMetricData.createDoubleGauge(
resourceToUse,
- InstrumentationScopeInfo.create("scope"),
+ scope,
metricName,
"description",
metricUnit,
@@ -427,7 +442,7 @@ class Otel2PrometheusConverterTest {
case HISTOGRAM:
return ImmutableMetricData.createDoubleHistogram(
resourceToUse,
- InstrumentationScopeInfo.create("scope"),
+ scope,
metricName,
"description",
metricUnit,
@@ -448,7 +463,7 @@ class Otel2PrometheusConverterTest {
case EXPONENTIAL_HISTOGRAM:
return ImmutableMetricData.createExponentialHistogram(
resourceToUse,
- InstrumentationScopeInfo.create("scope"),
+ scope,
metricName,
"description",
metricUnit,
diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java
index 81b85fb948..470ae2aa31 100644
--- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java
+++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java
@@ -409,7 +409,15 @@ class PrometheusHttpServerTest {
@Test
void stringRepresentation() {
assertThat(prometheusServer.toString())
- .isEqualTo("PrometheusHttpServer{address=" + prometheusServer.getAddress() + "}");
+ .isEqualTo(
+ "PrometheusHttpServer{"
+ + "host=localhost,"
+ + "port=0,"
+ + "otelScopeEnabled=true,"
+ + "allowedResourceAttributesFilter=null,"
+ + "memoryMode=REUSABLE_DATA,"
+ + "defaultAggregationSelector=DefaultAggregationSelector{COUNTER=default, UP_DOWN_COUNTER=default, HISTOGRAM=default, OBSERVABLE_COUNTER=default, OBSERVABLE_UP_DOWN_COUNTER=default, OBSERVABLE_GAUGE=default, GAUGE=default}"
+ + "}");
}
@Test
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 3735f265b9..78cb6e16a4 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionSha256Sum=7197a12f450794931532469d4ff21a59ea2c1cd59a3ec3f89c035c3c420a6999
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
+distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/integration-tests/graal-incubating/src/test/java/io/opentelemetry/integrationtests/graal/IncubatingApiTests.java b/integration-tests/graal-incubating/src/test/java/io/opentelemetry/integrationtests/graal/IncubatingApiTests.java
index fd3d0162da..bb2eceefd0 100644
--- a/integration-tests/graal-incubating/src/test/java/io/opentelemetry/integrationtests/graal/IncubatingApiTests.java
+++ b/integration-tests/graal-incubating/src/test/java/io/opentelemetry/integrationtests/graal/IncubatingApiTests.java
@@ -19,6 +19,7 @@ import io.opentelemetry.api.incubator.metrics.ExtendedLongHistogram;
import io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounter;
import io.opentelemetry.api.incubator.trace.ExtendedTracer;
import io.opentelemetry.api.logs.LoggerProvider;
+import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.api.trace.TracerProvider;
@@ -50,8 +51,8 @@ class IncubatingApiTests {
.build();
ExtendedLogger logger = (ExtendedLogger) loggerProvider.get("logger");
- logger.isEnabled();
- logger.logRecordBuilder().setBody("message").emit();
+ logger.isEnabled(Severity.INFO);
+ logger.logRecordBuilder().setSeverity(Severity.INFO).setBody("message").emit();
}
@Test
diff --git a/integration-tests/tracecontext/docker/Dockerfile b/integration-tests/tracecontext/docker/Dockerfile
index 02f577a93c..d7ba3fa57f 100644
--- a/integration-tests/tracecontext/docker/Dockerfile
+++ b/integration-tests/tracecontext/docker/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.13.5@sha256:5f69d22a88dd4cc4ee1576def19aef48c8faa1b566054c44291183831cbad13b AS build
+FROM python:3.13.5@sha256:a6af772cf98267c48c145928cbeb35bd8e89b610acd70f93e3e8ac3e96c92af8 AS build
# Main branch SHA as of April-1-2021
ARG TRACECONTEXT_GIT_TAG="dcd3ad9b7d6ac36f70ff3739874b73c11b0302a1"
@@ -11,7 +11,7 @@ RUN unzip trace-context.zip
RUN rm trace-context.zip
RUN mv trace-context-${TRACECONTEXT_GIT_TAG}/test /tracecontext-testsuite
-FROM python:3.13.5-slim@sha256:f2fdaec50160418e0c2867ba3e254755edd067171725886d5d303fd7057bbf81
+FROM python:3.13.5-slim@sha256:6544e0e002b40ae0f59bc3618b07c1e48064c4faed3a15ae2fbd2e8f663e8283
RUN pip install aiohttp
diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java
index 9480b66ac8..0485597edc 100644
--- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java
+++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java
@@ -7,6 +7,7 @@ package io.opentelemetry.sdk.autoconfigure.spi;
import static io.opentelemetry.api.internal.ConfigUtil.defaultIfNull;
+import io.opentelemetry.common.ComponentLoader;
import java.time.Duration;
import java.util.List;
import java.util.Map;
@@ -204,4 +205,9 @@ public interface ConfigProperties {
Map value = getMap(name);
return value.isEmpty() ? defaultValue : value;
}
+
+ /** Return a {@link ComponentLoader} that should be used to load SPIs. */
+ default ComponentLoader getComponentLoader() {
+ return ComponentLoader.forClassLoader(ConfigProperties.class.getClassLoader());
+ }
}
diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java
index b5496df7c4..f8818c015b 100644
--- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java
+++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java
@@ -10,6 +10,7 @@ import static java.util.stream.Collectors.joining;
import io.opentelemetry.api.internal.ConfigUtil;
import io.opentelemetry.api.internal.StringUtils;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import java.time.Duration;
@@ -38,6 +39,7 @@ import javax.annotation.Nullable;
public final class DefaultConfigProperties implements ConfigProperties {
private final Map config;
+ private final ComponentLoader componentLoader;
/**
* Creates a {@link DefaultConfigProperties} by merging system properties, environment variables,
@@ -46,9 +48,10 @@ public final class DefaultConfigProperties implements ConfigProperties {
*
Environment variables take priority over {@code defaultProperties}. System properties take
* priority over environment variables.
*/
- public static DefaultConfigProperties create(Map defaultProperties) {
+ public static DefaultConfigProperties create(
+ Map defaultProperties, ComponentLoader componentLoader) {
return new DefaultConfigProperties(
- ConfigUtil.safeSystemProperties(), System.getenv(), defaultProperties);
+ ConfigUtil.safeSystemProperties(), System.getenv(), defaultProperties, componentLoader);
}
/**
@@ -56,13 +59,18 @@ public final class DefaultConfigProperties implements ConfigProperties {
* properties and environment variables.
*/
public static DefaultConfigProperties createFromMap(Map properties) {
- return new DefaultConfigProperties(properties, Collections.emptyMap(), Collections.emptyMap());
+ return new DefaultConfigProperties(
+ properties,
+ Collections.emptyMap(),
+ Collections.emptyMap(),
+ ComponentLoader.forClassLoader(DefaultConfigProperties.class.getClassLoader()));
}
private DefaultConfigProperties(
Map, ?> systemProperties,
Map environmentVariables,
- Map defaultProperties) {
+ Map defaultProperties,
+ ComponentLoader componentLoader) {
Map config = new HashMap<>();
defaultProperties.forEach(
(name, value) -> config.put(ConfigUtil.normalizePropertyKey(name), value));
@@ -73,6 +81,7 @@ public final class DefaultConfigProperties implements ConfigProperties {
config.put(ConfigUtil.normalizePropertyKey(key.toString()), value.toString()));
this.config = config;
+ this.componentLoader = componentLoader;
}
private DefaultConfigProperties(
@@ -82,6 +91,7 @@ public final class DefaultConfigProperties implements ConfigProperties {
overrides.forEach((name, value) -> config.put(ConfigUtil.normalizePropertyKey(name), value));
this.config = config;
+ this.componentLoader = previousProperties.componentLoader;
}
@Override
@@ -233,6 +243,11 @@ public final class DefaultConfigProperties implements ConfigProperties {
Map.Entry::getKey, Map.Entry::getValue, (first, next) -> next, LinkedHashMap::new));
}
+ @Override
+ public ComponentLoader getComponentLoader() {
+ return componentLoader;
+ }
+
/**
* Return a new {@link DefaultConfigProperties} by overriding the {@code previousProperties} with
* the {@code overrides}.
diff --git a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java
index 78cc6806c0..4a119e600c 100644
--- a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java
+++ b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java
@@ -11,6 +11,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import java.time.Duration;
@@ -22,6 +23,9 @@ import org.junit.jupiter.api.Test;
class ConfigPropertiesTest {
+ private static final ComponentLoader COMPONENT_LOADER =
+ ComponentLoader.forClassLoader(ConfigPropertiesTest.class.getClassLoader());
+
@Test
void allValid() {
Map properties = makeTestProps();
@@ -246,7 +250,7 @@ class ConfigPropertiesTest {
expectedMap.put("bear", "growl");
Map map = makeTestProps();
- ConfigProperties properties = DefaultConfigProperties.create(map);
+ ConfigProperties properties = DefaultConfigProperties.create(map, COMPONENT_LOADER);
assertThat(properties.getBoolean("test.boolean", false)).isTrue();
assertThat(properties.getString("test.string", "nah")).isEqualTo("str");
assertThat(properties.getDouble("test.double", 65.535)).isEqualTo(5.4);
@@ -260,7 +264,7 @@ class ConfigPropertiesTest {
@Test
void defaultMethodsFallBack() {
- ConfigProperties properties = DefaultConfigProperties.create(emptyMap());
+ ConfigProperties properties = DefaultConfigProperties.create(emptyMap(), COMPONENT_LOADER);
assertThat(properties.getBoolean("foo", true)).isTrue();
assertThat(properties.getString("foo", "bar")).isEqualTo("bar");
assertThat(properties.getDouble("foo", 65.535)).isEqualTo(65.535);
@@ -271,7 +275,7 @@ class ConfigPropertiesTest {
@Test
void defaultCollectionTypes() {
- ConfigProperties properties = DefaultConfigProperties.create(emptyMap());
+ ConfigProperties properties = DefaultConfigProperties.create(emptyMap(), COMPONENT_LOADER);
assertThat(properties.getList("foo", Arrays.asList("1", "2", "3")))
.containsExactly("1", "2", "3");
assertThat(properties.getList("foo")).isEmpty();
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java
index 124231fa32..1b0e43c1f1 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java
@@ -8,11 +8,11 @@ package io.opentelemetry.sdk.autoconfigure;
import static java.util.Objects.requireNonNull;
import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.OpenTelemetrySdkBuilder;
-import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
@@ -117,7 +117,7 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
Function.identity();
private ComponentLoader componentLoader =
- SpiHelper.serviceComponentLoader(AutoConfiguredOpenTelemetrySdk.class.getClassLoader());
+ ComponentLoader.forClassLoader(AutoConfiguredOpenTelemetrySdk.class.getClassLoader());
private boolean registerShutdownHook = true;
@@ -410,12 +410,12 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
public AutoConfiguredOpenTelemetrySdkBuilder setServiceClassLoader(
ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
- this.componentLoader = SpiHelper.serviceComponentLoader(serviceClassLoader);
+ this.componentLoader = ComponentLoader.forClassLoader(serviceClassLoader);
return this;
}
/** Sets the {@link ComponentLoader} to be used to load SPI implementations. */
- AutoConfiguredOpenTelemetrySdkBuilder setComponentLoader(ComponentLoader componentLoader) {
+ public AutoConfiguredOpenTelemetrySdkBuilder setComponentLoader(ComponentLoader componentLoader) {
requireNonNull(componentLoader, "componentLoader");
this.componentLoader = componentLoader;
return this;
@@ -628,7 +628,8 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
}
private ConfigProperties computeConfigProperties() {
- DefaultConfigProperties properties = DefaultConfigProperties.create(propertiesSupplier.get());
+ DefaultConfigProperties properties =
+ DefaultConfigProperties.create(propertiesSupplier.get(), componentLoader);
for (Function> customizer : propertiesCustomizers) {
Map overrides = customizer.apply(properties);
properties = properties.withOverrides(overrides);
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/IncubatingUtil.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/IncubatingUtil.java
index a1280e241d..df2686ece5 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/IncubatingUtil.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/IncubatingUtil.java
@@ -8,8 +8,8 @@ package io.opentelemetry.sdk.autoconfigure;
import io.opentelemetry.api.incubator.config.ConfigProvider;
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
import io.opentelemetry.api.incubator.config.GlobalConfigProvider;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.sdk.OpenTelemetrySdk;
-import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.resources.Resource;
import java.io.FileInputStream;
@@ -51,8 +51,9 @@ final class IncubatingUtil {
Class> sdkConfigProvider =
Class.forName("io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider");
Method createFileConfigProvider =
- sdkConfigProvider.getMethod("create", openTelemetryConfiguration);
- ConfigProvider configProvider = (ConfigProvider) createFileConfigProvider.invoke(null, model);
+ sdkConfigProvider.getMethod("create", openTelemetryConfiguration, ComponentLoader.class);
+ ConfigProvider configProvider =
+ (ConfigProvider) createFileConfigProvider.invoke(null, model, componentLoader);
// Note: can't access file configuration resource without reflection so setting a dummy
// resource
return AutoConfiguredOpenTelemetrySdk.create(
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java
index 8e00ee19ab..6f15adfc03 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java
@@ -8,6 +8,7 @@ package io.opentelemetry.sdk.autoconfigure;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
+import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
@@ -59,7 +60,10 @@ public final class ResourceConfiguration {
* @return the resource.
*/
public static Resource createEnvironmentResource() {
- return createEnvironmentResource(DefaultConfigProperties.create(Collections.emptyMap()));
+ return createEnvironmentResource(
+ DefaultConfigProperties.create(
+ Collections.emptyMap(),
+ ComponentLoader.forClassLoader(ResourceConfiguration.class.getClassLoader())));
}
/**
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/AutoConfigureUtil.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/AutoConfigureUtil.java
index 52f0236e8d..8bf42005ba 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/AutoConfigureUtil.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/AutoConfigureUtil.java
@@ -59,22 +59,6 @@ public final class AutoConfigureUtil {
}
}
- /** Sets the {@link ComponentLoader} to be used in the auto-configuration process. */
- public static AutoConfiguredOpenTelemetrySdkBuilder setComponentLoader(
- AutoConfiguredOpenTelemetrySdkBuilder builder, ComponentLoader componentLoader) {
- try {
- Method method =
- AutoConfiguredOpenTelemetrySdkBuilder.class.getDeclaredMethod(
- "setComponentLoader", ComponentLoader.class);
- method.setAccessible(true);
- method.invoke(builder, componentLoader);
- return builder;
- } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
- throw new IllegalStateException(
- "Error calling setComponentLoader on AutoConfiguredOpenTelemetrySdkBuilder", e);
- }
- }
-
/** Sets the {@link ConfigProperties} customizer to be used in the auto-configuration process. */
public static AutoConfiguredOpenTelemetrySdkBuilder setConfigPropertiesCustomizer(
AutoConfiguredOpenTelemetrySdkBuilder builder,
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ComponentLoader.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ComponentLoader.java
index 49bfc4e52f..b7f29db27e 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ComponentLoader.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ComponentLoader.java
@@ -10,14 +10,9 @@ package io.opentelemetry.sdk.autoconfigure.internal;
*
*
Before parsing, environment variable substitution is performed as described in {@link
- * EnvSubstitutionConstructor}.
+ *
During parsing, environment variable substitution is performed as defined in the
+ * OpenTelemetry Configuration Data Model specification.
*
* @throws DeclarativeConfigException if unable to parse
*/
@@ -149,7 +153,7 @@ public final class DeclarativeConfiguration {
// Visible for testing
static Object loadYaml(InputStream inputStream, Map environmentVariables) {
LoadSettings settings = LoadSettings.builder().setSchema(new CoreSchema()).build();
- Load yaml = new Load(settings, new EnvSubstitutionConstructor(settings, environmentVariables));
+ Load yaml = new EnvLoad(settings, environmentVariables);
return yaml.loadFromInputStream(inputStream);
}
@@ -159,8 +163,7 @@ public final class DeclarativeConfiguration {
* @param model the configuration model
* @return a generic {@link DeclarativeConfigProperties} representation of the model
*/
- public static DeclarativeConfigProperties toConfigProperties(
- OpenTelemetryConfigurationModel model) {
+ public static DeclarativeConfigProperties toConfigProperties(Object model) {
return toConfigProperties(model, DEFAULT_COMPONENT_LOADER);
}
@@ -198,7 +201,9 @@ public final class DeclarativeConfiguration {
public static Sampler createSampler(DeclarativeConfigProperties genericSamplerModel) {
YamlDeclarativeConfigProperties yamlDeclarativeConfigProperties =
requireYamlDeclarativeConfigProperties(genericSamplerModel);
- SamplerModel samplerModel = convertToModel(yamlDeclarativeConfigProperties, SamplerModel.class);
+ SamplerModel samplerModel =
+ MAPPER.convertValue(
+ DeclarativeConfigProperties.toMap(yamlDeclarativeConfigProperties), SamplerModel.class);
return createAndMaybeCleanup(
SamplerFactory.getInstance(),
SpiHelper.create(yamlDeclarativeConfigProperties.getComponentLoader()),
@@ -214,11 +219,6 @@ public final class DeclarativeConfiguration {
return (YamlDeclarativeConfigProperties) declarativeConfigProperties;
}
- static T convertToModel(
- YamlDeclarativeConfigProperties yamlDeclarativeConfigProperties, Class modelType) {
- return MAPPER.convertValue(yamlDeclarativeConfigProperties.toMap(), modelType);
- }
-
static R createAndMaybeCleanup(Factory factory, SpiHelper spiHelper, M model) {
DeclarativeConfigContext context = new DeclarativeConfigContext(spiHelper);
try {
@@ -241,89 +241,110 @@ public final class DeclarativeConfiguration {
}
}
- /**
- * {@link StandardConstructor} which substitutes environment variables.
- *
- *
Environment variables follow the syntax {@code ${VARIABLE}}, where {@code VARIABLE} is an
- * environment variable matching the regular expression {@code [a-zA-Z_]+[a-zA-Z0-9_]*}.
- *
- *
Environment variable substitution only takes place on scalar values of maps. References to
- * environment variables in keys or sets are ignored.
- *
- *
If a referenced environment variable is not defined, it is replaced with {@code ""}.
- */
- private static final class EnvSubstitutionConstructor extends StandardConstructor {
+ private static final class EnvLoad extends Load {
- // Load is not thread safe but this instance is always used on the same thread
- private final Load load;
+ private final LoadSettings settings;
private final Map environmentVariables;
- private EnvSubstitutionConstructor(
- LoadSettings loadSettings, Map environmentVariables) {
- super(loadSettings);
- load = new Load(loadSettings);
+ public EnvLoad(LoadSettings settings, Map environmentVariables) {
+ super(settings);
+ this.settings = settings;
this.environmentVariables = environmentVariables;
}
- /**
- * Implementation is same as {@link
- * org.snakeyaml.engine.v2.constructor.BaseConstructor#constructMapping(MappingNode)} except we
- * override the resolution of values with our custom {@link #constructValueObject(Node)}, which
- * performs environment variable substitution.
- */
@Override
- @SuppressWarnings({"ReturnValueIgnored", "CatchingUnchecked"})
- protected Map