diff --git a/api/src/main/java/io/opentelemetry/OpenTelemetry.java b/api/src/main/java/io/opentelemetry/OpenTelemetry.java index 694247f6eb6..cd41c5aabc1 100644 --- a/api/src/main/java/io/opentelemetry/OpenTelemetry.java +++ b/api/src/main/java/io/opentelemetry/OpenTelemetry.java @@ -32,7 +32,7 @@ * This class provides a static global accessor for telemetry objects {@link Tracer}, {@link Meter} * and {@link Tagger}. * - *

The telemetry objects are lazy-loaded singletons resolved via {@link ServiceLoader} mechanism. + *

The telemetry objects are resolved via {@link ServiceLoader} mechanism. * * @see TracerProvider * @see MeterProvider @@ -42,41 +42,47 @@ public final class OpenTelemetry { @Nullable private static volatile OpenTelemetry instance; - private final Tracer tracer; - private final Meter meter; - private final Tagger tagger; + private final TracerProvider tracerProvider; + private final MeterProvider meterProvider; + private final TaggerProvider taggerProvider; /** - * Returns a singleton {@link Tracer}. + * Returns an instance of {@link Tracer}. In a single deployment runtime a singleton is returned, + * however in an application server with multiple deployments a different instance can be used per + * deployment. * * @return registered tracer or default via {@link DefaultTracer#getInstance()}. * @throws IllegalStateException if a specified tracer (via system properties) could not be found. * @since 0.1.0 */ public static Tracer getTracer() { - return getInstance().tracer; + return getInstance().tracerProvider.get(); } /** - * Returns a singleton {@link Meter}. + * Returns an instance {@link Meter}. In a single deployment runtime a singleton is returned, + * however in an application server with multiple deployments a different instance can be used per + * deployment. * * @return registered meter or default via {@link DefaultMeter#getInstance()}. * @throws IllegalStateException if a specified meter (via system properties) could not be found. * @since 0.1.0 */ public static Meter getMeter() { - return getInstance().meter; + return getInstance().meterProvider.get(); } /** - * Returns a singleton {@link Tagger}. + * Returns an instance of {@link Tagger}. In a single deployment runtime a singleton is returned, + * however in an application server with multiple deployments a different instance can be used per + * deployment. * * @return registered meter or default via {@link DefaultTagger#getInstance()}. * @throws IllegalStateException if a specified meter (via system properties) could not be found. * @since 0.1.0 */ public static Tagger getTagger() { - return getInstance().tagger; + return getInstance().taggerProvider.get(); } /** @@ -89,7 +95,11 @@ public static Tagger getTagger() { * @throws IllegalStateException if a specified provider is not found */ @Nullable - private static T loadSpi(Class providerClass) { + private static T loadSpi(Class providerClass, ClassLoader classLoader) { + if (classLoader.getParent() != null) { + return loadSpi(providerClass, classLoader.getParent()); + } + String specifiedProvider = System.getProperty(providerClass.getName()); ServiceLoader providers = ServiceLoader.load(providerClass); for (T provider : providers) { @@ -116,12 +126,39 @@ private static OpenTelemetry getInstance() { } private OpenTelemetry() { - TracerProvider tracerProvider = loadSpi(TracerProvider.class); - tracer = tracerProvider != null ? tracerProvider.create() : DefaultTracer.getInstance(); - MeterProvider meterProvider = loadSpi(MeterProvider.class); - meter = meterProvider != null ? meterProvider.create() : DefaultMeter.getInstance(); - TaggerProvider taggerProvider = loadSpi(TaggerProvider.class); - tagger = taggerProvider != null ? taggerProvider.create() : DefaultTagger.getInstance(); + TracerProvider tracerProvider = + loadSpi(TracerProvider.class, Thread.currentThread().getContextClassLoader()); + this.tracerProvider = + tracerProvider != null + ? tracerProvider + : new TracerProvider() { + @Override + public Tracer get() { + return DefaultTracer.getInstance(); + } + }; + MeterProvider meterProvider = + loadSpi(MeterProvider.class, Thread.currentThread().getContextClassLoader()); + this.meterProvider = + meterProvider != null + ? meterProvider + : new MeterProvider() { + @Override + public Meter get() { + return DefaultMeter.getInstance(); + } + }; + TaggerProvider taggerProvider = + loadSpi(TaggerProvider.class, Thread.currentThread().getContextClassLoader()); + this.taggerProvider = + taggerProvider != null + ? taggerProvider + : new TaggerProvider() { + @Override + public Tagger get() { + return DefaultTagger.getInstance(); + } + }; } // for testing diff --git a/api/src/main/java/io/opentelemetry/metrics/spi/MeterProvider.java b/api/src/main/java/io/opentelemetry/metrics/spi/MeterProvider.java index 84b000b8a54..36dd960de7c 100644 --- a/api/src/main/java/io/opentelemetry/metrics/spi/MeterProvider.java +++ b/api/src/main/java/io/opentelemetry/metrics/spi/MeterProvider.java @@ -31,10 +31,11 @@ public interface MeterProvider { /** - * Creates a new meter instance. + * Creates a meter instance. In a single deployment runtime a singleton is returned, however in an + * application server with multiple deployments a different instance can be used per deployment. * * @return a meter instance. * @since 0.1.0 */ - Meter create(); + Meter get(); } diff --git a/api/src/main/java/io/opentelemetry/tags/spi/TaggerProvider.java b/api/src/main/java/io/opentelemetry/tags/spi/TaggerProvider.java index 5f00563f0ea..7c086dc9df4 100644 --- a/api/src/main/java/io/opentelemetry/tags/spi/TaggerProvider.java +++ b/api/src/main/java/io/opentelemetry/tags/spi/TaggerProvider.java @@ -31,10 +31,12 @@ public interface TaggerProvider { /** - * Creates a new tagger instance. + * Creates a tagger instance. In a single deployment runtime a singleton is returned, however in + * an application server with multiple deployments a different instance can be used per + * deployment. * * @return a tagger instance. * @since 0.1.0 */ - Tagger create(); + Tagger get(); } diff --git a/api/src/main/java/io/opentelemetry/trace/spi/TracerProvider.java b/api/src/main/java/io/opentelemetry/trace/spi/TracerProvider.java index f6089823c25..f3d0aeec146 100644 --- a/api/src/main/java/io/opentelemetry/trace/spi/TracerProvider.java +++ b/api/src/main/java/io/opentelemetry/trace/spi/TracerProvider.java @@ -31,10 +31,12 @@ public interface TracerProvider { /** - * Creates a new tracer instance. + * Returns a tracer instance. In a single deployment runtime a singleton is returned, however in + * an application server with multiple deployments a different instance can be used per + * deployment. * * @return a tracer instance. * @since 0.1.0 */ - Tracer create(); + Tracer get(); } diff --git a/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java b/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java index 4430a3cec18..90d5c55a2aa 100644 --- a/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java +++ b/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java @@ -188,16 +188,20 @@ private static File createService(Class service, Class... impls) throws IO } public static class SecondTracer extends FirstTracer { + private static final Tracer INSTANCE = new SecondTracer(); + @Override - public Tracer create() { - return new SecondTracer(); + public Tracer get() { + return INSTANCE; } } public static class FirstTracer implements Tracer, TracerProvider { + private static final Tracer INSTANCE = new FirstTracer(); + @Override - public Tracer create() { - return new FirstTracer(); + public Tracer get() { + return INSTANCE; } @Override @@ -238,16 +242,20 @@ public HttpTextFormat getHttpTextFormat() { } public static class SecondMeter extends FirstMeter { + private static final Meter INSTANCE = new SecondMeter(); + @Override - public Meter create() { - return new SecondMeter(); + public Meter get() { + return INSTANCE; } } public static class FirstMeter implements Meter, MeterProvider { + private static final Meter INSTANCE = new FirstMeter(); + @Override - public Meter create() { - return new FirstMeter(); + public Meter get() { + return INSTANCE; } @Override @@ -286,16 +294,20 @@ public void record(List measurements, TagMap tags, SpanContext span } public static class SecondTagger extends FirstTagger { + private static final Tagger INSTANCE = new SecondTagger(); + @Override - public Tagger create() { - return new SecondTagger(); + public Tagger get() { + return INSTANCE; } } public static class FirstTagger implements Tagger, TaggerProvider { + private static final Tagger INSTANCE = new FirstTagger(); + @Override - public Tagger create() { - return new FirstTagger(); + public Tagger get() { + return INSTANCE; } @Override diff --git a/sdk/src/main/java/io/opentelemetry/sdk/metrics/MeterSdkProvider.java b/sdk/src/main/java/io/opentelemetry/sdk/metrics/MeterSdkProvider.java index f9fa4c1f9fe..09d9f9eb87a 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/metrics/MeterSdkProvider.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/metrics/MeterSdkProvider.java @@ -26,9 +26,10 @@ * io.opentelemetry.OpenTelemetry}. */ public class MeterSdkProvider implements MeterProvider { + private static final MeterSdk INSTANCE = new MeterSdk(); @Override - public Meter create() { - return new MeterSdk(); + public Meter get() { + return INSTANCE; } } diff --git a/sdk/src/main/java/io/opentelemetry/sdk/tags/TaggerSdkProvider.java b/sdk/src/main/java/io/opentelemetry/sdk/tags/TaggerSdkProvider.java index 1918a540c2d..553c114f1d1 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/tags/TaggerSdkProvider.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/tags/TaggerSdkProvider.java @@ -26,9 +26,10 @@ * io.opentelemetry.OpenTelemetry}. */ public class TaggerSdkProvider implements TaggerProvider { + private static final TaggerSdk INSTANCE = new TaggerSdk(); @Override - public Tagger create() { - return new TaggerSdk(); + public Tagger get() { + return INSTANCE; } } diff --git a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java index faf3271819d..8caddc045bd 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java @@ -25,9 +25,10 @@ * io.opentelemetry.OpenTelemetry}. */ public class TracerSdkProvider implements io.opentelemetry.trace.spi.TracerProvider { + private static final TracerSdk INSTANCE = new TracerSdk(); @Override - public Tracer create() { - return new TracerSdk(); + public Tracer get() { + return INSTANCE; } } diff --git a/sdk/src/test/java/io/opentelemetry/sdk/metrics/MeterSdkProviderTest.java b/sdk/src/test/java/io/opentelemetry/sdk/metrics/MeterSdkProviderTest.java index 1e7059aea61..b0f4ca9dc1a 100644 --- a/sdk/src/test/java/io/opentelemetry/sdk/metrics/MeterSdkProviderTest.java +++ b/sdk/src/test/java/io/opentelemetry/sdk/metrics/MeterSdkProviderTest.java @@ -27,6 +27,7 @@ public class MeterSdkProviderTest { @Test public void testDefault() { - assertThat(new MeterSdkProvider().create()).isInstanceOf(MeterSdk.class); + assertThat(new MeterSdkProvider().get()).isInstanceOf(MeterSdk.class); + assertThat(new MeterSdkProvider().get()).isSameInstanceAs(new MeterSdkProvider().get()); } } diff --git a/sdk/src/test/java/io/opentelemetry/sdk/tags/TaggerSdkProviderTest.java b/sdk/src/test/java/io/opentelemetry/sdk/tags/TaggerSdkProviderTest.java index 3d415cd6c37..5d9e0bfdd5e 100644 --- a/sdk/src/test/java/io/opentelemetry/sdk/tags/TaggerSdkProviderTest.java +++ b/sdk/src/test/java/io/opentelemetry/sdk/tags/TaggerSdkProviderTest.java @@ -27,6 +27,7 @@ public class TaggerSdkProviderTest { @Test public void testDefault() { - assertThat(new TaggerSdkProvider().create()).isInstanceOf(TaggerSdk.class); + assertThat(new TaggerSdkProvider().get()).isInstanceOf(TaggerSdk.class); + assertThat(new TaggerSdkProvider().get()).isSameInstanceAs(new TaggerSdkProvider().get()); } } diff --git a/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java b/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java index c0431b979d8..430d734a857 100644 --- a/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java +++ b/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java @@ -27,6 +27,7 @@ public class TracerSdkProviderTest { @Test public void testDefault() { - assertThat(new TracerSdkProvider().create()).isInstanceOf(TracerSdk.class); + assertThat(new TracerSdkProvider().get()).isInstanceOf(TracerSdk.class); + assertThat(new TracerSdkProvider().get()).isSameInstanceAs(new TracerSdkProvider().get()); } }