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

Use autoconfigured ClassLoader to load declarative config #6725

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@
private Function<ConfigProperties, ConfigProperties> configPropertiesCustomizer =
Function.identity();

private SpiHelper spiHelper =
SpiHelper.create(AutoConfiguredOpenTelemetrySdk.class.getClassLoader());
private ComponentLoader componentLoader =
SpiHelper.serviceComponentLoader(AutoConfiguredOpenTelemetrySdk.class.getClassLoader());

private boolean registerShutdownHook = true;

Expand Down Expand Up @@ -401,14 +401,14 @@
public AutoConfiguredOpenTelemetrySdkBuilder setServiceClassLoader(
ClassLoader serviceClassLoader) {
requireNonNull(serviceClassLoader, "serviceClassLoader");
this.spiHelper = SpiHelper.create(serviceClassLoader);
this.componentLoader = SpiHelper.serviceComponentLoader(serviceClassLoader);

Check warning on line 404 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L404 was not covered by tests
return this;
}

/** Sets the {@link ComponentLoader} to be used to load SPI implementations. */
AutoConfiguredOpenTelemetrySdkBuilder setComponentLoader(ComponentLoader componentLoader) {
requireNonNull(componentLoader, "componentLoader");
this.spiHelper = SpiHelper.create(componentLoader);
this.componentLoader = componentLoader;
return this;
}

Expand All @@ -417,6 +417,7 @@
* the settings of this {@link AutoConfiguredOpenTelemetrySdkBuilder}.
*/
public AutoConfiguredOpenTelemetrySdk build() {
SpiHelper spiHelper = SpiHelper.create(componentLoader);
if (!customized) {
customized = true;
mergeSdkTracerProviderConfigurer();
Expand All @@ -428,7 +429,8 @@

ConfigProperties config = getConfig();

AutoConfiguredOpenTelemetrySdk fromFileConfiguration = maybeConfigureFromFile(config);
AutoConfiguredOpenTelemetrySdk fromFileConfiguration =
maybeConfigureFromFile(config, componentLoader);
if (fromFileConfiguration != null) {
maybeRegisterShutdownHook(fromFileConfiguration.getOpenTelemetrySdk());
maybeSetAsGlobal(fromFileConfiguration.getOpenTelemetrySdk());
Expand Down Expand Up @@ -527,7 +529,8 @@
}

@Nullable
private static AutoConfiguredOpenTelemetrySdk maybeConfigureFromFile(ConfigProperties config) {
private static AutoConfiguredOpenTelemetrySdk maybeConfigureFromFile(
ConfigProperties config, ComponentLoader componentLoader) {
String otelConfigFile = config.getString("otel.config.file");
if (otelConfigFile != null && !otelConfigFile.isEmpty()) {
logger.warning(
Expand All @@ -552,8 +555,10 @@
Class<?> openTelemetryConfiguration =
Class.forName(
"io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel");
Method create = configurationFactory.getMethod("create", openTelemetryConfiguration);
OpenTelemetrySdk sdk = (OpenTelemetrySdk) create.invoke(null, model);
Method create =
configurationFactory.getMethod(
"create", openTelemetryConfiguration, ComponentLoader.class);
OpenTelemetrySdk sdk = (OpenTelemetrySdk) create.invoke(null, model, componentLoader);
Method toConfigProperties =
configurationFactory.getMethod("toConfigProperties", openTelemetryConfiguration);
StructuredConfigProperties structuredConfigProperties =
Expand Down Expand Up @@ -608,7 +613,7 @@
@SuppressWarnings("deprecation") // Support deprecated SdkTracerProviderConfigurer
private void mergeSdkTracerProviderConfigurer() {
for (io.opentelemetry.sdk.autoconfigure.spi.traces.SdkTracerProviderConfigurer configurer :
spiHelper.load(
componentLoader.load(
io.opentelemetry.sdk.autoconfigure.spi.traces.SdkTracerProviderConfigurer.class)) {
addTracerProviderCustomizer(
(builder, config) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,24 @@ private SpiHelper(ComponentLoader componentLoader) {

/** Create a {@link SpiHelper} which loads SPIs using the {@code classLoader}. */
public static SpiHelper create(ClassLoader classLoader) {
return new SpiHelper(new ServiceLoaderComponentLoader(classLoader));
return new SpiHelper(serviceComponentLoader(classLoader));
}

/** Create a {@link SpiHelper} which loads SPIs using the {@code componentLoader}. */
public static SpiHelper create(ComponentLoader componentLoader) {
return new SpiHelper(componentLoader);
}

/** Create a {@link ComponentLoader} which loads using the {@code classLoader}. */
public static ComponentLoader serviceComponentLoader(ClassLoader classLoader) {
return new ServiceLoaderComponentLoader(classLoader);
}

/** Return the backing underlying {@link ComponentLoader}. */
public ComponentLoader getComponentLoader() {
return componentLoader;
}

/**
* Load implementations of an SPI which are configurable (i.e. they accept {@link
* ConfigProperties}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ static <T> T requireNonNull(@Nullable T object, String description) {
*/
static <T> T loadComponent(SpiHelper spiHelper, Class<T> type, String name, Object model) {
// Map model to generic structured config properties
StructuredConfigProperties config = FileConfiguration.toConfigProperties(model);
StructuredConfigProperties config =
FileConfiguration.toConfigProperties(model, spiHelper.getComponentLoader());
return spiHelper.loadComponent(type, name, config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
Expand Down Expand Up @@ -49,6 +50,8 @@
private static final Logger logger = Logger.getLogger(FileConfiguration.class.getName());
private static final Pattern ENV_VARIABLE_REFERENCE =
Pattern.compile("\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)}");
private static final ComponentLoader DEFAULT_COMPONENT_LOADER =
SpiHelper.serviceComponentLoader(FileConfiguration.class.getClassLoader());

private static final ObjectMapper MAPPER;

Expand Down Expand Up @@ -86,9 +89,24 @@
* @throws ConfigurationException if unable to interpret
*/
public static OpenTelemetrySdk create(OpenTelemetryConfigurationModel configurationModel) {
return create(configurationModel, DEFAULT_COMPONENT_LOADER);
}

/**
* Interpret the {@code configurationModel} to create {@link OpenTelemetrySdk} instance
* corresponding to the configuration.
*
* @param configurationModel the configuration model
* @param componentLoader the component loader used to load {@link ComponentProvider}
* implementations
* @return the {@link OpenTelemetrySdk}
jack-berg marked this conversation as resolved.
Show resolved Hide resolved
* @throws ConfigurationException if unable to interpret
*/
public static OpenTelemetrySdk create(
OpenTelemetryConfigurationModel configurationModel, ComponentLoader componentLoader) {
return createAndMaybeCleanup(
OpenTelemetryConfigurationFactory.getInstance(),
SpiHelper.create(FileConfiguration.class.getClassLoader()),
SpiHelper.create(componentLoader),
configurationModel);
}

Expand Down Expand Up @@ -130,7 +148,7 @@
*/
public static StructuredConfigProperties toConfigProperties(
OpenTelemetryConfigurationModel model) {
return toConfigProperties((Object) model);
return toConfigProperties(model, DEFAULT_COMPONENT_LOADER);
}

/**
Expand All @@ -141,13 +159,14 @@
*/
public static StructuredConfigProperties toConfigProperties(InputStream configuration) {
Object yamlObj = loadYaml(configuration, System.getenv());
return toConfigProperties(yamlObj);
return toConfigProperties(yamlObj, DEFAULT_COMPONENT_LOADER);

Check warning on line 162 in sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java#L162

Added line #L162 was not covered by tests
}

static StructuredConfigProperties toConfigProperties(Object model) {
static StructuredConfigProperties toConfigProperties(
Object model, ComponentLoader componentLoader) {
Map<String, Object> configurationMap =
MAPPER.convertValue(model, new TypeReference<Map<String, Object>>() {});
return YamlStructuredConfigProperties.create(configurationMap);
return YamlStructuredConfigProperties.create(configurationMap, componentLoader);
}

/**
Expand All @@ -162,21 +181,27 @@
// ComponentProvider
public static io.opentelemetry.sdk.trace.samplers.Sampler createSampler(
StructuredConfigProperties genericSamplerModel) {
SamplerModel samplerModel = convertToModel(genericSamplerModel, SamplerModel.class);
YamlStructuredConfigProperties yamlStructuredConfigProperties =
requireYamlStructuredConfigProperties(genericSamplerModel);
SamplerModel samplerModel = convertToModel(yamlStructuredConfigProperties, SamplerModel.class);
return createAndMaybeCleanup(
SamplerFactory.getInstance(),
SpiHelper.create(FileConfiguration.class.getClassLoader()),
SpiHelper.create(yamlStructuredConfigProperties.getComponentLoader()),
samplerModel);
}

static <T> T convertToModel(
StructuredConfigProperties structuredConfigProperties, Class<T> modelType) {
private static YamlStructuredConfigProperties requireYamlStructuredConfigProperties(
StructuredConfigProperties structuredConfigProperties) {
if (!(structuredConfigProperties instanceof YamlStructuredConfigProperties)) {
throw new ConfigurationException(
"Only YamlStructuredConfigProperties can be converted to model");
}
return MAPPER.convertValue(
((YamlStructuredConfigProperties) structuredConfigProperties).toMap(), modelType);
return (YamlStructuredConfigProperties) structuredConfigProperties;
}

static <T> T convertToModel(
YamlStructuredConfigProperties structuredConfigProperties, Class<T> modelType) {
return MAPPER.convertValue(structuredConfigProperties.toMap(), modelType);
}

static <M, R> R createAndMaybeCleanup(Factory<M, R> factory, SpiHelper spiHelper, M model) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ final class ResourceFactory
Resource> {

private static final StructuredConfigProperties EMPTY_CONFIG =
FileConfiguration.toConfigProperties(Collections.emptyMap());
FileConfiguration.toConfigProperties(
Collections.emptyMap(),
SpiHelper.serviceComponentLoader(ResourceFactory.class.getClassLoader()));
private static final ResourceFactory INSTANCE = new ResourceFactory();

private ResourceFactory() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
Expand Down Expand Up @@ -37,14 +38,17 @@ final class YamlStructuredConfigProperties implements StructuredConfigProperties

private final Map<String, List<YamlStructuredConfigProperties>> listEntries;
private final Map<String, YamlStructuredConfigProperties> mapEntries;
private final ComponentLoader componentLoader;

private YamlStructuredConfigProperties(
Map<String, Object> simpleEntries,
Map<String, List<YamlStructuredConfigProperties>> listEntries,
Map<String, YamlStructuredConfigProperties> mapEntries) {
Map<String, YamlStructuredConfigProperties> mapEntries,
ComponentLoader componentLoader) {
this.simpleEntries = simpleEntries;
this.listEntries = listEntries;
this.mapEntries = mapEntries;
this.componentLoader = componentLoader;
}

/**
Expand All @@ -57,7 +61,8 @@ private YamlStructuredConfigProperties(
* @see FileConfiguration#toConfigProperties(OpenTelemetryConfigurationModel)
*/
@SuppressWarnings("unchecked")
static YamlStructuredConfigProperties create(Map<String, Object> properties) {
static YamlStructuredConfigProperties create(
Map<String, Object> properties, ComponentLoader componentLoader) {
Map<String, Object> simpleEntries = new HashMap<>();
Map<String, List<YamlStructuredConfigProperties>> listEntries = new HashMap<>();
Map<String, YamlStructuredConfigProperties> mapEntries = new HashMap<>();
Expand All @@ -75,13 +80,15 @@ static YamlStructuredConfigProperties create(Map<String, Object> properties) {
if (isListOfMaps(value)) {
List<YamlStructuredConfigProperties> list =
((List<Map<String, Object>>) value)
.stream().map(YamlStructuredConfigProperties::create).collect(toList());
.stream()
.map(map -> YamlStructuredConfigProperties.create(map, componentLoader))
.collect(toList());
listEntries.put(key, list);
continue;
}
if (isMap(value)) {
YamlStructuredConfigProperties configProperties =
YamlStructuredConfigProperties.create((Map<String, Object>) value);
YamlStructuredConfigProperties.create((Map<String, Object>) value, componentLoader);
mapEntries.put(key, configProperties);
continue;
}
Expand All @@ -91,7 +98,8 @@ static YamlStructuredConfigProperties create(Map<String, Object> properties) {
+ "\" has unrecognized object type "
+ value.getClass().getName());
}
return new YamlStructuredConfigProperties(simpleEntries, listEntries, mapEntries);
return new YamlStructuredConfigProperties(
simpleEntries, listEntries, mapEntries, componentLoader);
}

private static boolean isPrimitiveList(Object object) {
Expand Down Expand Up @@ -292,4 +300,9 @@ public Map<String, Object> toMap() {
mapEntries.forEach((key, value) -> result.put(key, value.toMap()));
return Collections.unmodifiableMap(result);
}

/** Return the {@link ComponentLoader}. */
public ComponentLoader getComponentLoader() {
return componentLoader;
}
}
Loading