Skip to content

Commit

Permalink
Make OpenTelemetrySdk implement the OpenTelemetry interface and have …
Browse files Browse the repository at this point in the history
…SPI find it. (#1857)
  • Loading branch information
Anuraag Agrawal authored Oct 25, 2020
1 parent a8975e8 commit 934c9ed
Show file tree
Hide file tree
Showing 18 changed files with 479 additions and 105 deletions.
1 change: 0 additions & 1 deletion QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,4 +500,3 @@ public class IgnoreExportErrorsFilter implements Filter {
## Registering the custom filter on the BatchSpanProcessor
io.opentelemetry.sdk.trace.export.BatchSpanProcessor = io.opentelemetry.extensions.logging.IgnoreExportErrorsFilter
```

86 changes: 23 additions & 63 deletions api/src/main/java/io/opentelemetry/DefaultOpenTelemetry.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,22 @@

import static java.util.Objects.requireNonNull;

import io.opentelemetry.baggage.BaggageManager;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.context.propagation.DefaultContextPropagators;
import io.opentelemetry.internal.Obfuscated;
import io.opentelemetry.metrics.DefaultMeterProvider;
import io.opentelemetry.metrics.Meter;
import io.opentelemetry.metrics.MeterProvider;
import io.opentelemetry.metrics.spi.MeterProviderFactory;
import io.opentelemetry.spi.OpenTelemetryFactory;
import io.opentelemetry.trace.DefaultTracerProvider;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.TracerProvider;
import io.opentelemetry.trace.spi.TracerProviderFactory;
import java.util.ServiceLoader;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;

/**
* This class provides a static global accessor for telemetry objects {@link Tracer}, {@link Meter}
* and {@link BaggageManager}.
*
* <p>The telemetry objects are lazy-loaded singletons resolved via {@link ServiceLoader} mechanism.
*
* @see TracerProvider
* @see MeterProviderFactory
* The default OpenTelemetry API, which tries to find API implementations via SPI or otherwise falls
* back to no-op default implementations.
*/
@ThreadSafe
final class DefaultOpenTelemetry implements OpenTelemetry {
Expand All @@ -40,7 +32,12 @@ static OpenTelemetry getGlobalOpenTelemetry() {
if (globalOpenTelemetry == null) {
synchronized (mutex) {
if (globalOpenTelemetry == null) {
globalOpenTelemetry = DefaultOpenTelemetry.builder().build();
OpenTelemetryFactory openTelemetryFactory = loadSpi(OpenTelemetryFactory.class);
if (openTelemetryFactory != null) {
globalOpenTelemetry = openTelemetryFactory.create();
} else {
globalOpenTelemetry = builder().build();
}
}
}
}
Expand Down Expand Up @@ -78,10 +75,7 @@ public ContextPropagators getPropagators() {
}

DefaultOpenTelemetry(
TracerProvider tracerProvider,
MeterProvider meterProvider,
BaggageManager baggageManager,
ContextPropagators propagators) {
TracerProvider tracerProvider, MeterProvider meterProvider, ContextPropagators propagators) {
this.tracerProvider = tracerProvider;
this.meterProvider = meterProvider;
this.propagators = propagators;
Expand Down Expand Up @@ -117,45 +111,43 @@ static void reset() {
globalOpenTelemetry = null;
}

Builder toBuilder() {
@Override
public Builder toBuilder() {
return new Builder()
.setTracerProvider(tracerProvider)
.setMeterProvider(meterProvider)
.setPropagators(propagators);
}

static class Builder {
static class Builder implements OpenTelemetry.Builder<Builder> {
private ContextPropagators propagators = DefaultContextPropagators.builder().build();

private TracerProvider tracerProvider;
private MeterProvider meterProvider;
private BaggageManager baggageManager;

Builder setTracerProvider(TracerProvider tracerProvider) {
@Override
public Builder setTracerProvider(TracerProvider tracerProvider) {
requireNonNull(tracerProvider, "tracerProvider");
this.tracerProvider = tracerProvider;
return this;
}

Builder setMeterProvider(MeterProvider meterProvider) {
@Override
public Builder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
this.meterProvider = meterProvider;
return this;
}

Builder setBaggageManager(BaggageManager baggageManager) {
requireNonNull(baggageManager, "baggageManager");
this.baggageManager = baggageManager;
return this;
}

Builder setPropagators(ContextPropagators propagators) {
@Override
public Builder setPropagators(ContextPropagators propagators) {
requireNonNull(propagators, "propagators");
this.propagators = propagators;
return this;
}

DefaultOpenTelemetry build() {
@Override
public OpenTelemetry build() {
MeterProvider meterProvider = this.meterProvider;
if (meterProvider == null) {
MeterProviderFactory meterProviderFactory = loadSpi(MeterProviderFactory.class);
Expand All @@ -170,45 +162,13 @@ DefaultOpenTelemetry build() {
if (tracerProvider == null) {
TracerProviderFactory tracerProviderFactory = loadSpi(TracerProviderFactory.class);
if (tracerProviderFactory != null) {
tracerProvider = new ObfuscatedTracerProvider(tracerProviderFactory.create());
tracerProvider = tracerProviderFactory.create();
} else {
tracerProvider = DefaultTracerProvider.getInstance();
}
}

return new DefaultOpenTelemetry(tracerProvider, meterProvider, baggageManager, propagators);
}
}

/**
* A {@link TracerProvider} wrapper that forces users to access the SDK specific implementation
* via the SDK, instead of via the API and casting it to the SDK specific implementation.
*
* @see Obfuscated
*/
@ThreadSafe
private static class ObfuscatedTracerProvider
implements TracerProvider, Obfuscated<TracerProvider> {

private final TracerProvider delegate;

private ObfuscatedTracerProvider(TracerProvider delegate) {
this.delegate = delegate;
}

@Override
public Tracer get(String instrumentationName) {
return delegate.get(instrumentationName);
}

@Override
public Tracer get(String instrumentationName, String instrumentationVersion) {
return delegate.get(instrumentationName, instrumentationVersion);
}

@Override
public TracerProvider unobfuscate() {
return delegate;
return new DefaultOpenTelemetry(tracerProvider, meterProvider, propagators);
}
}
}
60 changes: 56 additions & 4 deletions api/src/main/java/io/opentelemetry/OpenTelemetry.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,48 @@
/**
* The entrypoint to telemetry functionality for tracing, metrics and baggage.
*
* <p>The default for the OpenTelemetry API will include any {@link
* <p>A global singleton can be retrieved by {@link #get()}. The default for the returned {@link
* OpenTelemetry}, if none has been set via {@link #set(OpenTelemetry)}, will be created with any
* {@link io.opentelemetry.spi.OpenTelemetryFactory}, {@link
* io.opentelemetry.trace.spi.TracerProviderFactory} or {@link
* io.opentelemetry.metrics.spi.MeterProviderFactory} found on the classpath, or otherwise will be
* default, with no-op behavior.
*
* <p>If using the OpenTelemetry SDK, you may want to instantiate the {@link OpenTelemetry} to
* provide configuration, for example of {@code Resource} or {@code Sampler}. See {@code
* OpenTelemetrySdk} and {@code OpenTelemetrySdk.builder} for information on how to construct the
* SDK {@link OpenTelemetry}.
*
* @see TracerProvider
* @see MeterProvider
*/
public interface OpenTelemetry {

/**
* Returns the registered global {@link OpenTelemetry}. If no call to {@link #set(OpenTelemetry)}
* has been made so far, a default {@link OpenTelemetry} composed of functionality any {@link
* io.opentelemetry.spi.OpenTelemetryFactory}, {@link
* io.opentelemetry.trace.spi.TracerProviderFactory} or{@link
* io.opentelemetry.metrics.spi.MeterProviderFactory}, found on the classpath, or otherwise will
* be default, with no-op behavior.
*
* @throws IllegalStateException if a provider has been specified by system property using the
* interface FQCN but the specified provider cannot be found.
*/
static OpenTelemetry get() {
return DefaultOpenTelemetry.getGlobalOpenTelemetry();
}

/**
* Sets the {@link OpenTelemetry} that should be the global instance. Future calls to {@link
* #get()} will return the provided {@link OpenTelemetry} instance. This should be called once as
* early as possible in your application initialization logic, often in a {@code static} block in
* your main class.
*/
static void set(OpenTelemetry openTelemetry) {
DefaultOpenTelemetry.setGlobalOpenTelemetry(openTelemetry);
}

/** Returns the globally registered {@link TracerProvider}. */
static TracerProvider getGlobalTracerProvider() {
return DefaultOpenTelemetry.getGlobalOpenTelemetry().getTracerProvider();
Expand Down Expand Up @@ -109,9 +141,7 @@ static ContextPropagators getGlobalPropagators() {
*/
static void setGlobalPropagators(ContextPropagators propagators) {
requireNonNull(propagators, "propagators");
DefaultOpenTelemetry.setGlobalOpenTelemetry(
((DefaultOpenTelemetry) DefaultOpenTelemetry.getGlobalOpenTelemetry())
.toBuilder().setPropagators(propagators).build());
set(get().toBuilder().setPropagators(propagators).build());
}

/** Returns the {@link TracerProvider} for this {@link OpenTelemetry}. */
Expand Down Expand Up @@ -173,4 +203,26 @@ default Meter getMeter(String instrumentationName, String instrumentationVersion

/** Returns the {@link ContextPropagators} for this {@link OpenTelemetry}. */
ContextPropagators getPropagators();

/** Returns a new {@link Builder} with the configuration of this {@link OpenTelemetry}. */
Builder<?> toBuilder();

/**
* A builder of an implementation of the OpenTelemetry API. Generally used to reconfigure SDK
* implementations.
*/
interface Builder<T extends Builder<T>> {

/** Sets the {@link TracerProvider} to use. */
T setTracerProvider(TracerProvider tracerProvider);

/** Sets the {@link MeterProvider} to use. */
T setMeterProvider(MeterProvider meterProvider);

/** Sets the {@link ContextPropagators} to use. */
T setPropagators(ContextPropagators propagators);

/** Returns a new {@link OpenTelemetry} based on the configuration in this {@link Builder}. */
OpenTelemetry build();
}
}
22 changes: 22 additions & 0 deletions api/src/main/java/io/opentelemetry/spi/OpenTelemetryFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.spi;

import io.opentelemetry.OpenTelemetry;

/**
* A service provider interface (SPI) for a {@link OpenTelemetry}. Fully qualified class name of the
* implementation should be registered in a resource file {@code
* META-INF/services/io.opentelemetry.spi.OpenTelemetryFactory}.
*
* <p>A specific implementation can be selected by setting the system property {@code
* io.opentelemetry.spi.OpenTelemetryFactory} with the value of the fully qualified class name.
*/
public interface OpenTelemetryFactory {

/** Returns a new {@link OpenTelemetry} instance. */
OpenTelemetry create();
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*
* // creating InMemoryMetricExporter
* private final InMemoryMetricExporter exporter = InMemoryMetricExporter.create();
* private final MeterSdkProvider meterSdkProvider = OpenTelemetrySdk.getMeterProvider();
* private final MeterSdkProvider meterSdkProvider = OpenTelemetrySdk.getGlobalMeterProvider();
* private final Meter meter = meterSdkProvider.get("InMemoryMetricExporterExample");
* private IntervalMetricReader intervalMetricReader;
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private static void setupJaegerExporter() {
.setChannel(jaegerChannel)
.setDeadlineMs(30000)
.build();
OpenTelemetrySdk.getTracerManagement()
OpenTelemetrySdk.getGlobalTracerManagement()
.addSpanProcessor(SimpleSpanProcessor.builder(jaegerExporter).build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private void setupJaegerExporter() {
.build();

// Set to process the spans by the Jaeger Exporter
OpenTelemetrySdk.getTracerManagement()
OpenTelemetrySdk.getGlobalTracerManagement()
.addSpanProcessor(SimpleSpanProcessor.builder(jaegerExporter).build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class OpenTelemetryInteroperabilityTest {
OpenTelemetry.getGlobalTracer("opentracingshim");
private final InMemoryTracing inMemoryTracing =
InMemoryTracing.builder()
.setTracerSdkManagement(OpenTelemetrySdk.getTracerManagement())
.setTracerSdkManagement(OpenTelemetrySdk.getGlobalTracerManagement())
.build();
private final Tracer otTracer =
TraceShim.createTracerShim(OpenTelemetry.getGlobalTracerProvider());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void setUp() throws IOException {
@AfterEach
void tearDown() throws IOException {
intervalMetricReader.shutdown();
OpenTelemetrySdk.getTracerManagement().shutdown();
OpenTelemetrySdk.getGlobalTracerManagement().shutdown();

toxiproxyClient.reset();
collectorProxy.delete();
Expand Down Expand Up @@ -239,7 +239,8 @@ private static IntervalMetricReader setupSdk(MetricExporter metricExporter) {
IntervalMetricReader.builder()
.setMetricExporter(metricExporter)
.setMetricProducers(
Collections.singleton(OpenTelemetrySdk.getMeterProvider().getMetricProducer()))
Collections.singleton(
OpenTelemetrySdk.getGlobalMeterProvider().getMetricProducer()))
.setExportIntervalMillis(1000)
.build();
return intervalMetricReader;
Expand All @@ -261,6 +262,6 @@ private static void addOtlpSpanExporter() {
// .setMaxExportBatchSize(1024)
// .setScheduleDelayMillis(1000)
.build();
OpenTelemetrySdk.getTracerManagement().addSpanProcessor(spanProcessor);
OpenTelemetrySdk.getGlobalTracerManagement().addSpanProcessor(spanProcessor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public class SpanAttributeTruncateBenchmark {
@Setup(Level.Trial)
public final void setup() {
TraceConfig config =
OpenTelemetrySdk.getTracerManagement().getActiveTraceConfig().toBuilder()
OpenTelemetrySdk.getGlobalTracerManagement().getActiveTraceConfig().toBuilder()
.setMaxLengthOfAttributeValues(maxLength)
.build();
OpenTelemetrySdk.getTracerManagement().updateActiveTraceConfig(config);
OpenTelemetrySdk.getGlobalTracerManagement().updateActiveTraceConfig(config);
spanBuilderSdk =
(SpanBuilderSdk)
tracerSdk
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class SpanPipelineBenchmark {
@Setup(Level.Trial)
public final void setup() {
SpanExporter exporter = new NoOpSpanExporter();
OpenTelemetrySdk.getTracerManagement()
OpenTelemetrySdk.getGlobalTracerManagement()
.addSpanProcessor(SimpleSpanProcessor.builder(exporter).build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public CompletableResultCode shutdown() {
@State(Scope.Benchmark)
public static class BenchmarkState {
private final MetricProducer metricProducer =
OpenTelemetrySdk.getMeterProvider().getMetricProducer();
OpenTelemetrySdk.getGlobalMeterProvider().getMetricProducer();
private BatchSpanProcessor processor;
private Tracer tracer;
private Collection<MetricData> allMetrics;
Expand Down
Loading

0 comments on commit 934c9ed

Please sign in to comment.