diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java index 82888ed5735..1a28935086b 100644 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java +++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java @@ -12,8 +12,10 @@ import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Sampler; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; @@ -84,30 +86,10 @@ public static OpenTelemetrySdk parseAndCreate(InputStream inputStream) { * @throws ConfigurationException if unable to interpret */ public static OpenTelemetrySdk create(OpenTelemetryConfiguration configurationModel) { - List closeables = new ArrayList<>(); - try { - return OpenTelemetryConfigurationFactory.getInstance() - .create( - configurationModel, - SpiHelper.create(FileConfiguration.class.getClassLoader()), - closeables); - } catch (RuntimeException e) { - logger.info( - "Error encountered interpreting configuration model. Closing partially configured components."); - for (Closeable closeable : closeables) { - try { - logger.fine("Closing " + closeable.getClass().getName()); - closeable.close(); - } catch (IOException ex) { - logger.warning( - "Error closing " + closeable.getClass().getName() + ": " + ex.getMessage()); - } - } - if (e instanceof ConfigurationException) { - throw e; - } - throw new ConfigurationException("Unexpected configuration error", e); - } + return createAndMaybeCleanup( + OpenTelemetryConfigurationFactory.getInstance(), + SpiHelper.create(FileConfiguration.class.getClassLoader()), + configurationModel); } /** @@ -157,6 +139,57 @@ static StructuredConfigProperties toConfigProperties(Object model) { return YamlStructuredConfigProperties.create(configurationMap); } + /** + * Create a {@link Sampler} from the {@code samplerModel} representing the sampler config. + * + *

This is used when samplers are composed, with one sampler accepting one or more additional + * samplers as config properties. The {@link ComponentProvider} implementation can call this to + * configure a delegate {@link Sampler} from the {@link StructuredConfigProperties} corresponding + * to a particular config property. + */ + // TODO(jack-berg): add create methods for all SDK extension components supported by + // ComponentProvider + public static io.opentelemetry.sdk.trace.samplers.Sampler createSampler( + StructuredConfigProperties genericSamplerModel) { + Sampler samplerModel = convertToModel(genericSamplerModel, Sampler.class); + return createAndMaybeCleanup( + SamplerFactory.getInstance(), + SpiHelper.create(FileConfiguration.class.getClassLoader()), + samplerModel); + } + + static T convertToModel( + StructuredConfigProperties structuredConfigProperties, Class modelType) { + if (!(structuredConfigProperties instanceof YamlStructuredConfigProperties)) { + throw new ConfigurationException( + "Only YamlStructuredConfigProperties can be converted to model"); + } + return MAPPER.convertValue( + ((YamlStructuredConfigProperties) structuredConfigProperties).toMap(), modelType); + } + + static R createAndMaybeCleanup(Factory factory, SpiHelper spiHelper, M model) { + List closeables = new ArrayList<>(); + try { + return factory.create(model, spiHelper, closeables); + } catch (RuntimeException e) { + logger.info("Error encountered interpreting model. Closing partially configured components."); + for (Closeable closeable : closeables) { + try { + logger.fine("Closing " + closeable.getClass().getName()); + closeable.close(); + } catch (IOException ex) { + logger.warning( + "Error closing " + closeable.getClass().getName() + ": " + ex.getMessage()); + } + } + if (e instanceof ConfigurationException) { + throw e; + } + throw new ConfigurationException("Unexpected configuration error", e); + } + } + /** * {@link StandardConstructor} which substitutes environment variables. * diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java index f900015f8c4..2f8c3bc4520 100644 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java +++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java @@ -7,20 +7,14 @@ import static java.util.stream.Collectors.joining; -import io.opentelemetry.sdk.autoconfigure.internal.NamedSpiManager; import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.JaegerRemote; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ParentBased; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TraceIdRatioBased; import io.opentelemetry.sdk.trace.samplers.ParentBasedSamplerBuilder; import io.opentelemetry.sdk.trace.samplers.Sampler; import java.io.Closeable; -import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -63,70 +57,49 @@ public Sampler create( : create(parentBasedModel.getRoot(), spiHelper, closeables); ParentBasedSamplerBuilder builder = Sampler.parentBasedBuilder(root); if (parentBasedModel.getRemoteParentSampled() != null) { - builder.setRemoteParentSampled( - create(parentBasedModel.getRemoteParentSampled(), spiHelper, closeables)); + Sampler sampler = create(parentBasedModel.getRemoteParentSampled(), spiHelper, closeables); + builder.setRemoteParentSampled(sampler); } if (parentBasedModel.getRemoteParentNotSampled() != null) { - builder.setRemoteParentNotSampled( - create(parentBasedModel.getRemoteParentNotSampled(), spiHelper, closeables)); + Sampler sampler = + create(parentBasedModel.getRemoteParentNotSampled(), spiHelper, closeables); + builder.setRemoteParentNotSampled(sampler); } if (parentBasedModel.getLocalParentSampled() != null) { - builder.setLocalParentSampled( - create(parentBasedModel.getLocalParentSampled(), spiHelper, closeables)); + Sampler sampler = create(parentBasedModel.getLocalParentSampled(), spiHelper, closeables); + builder.setLocalParentSampled(sampler); } if (parentBasedModel.getLocalParentNotSampled() != null) { - builder.setLocalParentNotSampled( - create(parentBasedModel.getLocalParentNotSampled(), spiHelper, closeables)); + Sampler sampler = + create(parentBasedModel.getLocalParentNotSampled(), spiHelper, closeables); + builder.setLocalParentNotSampled(sampler); } return builder.build(); } JaegerRemote jaegerRemoteModel = model.getJaegerRemote(); if (jaegerRemoteModel != null) { - // Translate from file configuration scheme to environment variable scheme. This is ultimately - // interpreted by JaegerRemoteSamplerProvider, but we want to avoid the dependency on - // opentelemetry-sdk-extension-jaeger-remote-sampler - Map properties = new HashMap<>(); - if (jaegerRemoteModel.getEndpoint() != null) { - properties.put("endpoint", jaegerRemoteModel.getEndpoint()); - } - if (jaegerRemoteModel.getInterval() != null) { - properties.put("pollingInterval", String.valueOf(jaegerRemoteModel.getInterval())); - } - // TODO(jack-berg): determine how to support initial sampler. This is first case where a - // component configured via SPI has property that isn't available in the environment variable - // scheme. - String otelTraceSamplerArg = - properties.entrySet().stream() - .map(entry -> entry.getKey() + "=" + entry.getValue()) - .collect(joining(",")); - - ConfigProperties configProperties = - DefaultConfigProperties.createFromMap( - Collections.singletonMap("otel.traces.sampler.arg", otelTraceSamplerArg)); - return FileConfigUtil.addAndReturn( - closeables, - FileConfigUtil.assertNotNull( - samplerSpiManager(configProperties, spiHelper).getByName("jaeger_remote"), - "jaeger remote sampler")); + model.getAdditionalProperties().put("jaeger_remote", jaegerRemoteModel); } - // TODO(jack-berg): add support for generic SPI samplers if (!model.getAdditionalProperties().isEmpty()) { - throw new ConfigurationException( - "Unrecognized sampler(s): " - + model.getAdditionalProperties().keySet().stream().collect(joining(",", "[", "]"))); + Map additionalProperties = model.getAdditionalProperties(); + if (additionalProperties.size() > 1) { + throw new ConfigurationException( + "Invalid configuration - multiple samplers exporters set: " + + additionalProperties.keySet().stream().collect(joining(",", "[", "]"))); + } + Map.Entry exporterKeyValue = + additionalProperties.entrySet().stream() + .findFirst() + .orElseThrow( + () -> new IllegalStateException("Missing sampler. This is a programming error.")); + Sampler sampler = + FileConfigUtil.loadComponent( + spiHelper, Sampler.class, exporterKeyValue.getKey(), exporterKeyValue.getValue()); + return FileConfigUtil.addAndReturn(closeables, sampler); } else { throw new ConfigurationException("sampler must be set"); } } - - private static NamedSpiManager samplerSpiManager( - ConfigProperties config, SpiHelper spiHelper) { - return spiHelper.loadConfigurable( - ConfigurableSamplerProvider.class, - ConfigurableSamplerProvider::getName, - ConfigurableSamplerProvider::createSampler, - config); - } } diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java index 6475bbe1698..2e9e20d3f0c 100644 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java +++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java @@ -35,13 +35,13 @@ final class YamlStructuredConfigProperties implements StructuredConfigProperties /** Values are {@link #isPrimitive(Object)}, {@link List} of scalars. */ private final Map simpleEntries; - private final Map> listEntries; - private final Map mapEntries; + private final Map> listEntries; + private final Map mapEntries; private YamlStructuredConfigProperties( Map simpleEntries, - Map> listEntries, - Map mapEntries) { + Map> listEntries, + Map mapEntries) { this.simpleEntries = simpleEntries; this.listEntries = listEntries; this.mapEntries = mapEntries; @@ -59,8 +59,8 @@ private YamlStructuredConfigProperties( @SuppressWarnings("unchecked") static YamlStructuredConfigProperties create(Map properties) { Map simpleEntries = new HashMap<>(); - Map> listEntries = new HashMap<>(); - Map mapEntries = new HashMap<>(); + Map> listEntries = new HashMap<>(); + Map mapEntries = new HashMap<>(); for (Map.Entry entry : properties.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); @@ -73,7 +73,7 @@ static YamlStructuredConfigProperties create(Map properties) { continue; } if (isListOfMaps(value)) { - List list = + List list = ((List>) value) .stream().map(YamlStructuredConfigProperties::create).collect(toList()); listEntries.put(key, list); @@ -257,7 +257,11 @@ public StructuredConfigProperties getStructured(String name) { @Nullable @Override public List getStructuredList(String name) { - return listEntries.get(name); + List value = listEntries.get(name); + if (value != null) { + return Collections.unmodifiableList(value); + } + return null; } @Override @@ -277,4 +281,15 @@ public String toString() { mapEntries.forEach((key, value) -> joiner.add(key + "=" + value)); return joiner.toString(); } + + /** Return a map representation of the data. */ + Map toMap() { + Map result = new HashMap<>(simpleEntries); + listEntries.forEach( + (key, value) -> + result.put( + key, value.stream().map(YamlStructuredConfigProperties::toMap).collect(toList()))); + mapEntries.forEach((key, value) -> result.put(key, value.toMap())); + return Collections.unmodifiableMap(result); + } } diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfigurationCreateTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfigurationCreateTest.java index dcd90cd60c4..d47ae14eb9a 100644 --- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfigurationCreateTest.java +++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfigurationCreateTest.java @@ -121,7 +121,7 @@ void parseAndCreate_Exception_CleansUpPartials() { .hasMessage( "No component provider detected for io.opentelemetry.sdk.logs.export.LogRecordExporter with name \"foo\"."); logCapturer.assertContains( - "Error encountered interpreting configuration model. Closing partially configured components."); + "Error encountered interpreting model. Closing partially configured components."); logCapturer.assertContains( "Closing io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter"); logCapturer.assertContains("Closing io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor"); diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java index 4df997c3b2a..4413ddb34c7 100644 --- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java +++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java @@ -13,6 +13,7 @@ import io.opentelemetry.internal.testing.slf4j.SuppressLogger; import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; +import io.opentelemetry.sdk.extension.incubator.fileconfig.component.SamplerComponentProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AlwaysOff; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AlwaysOn; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.JaegerRemote; @@ -116,23 +117,41 @@ private static Stream createArguments() { JaegerRemoteSampler.builder() .setEndpoint("http://jaeger-remote-endpoint") .setPollingInterval(Duration.ofSeconds(10)) + .setInitialSampler(io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOff()) .build())); } @Test - void create_SpiExporter() { + void create_SpiExporter_Unknown() { List closeables = new ArrayList<>(); assertThatThrownBy( () -> SamplerFactory.getInstance() .create( - new Sampler() - .withAdditionalProperty("test", ImmutableMap.of("key1", "value1")), + new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model + .Sampler() + .withAdditionalProperty( + "unknown_key", ImmutableMap.of("key1", "value1")), spiHelper, new ArrayList<>())) .isInstanceOf(ConfigurationException.class) - .hasMessage("Unrecognized sampler(s): [test]"); + .hasMessage( + "No component provider detected for io.opentelemetry.sdk.trace.samplers.Sampler with name \"unknown_key\"."); cleanup.addCloseables(closeables); } + + @Test + void create_SpiExporter_Valid() { + io.opentelemetry.sdk.trace.samplers.Sampler sampler = + SamplerFactory.getInstance() + .create( + new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Sampler() + .withAdditionalProperty("test", ImmutableMap.of("key1", "value1")), + spiHelper, + new ArrayList<>()); + assertThat(sampler).isInstanceOf(SamplerComponentProvider.TestSampler.class); + assertThat(((SamplerComponentProvider.TestSampler) sampler).config.getString("key1")) + .isEqualTo("value1"); + } } diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SamplerComponentProvider.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SamplerComponentProvider.java new file mode 100644 index 00000000000..2d4c983e4d7 --- /dev/null +++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SamplerComponentProvider.java @@ -0,0 +1,58 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.extension.incubator.fileconfig.component; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import java.util.List; + +public class SamplerComponentProvider implements ComponentProvider { + @Override + public Class getType() { + return Sampler.class; + } + + @Override + public String getName() { + return "test"; + } + + @Override + public Sampler create(StructuredConfigProperties config) { + return new TestSampler(config); + } + + public static class TestSampler implements Sampler { + + public final StructuredConfigProperties config; + + private TestSampler(StructuredConfigProperties config) { + this.config = config; + } + + @Override + public SamplingResult shouldSample( + Context parentContext, + String traceId, + String name, + SpanKind spanKind, + Attributes attributes, + List parentLinks) { + return SamplingResult.recordOnly(); + } + + @Override + public String getDescription() { + return "test"; + } + } +} diff --git a/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider b/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider index 88759776549..2bc161f4d9c 100644 --- a/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider +++ b/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider @@ -1,6 +1,7 @@ io.opentelemetry.sdk.extension.incubator.fileconfig.component.MetricExporterComponentProvider io.opentelemetry.sdk.extension.incubator.fileconfig.component.SpanExporterComponentProvider io.opentelemetry.sdk.extension.incubator.fileconfig.component.LogRecordExporterComponentProvider +io.opentelemetry.sdk.extension.incubator.fileconfig.component.SamplerComponentProvider io.opentelemetry.sdk.extension.incubator.fileconfig.component.SpanProcessorComponentProvider io.opentelemetry.sdk.extension.incubator.fileconfig.component.LogRecordProcessorComponentProvider io.opentelemetry.sdk.extension.incubator.fileconfig.component.ResourceComponentProvider diff --git a/sdk-extensions/jaeger-remote-sampler/build.gradle.kts b/sdk-extensions/jaeger-remote-sampler/build.gradle.kts index fca0210b6a1..ac250eef3d1 100644 --- a/sdk-extensions/jaeger-remote-sampler/build.gradle.kts +++ b/sdk-extensions/jaeger-remote-sampler/build.gradle.kts @@ -13,6 +13,7 @@ otelJava.moduleName.set("io.opentelemetry.sdk.extension.trace.jaeger") dependencies { api(project(":sdk:all")) compileOnly(project(":sdk-extensions:autoconfigure")) + compileOnly(project(":sdk-extensions:incubator")) implementation(project(":sdk:all")) implementation(project(":exporters:common")) diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java new file mode 100644 index 00000000000..9ce99c908b2 --- /dev/null +++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.extension.trace.jaeger.sampler.internal; + +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.FileConfiguration; +import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler; +import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSamplerBuilder; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.time.Duration; + +/** + * File configuration SPI implementation for {@link JaegerRemoteSampler}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class JaegerRemoteSamplerComponentProvider implements ComponentProvider { + @Override + public Class getType() { + return Sampler.class; + } + + @Override + public String getName() { + return "jaeger_remote"; + } + + @Override + public Sampler create(StructuredConfigProperties config) { + JaegerRemoteSamplerBuilder builder = JaegerRemoteSampler.builder(); + + // Optional configuration + String endpoint = config.getString("endpoint"); + if (endpoint != null) { + builder.setEndpoint(endpoint); + } + Long pollingIntervalMs = config.getLong("internal"); + if (pollingIntervalMs != null) { + builder.setPollingInterval(Duration.ofMillis(pollingIntervalMs)); + } + StructuredConfigProperties initialSamplerModel = config.getStructured("initial_sampler"); + if (initialSamplerModel != null) { + Sampler initialSampler = FileConfiguration.createSampler(initialSamplerModel); + builder.setInitialSampler(initialSampler); + } + + return builder.build(); + } +} diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider b/sdk-extensions/jaeger-remote-sampler/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider new file mode 100644 index 00000000000..a06efe29e4f --- /dev/null +++ b/sdk-extensions/jaeger-remote-sampler/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider @@ -0,0 +1 @@ +io.opentelemetry.sdk.extension.trace.jaeger.sampler.internal.JaegerRemoteSamplerComponentProvider