Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explicit setup method to API. #1058

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 65 additions & 16 deletions api/src/main/java/io/opentelemetry/OpenTelemetry.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,24 +138,39 @@ private static OpenTelemetry getInstance() {
return instance;
}

private OpenTelemetry() {
TraceProvider traceProvider = loadSpi(TraceProvider.class);
this.tracerProvider =
traceProvider != null
? traceProvider.create()
: DefaultTraceProvider.getInstance().create();

MetricsProvider metricsProvider = loadSpi(MetricsProvider.class);
meterProvider =
metricsProvider != null
? metricsProvider.create()
: DefaultMetricsProvider.getInstance().create();
private static CorrelationContextManager loadCorrelationContextManager() {
CorrelationContextManagerProvider contextManagerProvider =
loadSpi(CorrelationContextManagerProvider.class);
contextManager =
contextManagerProvider != null
? contextManagerProvider.create()
: DefaultCorrelationContextManagerProvider.getInstance().create();
return contextManagerProvider != null
? contextManagerProvider.create()
: DefaultCorrelationContextManagerProvider.getInstance().create();
}

private static MeterProvider loadMeterProvider() {
MetricsProvider metricsProvider = loadSpi(MetricsProvider.class);
return metricsProvider != null
? metricsProvider.create()
: DefaultMetricsProvider.getInstance().create();
}

private static TracerProvider loadTracerProvider() {
TraceProvider traceProvider = loadSpi(TraceProvider.class);
return traceProvider != null
? traceProvider.create()
: DefaultTraceProvider.getInstance().create();
}

private OpenTelemetry(
@Nullable TracerProvider tracerProvider,
@Nullable MeterProvider meterProvider,
@Nullable CorrelationContextManager contextManager) {
this.tracerProvider = tracerProvider != null ? tracerProvider : loadTracerProvider();
this.meterProvider = meterProvider != null ? meterProvider : loadMeterProvider();
this.contextManager = contextManager != null ? contextManager : loadCorrelationContextManager();
}

private OpenTelemetry() {
this(null, null, null);
}

/**
Expand Down Expand Up @@ -183,6 +198,40 @@ private static <T> T loadSpi(Class<T> providerClass) {
return null;
}

/**
* Sets up the OpenTelemetry API to use the given implementation objects.
*
* <p>This method must not be called after attempting to access an API implementation object via
* this class (i.e., after calling methods such as {@link #getTracerProvider()}). Basically this
* means that the one who is in control of the main method is the only one who may call this
* method. Consequently, If another method calls this, this requirement applies to that method
Oberon00 marked this conversation as resolved.
Show resolved Hide resolved
* too, recursively.
*
* <p>This method must only be called once, even if you use any {@code null} arguments. Any null
* arguments are defaulted using the usual mechanism, falling back to the default (no-op)
* implementations if no SPI can be found.
*
* @param tracerProvider The {@link TracerProvider} instance to use, or {@code null} to load using
* default mechanism.
* @param meterProvider The {@link MeterProvider} instance to use, or {@code null} to load using
* default mechanism.
* @param contextManager The {@link CorrelationContextManager} instance to use, or {@code null} to
* load using default mechanism.
* @throws IllegalStateException if OpenTelemetry is already initialized.
*/
public static void setupExplicitImplementations(
@Nullable TracerProvider tracerProvider,
@Nullable MeterProvider meterProvider,
@Nullable CorrelationContextManager contextManager) {
synchronized (OpenTelemetry.class) { // No double-checked locking, not performance-sensitive.
jkwatson marked this conversation as resolved.
Show resolved Hide resolved
if (instance == null) {
instance = new OpenTelemetry(tracerProvider, meterProvider, contextManager);
return;
}
}
throw new IllegalStateException("OpenTelemetry is already initialized.");
jkwatson marked this conversation as resolved.
Show resolved Hide resolved
}

// for testing
static void reset() {
instance = null;
Expand Down
33 changes: 33 additions & 0 deletions api/src/test/java/io/opentelemetry/OpenTelemetryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,39 @@ public void testTracerSystemProperty() throws IOException {
}
}

@Test
public void testSetupExplicit() {
final SecondTraceProvider tracerProvider = new SecondTraceProvider();
final SecondMetricsProvider meterProvider = new SecondMetricsProvider();
final SecondCorrelationContextManager contextManager = new SecondCorrelationContextManager();
OpenTelemetry.setupExplicitImplementations(tracerProvider, meterProvider, contextManager);
assertThat(OpenTelemetry.getTracerProvider()).isSameInstanceAs(tracerProvider);
assertThat(OpenTelemetry.getMeterProvider()).isSameInstanceAs(meterProvider);
assertThat(OpenTelemetry.getCorrelationContextManager()).isSameInstanceAs(contextManager);
}

@Test
public void testSetupDefault() {
OpenTelemetry.setupExplicitImplementations(null, null, null);
testDefault();
}

@Test
public void testSetupTwice() {
OpenTelemetry.setupExplicitImplementations(null, null, null);
thrown.expect(IllegalStateException.class);
thrown.expectMessage("already initialized");
OpenTelemetry.setupExplicitImplementations(null, null, null);
}

@Test
public void testSetupTooLate() {
OpenTelemetry.getTracerProvider(); // Triggers init
thrown.expect(IllegalStateException.class);
thrown.expectMessage("already initialized");
OpenTelemetry.setupExplicitImplementations(null, null, null);
}

@Test
public void testTracerNotFound() {
System.setProperty(TraceProvider.class.getName(), "io.does.not.exists");
Expand Down