Add ConfigurableSamplerProvider to allow custom samplers in agent, etc (#3029)

This commit is contained in:
Anuraag Agrawal 2021-03-17 13:33:22 +09:00 committed by GitHub
parent 66be330d7d
commit f5e0a82e04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 150 additions and 4 deletions

View File

@ -5,6 +5,7 @@
package io.opentelemetry.sdk.autoconfigure;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurableSamplerProvider;
import io.opentelemetry.sdk.autoconfigure.spi.SdkTracerProviderConfigurer;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
@ -18,7 +19,10 @@ import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.time.Duration;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
final class TracerProviderConfiguration {
@ -115,6 +119,14 @@ final class TracerProviderConfiguration {
// Visible for testing
static Sampler configureSampler(String sampler, ConfigProperties config) {
Map<String, Sampler> spiSamplers =
StreamSupport.stream(
ServiceLoader.load(ConfigurableSamplerProvider.class).spliterator(), false)
.collect(
Collectors.toMap(
ConfigurableSamplerProvider::getName,
provider -> provider.createSampler(config)));
switch (sampler) {
case "always_on":
return Sampler.alwaysOn();
@ -141,7 +153,12 @@ final class TracerProviderConfiguration {
return Sampler.parentBased(Sampler.traceIdRatioBased(ratio));
}
default:
throw new ConfigurationException("Unrecognized value for otel.traces.sampler: " + sampler);
Sampler spiSampler = spiSamplers.get(sampler);
if (spiSampler == null) {
throw new ConfigurationException(
"Unrecognized value for otel.traces.sampler: " + sampler);
}
return spiSampler;
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.autoconfigure.spi;
import io.opentelemetry.sdk.autoconfigure.ConfigProperties;
import io.opentelemetry.sdk.trace.samplers.Sampler;
/**
* A service provider interface (SPI) for providing additional samplers that can be used with the
* autoconfigured SDK. If the {@code otel.traces.sampler} property contains a value equal to what is
* returned by {@link #getName()}, the sampler returned by {@link #createSampler(ConfigProperties)}
* will be enabled and added to the SDK.
*/
public interface ConfigurableSamplerProvider {
/**
* Returns a {@link Sampler} that can be registered to OpenTelemetry by providing the property
* value specified by {@link #getName()}.
*/
Sampler createSampler(ConfigProperties config);
/**
* Returns the name of this sampler, which can be specified with the {@code otel.traces.sampler}
* property to enable it. The name returned should NOT be the same as any other exporter name. If
* the name does conflict with another exporter name, the resulting behavior is undefined and it
* is explicitly unspecified which exporter will actually be used.
*/
String getName();
}

View File

@ -10,8 +10,8 @@ import io.opentelemetry.sdk.trace.export.SpanExporter;
/**
* A service provider interface (SPI) for providing additional exporters that can be used with the
* autoconfigured SDK. If the {@code otel.trace.exporter} property contains a value equal to what is
* returned by {@link #getName()}, the exporter returned by {@link
* autoconfigured SDK. If the {@code otel.traces.exporter} property contains a value equal to what
* is returned by {@link #getName()}, the exporter returned by {@link
* #createExporter(ConfigProperties)} will be enabled and added to the SDK.
*/
public interface ConfigurableSpanExporterProvider {
@ -23,7 +23,7 @@ public interface ConfigurableSpanExporterProvider {
SpanExporter createExporter(ConfigProperties config);
/**
* Returns the name of this exporter, which can be specified with the {@code otel.trace.exporter}
* Returns the name of this exporter, which can be specified with the {@code otel.traces.exporter}
* property to enable it. The name returned should NOT be the same as any other exporter name. If
* the name does conflict with another exporter name, the resulting behavior is undefined and it
* is explicitly unspecified which exporter will actually be used.

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.autoconfigure;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.util.Collections;
import org.junit.jupiter.api.Test;
public class ConfigurableSamplerTest {
@Test
void configuration() {
ConfigProperties config =
ConfigProperties.createForTest(ImmutableMap.of("test.option", "true"));
Sampler sampler = TracerProviderConfiguration.configureSampler("testSampler", config);
assertThat(sampler)
.isInstanceOfSatisfying(
TestConfigurableSamplerProvider.TestSampler.class,
s -> assertThat(s.getConfig()).isSameAs(config));
}
@Test
void samplerNotFound() {
assertThatThrownBy(
() ->
TracerProviderConfiguration.configureSampler(
"catSampler", ConfigProperties.createForTest(Collections.emptyMap())))
.isInstanceOf(ConfigurationException.class)
.hasMessageContaining("catSampler");
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.autoconfigure;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurableSamplerProvider;
import io.opentelemetry.sdk.trace.data.LinkData;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.sdk.trace.samplers.SamplingDecision;
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
import java.util.List;
public class TestConfigurableSamplerProvider implements ConfigurableSamplerProvider {
@Override
public Sampler createSampler(ConfigProperties config) {
return new TestSampler(config);
}
@Override
public String getName() {
return "testSampler";
}
public static class TestSampler implements Sampler {
private final ConfigProperties config;
public TestSampler(ConfigProperties config) {
this.config = config;
}
@Override
public SamplingResult shouldSample(
Context parentContext,
String traceId,
String name,
SpanKind spanKind,
Attributes attributes,
List<LinkData> parentLinks) {
return SamplingResult.create(SamplingDecision.RECORD_AND_SAMPLE);
}
@Override
public String getDescription() {
return "test";
}
public ConfigProperties getConfig() {
return config;
}
}
}

View File

@ -0,0 +1 @@
io.opentelemetry.sdk.autoconfigure.TestConfigurableSamplerProvider