Skip to content

Commit 08c2eec

Browse files
committed
Autoconfigure compileOnly dependency on api incubator
1 parent 20de4ef commit 08c2eec

File tree

15 files changed

+338
-207
lines changed

15 files changed

+338
-207
lines changed

sdk-extensions/autoconfigure/build.gradle.kts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ otelJava.moduleName.set("io.opentelemetry.sdk.autoconfigure")
99
dependencies {
1010
api(project(":sdk:all"))
1111
api(project(":sdk-extensions:autoconfigure-spi"))
12-
// TODO(jack-berg): should be compileOnly
13-
implementation(project(":api:incubator"))
12+
13+
compileOnly(project(":api:incubator"))
1414

1515
annotationProcessor("com.google.auto.value:auto-value")
1616

@@ -47,7 +47,6 @@ testing {
4747
}
4848
register<JvmTestSuite>("testFullConfig") {
4949
dependencies {
50-
implementation(project(":api:incubator"))
5150
implementation(project(":extensions:trace-propagators"))
5251
implementation(project(":exporters:logging"))
5352
implementation(project(":exporters:logging-otlp"))
@@ -80,6 +79,13 @@ testing {
8079
}
8180
}
8281
}
82+
register<JvmTestSuite>("testIncubating") {
83+
dependencies {
84+
implementation(project(":sdk-extensions:incubator"))
85+
implementation(project(":exporters:logging"))
86+
implementation(project(":sdk:testing"))
87+
}
88+
}
8389
}
8490
}
8591

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdk.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.opentelemetry.api.OpenTelemetry;
1111
import io.opentelemetry.api.incubator.config.ConfigProvider;
1212
import io.opentelemetry.sdk.OpenTelemetrySdk;
13+
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
1314
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1415
import io.opentelemetry.sdk.resources.Resource;
1516
import javax.annotation.Nullable;
@@ -48,7 +49,7 @@ static AutoConfiguredOpenTelemetrySdk create(
4849
OpenTelemetrySdk sdk,
4950
Resource resource,
5051
@Nullable ConfigProperties config,
51-
@Nullable ConfigProvider configProvider) {
52+
@Nullable Object configProvider) {
5253
return new AutoValue_AutoConfiguredOpenTelemetrySdk(sdk, resource, config, configProvider);
5354
}
5455

@@ -69,6 +70,9 @@ static AutoConfiguredOpenTelemetrySdk create(
6970
* Returns the {@link ConfigProperties} used for auto-configuration, or {@code null} if
7071
* declarative configuration was used.
7172
*
73+
* <p>This method is experimental so not public. You may reflectively call it using {@link
74+
* AutoConfigureUtil#getConfig(AutoConfiguredOpenTelemetrySdk)}.
75+
*
7276
* @see #getConfigProvider()
7377
*/
7478
@Nullable
@@ -77,10 +81,13 @@ static AutoConfiguredOpenTelemetrySdk create(
7781
/**
7882
* Returns the {@link ConfigProvider}, or {@code null} if declarative configuration was not used.
7983
*
84+
* <p>This method is experimental so not public. You may reflectively call it using {@link
85+
* AutoConfigureUtil#getConfigProvider(AutoConfiguredOpenTelemetrySdk)}.
86+
*
8087
* @see #getConfig()
8188
*/
8289
@Nullable
83-
abstract ConfigProvider getConfigProvider();
90+
abstract Object getConfigProvider();
8491

8592
AutoConfiguredOpenTelemetrySdk() {}
8693
}

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java

Lines changed: 22 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
import static java.util.Objects.requireNonNull;
99

1010
import io.opentelemetry.api.GlobalOpenTelemetry;
11-
import io.opentelemetry.api.incubator.config.ConfigProvider;
12-
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
13-
import io.opentelemetry.api.incubator.config.GlobalConfigProvider;
1411
import io.opentelemetry.context.propagation.ContextPropagators;
1512
import io.opentelemetry.context.propagation.TextMapPropagator;
1613
import io.opentelemetry.sdk.OpenTelemetrySdk;
@@ -38,19 +35,12 @@
3835
import io.opentelemetry.sdk.trace.export.SpanExporter;
3936
import io.opentelemetry.sdk.trace.samplers.Sampler;
4037
import java.io.Closeable;
41-
import java.io.FileInputStream;
42-
import java.io.FileNotFoundException;
4338
import java.io.IOException;
44-
import java.io.InputStream;
45-
import java.lang.reflect.InvocationTargetException;
46-
import java.lang.reflect.Method;
4739
import java.util.ArrayList;
4840
import java.util.Collections;
4941
import java.util.HashMap;
5042
import java.util.List;
5143
import java.util.Map;
52-
import java.util.Objects;
53-
import java.util.Optional;
5444
import java.util.function.BiFunction;
5545
import java.util.function.Function;
5646
import java.util.function.Supplier;
@@ -69,6 +59,18 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
6959

7060
private static final Logger logger =
7161
Logger.getLogger(AutoConfiguredOpenTelemetrySdkBuilder.class.getName());
62+
private static final boolean INCUBATOR_AVAILABLE;
63+
64+
static {
65+
boolean incubatorAvailable = false;
66+
try {
67+
Class.forName("io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration");
68+
incubatorAvailable = true;
69+
} catch (ClassNotFoundException e) {
70+
// Not available
71+
}
72+
INCUBATOR_AVAILABLE = incubatorAvailable;
73+
}
7274

7375
@Nullable private ConfigProperties config;
7476

@@ -436,9 +438,7 @@ public AutoConfiguredOpenTelemetrySdk build() {
436438
if (fromFileConfiguration != null) {
437439
maybeRegisterShutdownHook(fromFileConfiguration.getOpenTelemetrySdk());
438440
maybeSetAsGlobal(
439-
fromFileConfiguration.getOpenTelemetrySdk(),
440-
Optional.ofNullable(fromFileConfiguration.getConfigProvider())
441-
.orElse(ConfigProvider.noop()));
441+
fromFileConfiguration.getOpenTelemetrySdk(), fromFileConfiguration.getConfigProvider());
442442
return fromFileConfiguration;
443443
}
444444

@@ -464,7 +464,7 @@ public AutoConfiguredOpenTelemetrySdk build() {
464464

465465
OpenTelemetrySdk openTelemetrySdk = sdkBuilder.build();
466466
maybeRegisterShutdownHook(openTelemetrySdk);
467-
maybeSetAsGlobal(openTelemetrySdk, ConfigProvider.noop());
467+
maybeSetAsGlobal(openTelemetrySdk, null);
468468
callAutoConfigureListeners(spiHelper, openTelemetrySdk);
469469

470470
return AutoConfiguredOpenTelemetrySdk.create(openTelemetrySdk, resource, config, null);
@@ -555,52 +555,11 @@ private static AutoConfiguredOpenTelemetrySdk maybeConfigureFromFile(
555555
if (configurationFile == null || configurationFile.isEmpty()) {
556556
return null;
557557
}
558-
logger.fine("Autoconfiguring from configuration file: " + configurationFile);
559-
try (FileInputStream fis = new FileInputStream(configurationFile)) {
560-
Class<?> declarativeConfiguration =
561-
Class.forName(
562-
"io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration");
563-
Method parse = declarativeConfiguration.getMethod("parse", InputStream.class);
564-
Object model = parse.invoke(null, fis);
565-
Class<?> openTelemetryConfiguration =
566-
Class.forName(
567-
"io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel");
568-
Method create =
569-
declarativeConfiguration.getMethod(
570-
"create", openTelemetryConfiguration, ComponentLoader.class);
571-
OpenTelemetrySdk sdk = (OpenTelemetrySdk) create.invoke(null, model, componentLoader);
572-
Class<?> sdkConfigProvider =
573-
Class.forName("io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider");
574-
Method createFileConfigProvider =
575-
sdkConfigProvider.getMethod("create", openTelemetryConfiguration);
576-
ConfigProvider configProvider = (ConfigProvider) createFileConfigProvider.invoke(null, model);
577-
// Note: can't access file configuration resource without reflection so setting a dummy
578-
// resource
579-
return AutoConfiguredOpenTelemetrySdk.create(
580-
sdk, Resource.getDefault(), null, configProvider);
581-
} catch (FileNotFoundException e) {
582-
throw new ConfigurationException("Configuration file not found", e);
583-
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
558+
if (!INCUBATOR_AVAILABLE) {
584559
throw new ConfigurationException(
585-
"Error configuring from file. Is opentelemetry-sdk-extension-incubator on the classpath?",
586-
e);
587-
} catch (InvocationTargetException e) {
588-
Throwable cause = e.getCause();
589-
if (cause instanceof DeclarativeConfigException) {
590-
throw toConfigurationException((DeclarativeConfigException) cause);
591-
}
592-
throw new ConfigurationException("Unexpected error configuring from file", e);
593-
} catch (IOException e) {
594-
// IOException (other than FileNotFoundException which is caught above) is only thrown
595-
// above by FileInputStream.close()
596-
throw new ConfigurationException("Error closing file", e);
560+
"Cannot autoconfigure from config file without opentelemetry-sdk-extension-incubator on the classpath");
597561
}
598-
}
599-
600-
private static ConfigurationException toConfigurationException(
601-
DeclarativeConfigException exception) {
602-
String message = Objects.requireNonNull(exception.getMessage());
603-
return new ConfigurationException(message, exception);
562+
return IncubatingUtil.configureFromFile(logger, configurationFile, componentLoader);
604563
}
605564

606565
private void maybeRegisterShutdownHook(OpenTelemetrySdk openTelemetrySdk) {
@@ -610,12 +569,15 @@ private void maybeRegisterShutdownHook(OpenTelemetrySdk openTelemetrySdk) {
610569
Runtime.getRuntime().addShutdownHook(shutdownHook(openTelemetrySdk));
611570
}
612571

613-
private void maybeSetAsGlobal(OpenTelemetrySdk openTelemetrySdk, ConfigProvider configProvider) {
572+
private void maybeSetAsGlobal(
573+
OpenTelemetrySdk openTelemetrySdk, @Nullable Object configProvider) {
614574
if (!setResultAsGlobal) {
615575
return;
616576
}
617577
GlobalOpenTelemetry.set(openTelemetrySdk);
618-
GlobalConfigProvider.set(configProvider);
578+
if (INCUBATOR_AVAILABLE && configProvider != null) {
579+
IncubatingUtil.setGlobalConfigProvider(configProvider);
580+
}
619581
logger.log(
620582
Level.FINE, "Global OpenTelemetry set to {0} by autoconfiguration", openTelemetrySdk);
621583
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.sdk.autoconfigure;
7+
8+
import io.opentelemetry.api.incubator.config.ConfigProvider;
9+
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
10+
import io.opentelemetry.api.incubator.config.GlobalConfigProvider;
11+
import io.opentelemetry.sdk.OpenTelemetrySdk;
12+
import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader;
13+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
14+
import io.opentelemetry.sdk.resources.Resource;
15+
import java.io.FileInputStream;
16+
import java.io.FileNotFoundException;
17+
import java.io.IOException;
18+
import java.io.InputStream;
19+
import java.lang.reflect.InvocationTargetException;
20+
import java.lang.reflect.Method;
21+
import java.util.Objects;
22+
import java.util.logging.Logger;
23+
24+
/**
25+
* Utilities for interacting with incubating components ({@code
26+
* io.opentelemetry:opentelemetry-api-incubator} and {@code
27+
* io.opentelemetry:opentelemetry-sdk-extension-incubator}), which are not guaranteed to be present
28+
* on the classpath. For all methods, callers MUST first separately reflectively confirm that the
29+
* incubator is available on the classpath.
30+
*/
31+
final class IncubatingUtil {
32+
33+
private IncubatingUtil() {}
34+
35+
static AutoConfiguredOpenTelemetrySdk configureFromFile(
36+
Logger logger, String configurationFile, ComponentLoader componentLoader) {
37+
logger.fine("Autoconfiguring from configuration file: " + configurationFile);
38+
try (FileInputStream fis = new FileInputStream(configurationFile)) {
39+
Class<?> declarativeConfiguration =
40+
Class.forName(
41+
"io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration");
42+
Method parse = declarativeConfiguration.getMethod("parse", InputStream.class);
43+
Object model = parse.invoke(null, fis);
44+
Class<?> openTelemetryConfiguration =
45+
Class.forName(
46+
"io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel");
47+
Method create =
48+
declarativeConfiguration.getMethod(
49+
"create", openTelemetryConfiguration, ComponentLoader.class);
50+
OpenTelemetrySdk sdk = (OpenTelemetrySdk) create.invoke(null, model, componentLoader);
51+
Class<?> sdkConfigProvider =
52+
Class.forName("io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider");
53+
Method createFileConfigProvider =
54+
sdkConfigProvider.getMethod("create", openTelemetryConfiguration);
55+
ConfigProvider configProvider = (ConfigProvider) createFileConfigProvider.invoke(null, model);
56+
// Note: can't access file configuration resource without reflection so setting a dummy
57+
// resource
58+
return AutoConfiguredOpenTelemetrySdk.create(
59+
sdk, Resource.getDefault(), null, configProvider);
60+
} catch (FileNotFoundException e) {
61+
throw new ConfigurationException("Configuration file not found", e);
62+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
63+
throw new ConfigurationException(
64+
"Error configuring from file. Is opentelemetry-sdk-extension-incubator on the classpath?",
65+
e);
66+
} catch (InvocationTargetException e) {
67+
Throwable cause = e.getCause();
68+
if (cause instanceof DeclarativeConfigException) {
69+
throw toConfigurationException((DeclarativeConfigException) cause);
70+
}
71+
throw new ConfigurationException("Unexpected error configuring from file", e);
72+
} catch (IOException e) {
73+
// IOException (other than FileNotFoundException which is caught above) is only thrown
74+
// above by FileInputStream.close()
75+
throw new ConfigurationException("Error closing file", e);
76+
}
77+
}
78+
79+
private static ConfigurationException toConfigurationException(
80+
DeclarativeConfigException exception) {
81+
String message = Objects.requireNonNull(exception.getMessage());
82+
return new ConfigurationException(message, exception);
83+
}
84+
85+
static void setGlobalConfigProvider(Object configProvider) {
86+
GlobalConfigProvider.set((ConfigProvider) configProvider);
87+
}
88+
}

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/SpiHelper.java

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55

66
package io.opentelemetry.sdk.autoconfigure.internal;
77

8-
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
9-
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
108
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
119
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
1210
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
13-
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
1411
import java.util.ArrayList;
1512
import java.util.Collections;
1613
import java.util.Comparator;
@@ -23,7 +20,6 @@
2320
import java.util.function.BiFunction;
2421
import java.util.function.Function;
2522
import java.util.function.Supplier;
26-
import java.util.stream.Collectors;
2723

2824
/**
2925
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
@@ -90,53 +86,6 @@ public <T, S> NamedSpiManager<T> loadConfigurable(
9086
return NamedSpiManager.create(nameToProvider);
9187
}
9288

93-
/**
94-
* Find a registered {@link ComponentProvider} with {@link ComponentProvider#getType()} matching
95-
* {@code type}, {@link ComponentProvider#getName()} matching {@code name}, and call {@link
96-
* ComponentProvider#create(DeclarativeConfigProperties)} with the given {@code config}.
97-
*
98-
* @throws DeclarativeConfigException if no matching providers are found, or if multiple are found
99-
* (i.e. conflict), or if {@link ComponentProvider#create(DeclarativeConfigProperties)} throws
100-
*/
101-
@SuppressWarnings({"unchecked", "rawtypes"})
102-
public <T> T loadComponent(Class<T> type, String name, DeclarativeConfigProperties config) {
103-
// TODO(jack-berg): cache loaded component providers
104-
List<ComponentProvider> componentProviders = load(ComponentProvider.class);
105-
List<ComponentProvider<?>> matchedProviders =
106-
componentProviders.stream()
107-
.map(
108-
(Function<ComponentProvider, ComponentProvider<?>>)
109-
componentProvider -> componentProvider)
110-
.filter(
111-
componentProvider ->
112-
componentProvider.getType() == type && name.equals(componentProvider.getName()))
113-
.collect(Collectors.toList());
114-
if (matchedProviders.isEmpty()) {
115-
throw new DeclarativeConfigException(
116-
"No component provider detected for " + type.getName() + " with name \"" + name + "\".");
117-
}
118-
if (matchedProviders.size() > 1) {
119-
throw new DeclarativeConfigException(
120-
"Component provider conflict. Multiple providers detected for "
121-
+ type.getName()
122-
+ " with name \""
123-
+ name
124-
+ "\": "
125-
+ componentProviders.stream()
126-
.map(provider -> provider.getClass().getName())
127-
.collect(Collectors.joining(",", "[", "]")));
128-
}
129-
// Exactly one matching component provider
130-
ComponentProvider<T> provider = (ComponentProvider<T>) matchedProviders.get(0);
131-
132-
try {
133-
return provider.create(config);
134-
} catch (Throwable throwable) {
135-
throw new DeclarativeConfigException(
136-
"Error configuring " + type.getName() + " with name \"" + name + "\"", throwable);
137-
}
138-
}
139-
14089
/**
14190
* Load implementations of an ordered SPI (i.e. implements {@link Ordered}).
14291
*

0 commit comments

Comments
 (0)