Skip to content

Commit 73ef00a

Browse files
committed
Wire ResourceProvider in end-to-end test with new incubating ExtendedOpenTelemetry API.
- Update shared state in SDK to use Supplier<Resource> instead of Resource - Add helper utils to expose private methods to supply the supplier - Create new ExtendedOpenTelemetry* API/SDK and end-to-end test.
1 parent ebf9557 commit 73ef00a

File tree

21 files changed

+659
-22
lines changed

21 files changed

+659
-22
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.sdk.extension.incubator;
7+
8+
import io.opentelemetry.api.incubator.entities.ExtendedOpenTelemetry;
9+
import io.opentelemetry.sdk.common.CompletableResultCode;
10+
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
11+
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
12+
import io.opentelemetry.sdk.trace.SdkTracerProvider;
13+
import java.io.Closeable;
14+
15+
/** A new interface for creating OpenTelemetrySdk that supports {@link ResourceProvider}. */
16+
public interface ExtendedOpenTelemetrySdk extends ExtendedOpenTelemetry, Closeable {
17+
/**
18+
* Shutdown the SDK. Calls {@link SdkTracerProvider#shutdown()}, {@link
19+
* SdkMeterProvider#shutdown()}, and {@link SdkLoggerProvider#shutdown()}.
20+
*
21+
* @return a {@link CompletableResultCode} which completes when all providers are shutdown
22+
*/
23+
CompletableResultCode shutdown();
24+
25+
/** Returns a builder for {@link ExtendedOpenTelemetrySdk}. */
26+
static ExtendedOpenTelemetrySdkBuilder builder() {
27+
return new ExtendedOpenTelemetrySdkBuilder();
28+
}
29+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.sdk.extension.incubator;
7+
8+
import io.opentelemetry.api.GlobalOpenTelemetry;
9+
import io.opentelemetry.context.propagation.ContextPropagators;
10+
import io.opentelemetry.sdk.OpenTelemetrySdk;
11+
import io.opentelemetry.sdk.OpenTelemetrySdkBuilder;
12+
import io.opentelemetry.sdk.extension.incubator.entities.SdkResourceProvider;
13+
import io.opentelemetry.sdk.extension.incubator.entities.SdkResourceProviderBuilder;
14+
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
15+
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
16+
import io.opentelemetry.sdk.logs.internal.SdkLoggerProviderUtil;
17+
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
18+
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
19+
import io.opentelemetry.sdk.metrics.internal.SdkMeterProviderUtil;
20+
import io.opentelemetry.sdk.trace.SdkTracerProvider;
21+
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
22+
import io.opentelemetry.sdk.trace.internal.SdkTracerProviderUtil;
23+
import java.util.function.Consumer;
24+
25+
/** A new interface for creating OpenTelemetrySdk that supports {@link ResourceProvider}. */
26+
public final class ExtendedOpenTelemetrySdkBuilder {
27+
private ContextPropagators propagators = ContextPropagators.noop();
28+
private final SdkTracerProviderBuilder tracerProviderBuilder = SdkTracerProvider.builder();
29+
private final SdkMeterProviderBuilder meterProviderBuilder = SdkMeterProvider.builder();
30+
private final SdkLoggerProviderBuilder loggerProviderBuilder = SdkLoggerProvider.builder();
31+
private final SdkResourceProviderBuilder resourceProviderBuilder = SdkResourceProvider.builder();
32+
33+
/** Sets the {@link ContextPropagators} to use. */
34+
public ExtendedOpenTelemetrySdkBuilder setPropagators(ContextPropagators propagators) {
35+
this.propagators = propagators;
36+
return this;
37+
}
38+
39+
/**
40+
* Applies a consumer callback to configure the TracerProvider being built for this OpenTelemetry.
41+
*
42+
* @param configurator A callback fleshing out tracers.
43+
* @return this
44+
*/
45+
public ExtendedOpenTelemetrySdkBuilder withTracerProvider(
46+
Consumer<SdkTracerProviderBuilder> configurator) {
47+
configurator.accept(this.tracerProviderBuilder);
48+
return this;
49+
}
50+
51+
/**
52+
* Applies a consumer callback to configure the MeterProvider being built for this OpenTelemetry.
53+
*
54+
* @param configurator A callback fleshing out meters.
55+
* @return this
56+
*/
57+
public ExtendedOpenTelemetrySdkBuilder withMeterProvider(
58+
Consumer<SdkMeterProviderBuilder> configurator) {
59+
configurator.accept(this.meterProviderBuilder);
60+
return this;
61+
}
62+
63+
/**
64+
* Applies a consumer callback to configure the LoggerProvider being built for this OpenTelemetry.
65+
*
66+
* @param configurator A callback fleshing out meters.
67+
* @return this
68+
*/
69+
public ExtendedOpenTelemetrySdkBuilder withLoggerProvider(
70+
Consumer<SdkLoggerProviderBuilder> configurator) {
71+
configurator.accept(this.loggerProviderBuilder);
72+
return this;
73+
}
74+
75+
/**
76+
* Returns a new {@link OpenTelemetrySdk} built with the configuration of this {@link
77+
* OpenTelemetrySdkBuilder}. This SDK is not registered as the global {@link
78+
* io.opentelemetry.api.OpenTelemetry}. It is recommended that you register one SDK using {@link
79+
* OpenTelemetrySdkBuilder#buildAndRegisterGlobal()} for use by instrumentation that requires
80+
* access to a global instance of {@link io.opentelemetry.api.OpenTelemetry}.
81+
*
82+
* @see GlobalOpenTelemetry
83+
*/
84+
public ExtendedOpenTelemetrySdk build() {
85+
SdkResourceProvider resourceProvider = resourceProviderBuilder.build();
86+
SdkTracerProvider tracerProvider =
87+
SdkTracerProviderUtil.setResourceSupplier(
88+
tracerProviderBuilder, resourceProvider::getSdkResource)
89+
.build();
90+
SdkMeterProvider meterProvider =
91+
SdkMeterProviderUtil.setResourceSupplier(
92+
meterProviderBuilder, resourceProvider::getSdkResource)
93+
.build();
94+
SdkLoggerProvider loggerProvider =
95+
SdkLoggerProviderUtil.setResourceSupplier(
96+
loggerProviderBuilder, resourceProvider::getSdkResource)
97+
.build();
98+
return new ObfuscatedExtendedOpenTelemerySdk(
99+
resourceProvider, tracerProvider, meterProvider, loggerProvider, propagators);
100+
}
101+
102+
/**
103+
* Returns a new {@link OpenTelemetrySdk} built with the configuration of this {@link
104+
* OpenTelemetrySdkBuilder} and registers it as the global {@link
105+
* io.opentelemetry.api.OpenTelemetry}. An exception will be thrown if this method is attempted to
106+
* be called multiple times in the lifecycle of an application - ensure you have only one SDK for
107+
* use as the global instance. If you need to configure multiple SDKs for tests, use {@link
108+
* GlobalOpenTelemetry#resetForTest()} between them.
109+
*
110+
* @see GlobalOpenTelemetry
111+
*/
112+
public ExtendedOpenTelemetrySdk buildAndRegisterGlobal() {
113+
ExtendedOpenTelemetrySdk sdk = build();
114+
GlobalOpenTelemetry.set(sdk);
115+
return sdk;
116+
}
117+
}
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.sdk.extension.incubator;
7+
8+
import io.opentelemetry.api.incubator.entities.Resource;
9+
import io.opentelemetry.api.incubator.entities.ResourceProvider;
10+
import io.opentelemetry.api.logs.LoggerBuilder;
11+
import io.opentelemetry.api.logs.LoggerProvider;
12+
import io.opentelemetry.api.metrics.MeterBuilder;
13+
import io.opentelemetry.api.metrics.MeterProvider;
14+
import io.opentelemetry.api.trace.Tracer;
15+
import io.opentelemetry.api.trace.TracerBuilder;
16+
import io.opentelemetry.api.trace.TracerProvider;
17+
import io.opentelemetry.context.propagation.ContextPropagators;
18+
import io.opentelemetry.sdk.common.CompletableResultCode;
19+
import io.opentelemetry.sdk.extension.incubator.entities.SdkResourceProvider;
20+
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
21+
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
22+
import io.opentelemetry.sdk.trace.SdkTracerProvider;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.concurrent.TimeUnit;
26+
import java.util.concurrent.atomic.AtomicBoolean;
27+
import java.util.logging.Logger;
28+
import javax.annotation.concurrent.ThreadSafe;
29+
30+
/** The SDK implementation of {@link ExtendedOpenTelemetrySdk}. */
31+
final class ObfuscatedExtendedOpenTelemerySdk implements ExtendedOpenTelemetrySdk {
32+
33+
private static final Logger LOGGER =
34+
Logger.getLogger(ObfuscatedExtendedOpenTelemerySdk.class.getName());
35+
private final AtomicBoolean isShutdown = new AtomicBoolean(false);
36+
private final ObfuscatedTracerProvider tracerProvider;
37+
private final ObfuscatedMeterProvider meterProvider;
38+
private final ObfuscatedLoggerProvider loggerProvider;
39+
private final ObfuscatedResourceProvider resourceProvider;
40+
private final ContextPropagators propagators;
41+
42+
ObfuscatedExtendedOpenTelemerySdk(
43+
SdkResourceProvider resourceProvider,
44+
SdkTracerProvider tracerProvider,
45+
SdkMeterProvider meterProvider,
46+
SdkLoggerProvider loggerProvider,
47+
ContextPropagators propagators) {
48+
this.resourceProvider = new ObfuscatedResourceProvider(resourceProvider);
49+
this.tracerProvider = new ObfuscatedTracerProvider(tracerProvider);
50+
this.meterProvider = new ObfuscatedMeterProvider(meterProvider);
51+
this.loggerProvider = new ObfuscatedLoggerProvider(loggerProvider);
52+
this.propagators = propagators;
53+
}
54+
55+
@Override
56+
public CompletableResultCode shutdown() {
57+
if (!isShutdown.compareAndSet(false, true)) {
58+
LOGGER.info("Multiple shutdown calls");
59+
return CompletableResultCode.ofSuccess();
60+
}
61+
List<CompletableResultCode> results = new ArrayList<>();
62+
results.add(tracerProvider.unobfuscate().shutdown());
63+
results.add(meterProvider.unobfuscate().shutdown());
64+
results.add(loggerProvider.unobfuscate().shutdown());
65+
return CompletableResultCode.ofAll(results);
66+
}
67+
68+
@Override
69+
public void close() {
70+
shutdown().join(10, TimeUnit.SECONDS);
71+
}
72+
73+
@Override
74+
public TracerProvider getTracerProvider() {
75+
return tracerProvider;
76+
}
77+
78+
@Override
79+
public MeterProvider getMeterProvider() {
80+
return meterProvider;
81+
}
82+
83+
@Override
84+
public LoggerProvider getLogsBridge() {
85+
return loggerProvider;
86+
}
87+
88+
@Override
89+
public ResourceProvider getResourceProvider() {
90+
return resourceProvider;
91+
}
92+
93+
@Override
94+
public ContextPropagators getPropagators() {
95+
return propagators;
96+
}
97+
98+
@Override
99+
public String toString() {
100+
return "ExtendedOpenTelemetrySdk{"
101+
+ "resourceProivder="
102+
+ resourceProvider.unobfuscate()
103+
+ ", tracerProvider="
104+
+ tracerProvider.unobfuscate()
105+
+ ", meterProvider="
106+
+ meterProvider.unobfuscate()
107+
+ ", loggerProvider="
108+
+ loggerProvider.unobfuscate()
109+
+ ", propagators="
110+
+ propagators
111+
+ "}";
112+
}
113+
114+
/**
115+
* This class allows the SDK to unobfuscate an obfuscated static global provider.
116+
*
117+
* <p>Static global providers are obfuscated when they are returned from the API to prevent users
118+
* from casting them to their SDK specific implementation. For example, we do not want users to
119+
* use patterns like {@code (SdkTracerProvider) openTelemetry.getTracerProvider()}.
120+
*/
121+
@ThreadSafe
122+
// Visible for testing
123+
static class ObfuscatedTracerProvider implements TracerProvider {
124+
125+
private final SdkTracerProvider delegate;
126+
127+
ObfuscatedTracerProvider(SdkTracerProvider delegate) {
128+
this.delegate = delegate;
129+
}
130+
131+
@Override
132+
public Tracer get(String instrumentationScopeName) {
133+
return delegate.get(instrumentationScopeName);
134+
}
135+
136+
@Override
137+
public Tracer get(String instrumentationScopeName, String instrumentationScopeVersion) {
138+
return delegate.get(instrumentationScopeName, instrumentationScopeVersion);
139+
}
140+
141+
@Override
142+
public TracerBuilder tracerBuilder(String instrumentationScopeName) {
143+
return delegate.tracerBuilder(instrumentationScopeName);
144+
}
145+
146+
public SdkTracerProvider unobfuscate() {
147+
return delegate;
148+
}
149+
}
150+
151+
/**
152+
* This class allows the SDK to unobfuscate an obfuscated static global provider.
153+
*
154+
* <p>Static global providers are obfuscated when they are returned from the API to prevent users
155+
* from casting them to their SDK specific implementation. For example, we do not want users to
156+
* use patterns like {@code (SdkMeterProvider) openTelemetry.getMeterProvider()}.
157+
*/
158+
@ThreadSafe
159+
// Visible for testing
160+
static class ObfuscatedMeterProvider implements MeterProvider {
161+
162+
private final SdkMeterProvider delegate;
163+
164+
ObfuscatedMeterProvider(SdkMeterProvider delegate) {
165+
this.delegate = delegate;
166+
}
167+
168+
@Override
169+
public MeterBuilder meterBuilder(String instrumentationScopeName) {
170+
return delegate.meterBuilder(instrumentationScopeName);
171+
}
172+
173+
public SdkMeterProvider unobfuscate() {
174+
return delegate;
175+
}
176+
}
177+
178+
/**
179+
* This class allows the SDK to unobfuscate an obfuscated static global provider.
180+
*
181+
* <p>Static global providers are obfuscated when they are returned from the API to prevent users
182+
* from casting them to their SDK specific implementation. For example, we do not want users to
183+
* use patterns like {@code (SdkMeterProvider) openTelemetry.getMeterProvider()}.
184+
*/
185+
@ThreadSafe
186+
// Visible for testing
187+
static class ObfuscatedLoggerProvider implements LoggerProvider {
188+
189+
private final SdkLoggerProvider delegate;
190+
191+
ObfuscatedLoggerProvider(SdkLoggerProvider delegate) {
192+
this.delegate = delegate;
193+
}
194+
195+
@Override
196+
public LoggerBuilder loggerBuilder(String instrumentationScopeName) {
197+
return delegate.loggerBuilder(instrumentationScopeName);
198+
}
199+
200+
public SdkLoggerProvider unobfuscate() {
201+
return delegate;
202+
}
203+
}
204+
205+
/**
206+
* This class allows the SDK to unobfuscate an obfuscated static global provider.
207+
*
208+
* <p>Static global providers are obfuscated when they are returned from the API to prevent users
209+
* from casting them to their SDK specific implementation. For example, we do not want users to
210+
* use patterns like {@code (SdkResourceProvider) openTelemetry.getResourceProvider()}.
211+
*/
212+
@ThreadSafe
213+
// Visible for testing
214+
static class ObfuscatedResourceProvider implements ResourceProvider {
215+
216+
private final SdkResourceProvider delegate;
217+
218+
ObfuscatedResourceProvider(SdkResourceProvider delegate) {
219+
this.delegate = delegate;
220+
}
221+
222+
@Override
223+
public Resource getResource() {
224+
return delegate.getResource();
225+
}
226+
227+
public SdkResourceProvider unobfuscate() {
228+
return delegate;
229+
}
230+
}
231+
}

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/entities/SdkResourceProvider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,9 @@ public io.opentelemetry.sdk.resources.Resource getSdkResource() {
2424
public static SdkResourceProviderBuilder builder() {
2525
return new SdkResourceProviderBuilder();
2626
}
27+
28+
@Override
29+
public String toString() {
30+
return "SdkResourceProvider{}";
31+
}
2732
}

0 commit comments

Comments
 (0)