Use autoconfigured ClassLoader to load declarative config (#6725)
This commit is contained in:
parent
39b24118a1
commit
325822ce85
|
@ -107,8 +107,8 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
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;
|
||||
|
||||
|
@ -401,14 +401,14 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
public AutoConfiguredOpenTelemetrySdkBuilder setServiceClassLoader(
|
||||
ClassLoader serviceClassLoader) {
|
||||
requireNonNull(serviceClassLoader, "serviceClassLoader");
|
||||
this.spiHelper = SpiHelper.create(serviceClassLoader);
|
||||
this.componentLoader = SpiHelper.serviceComponentLoader(serviceClassLoader);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -417,6 +417,7 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
* the settings of this {@link AutoConfiguredOpenTelemetrySdkBuilder}.
|
||||
*/
|
||||
public AutoConfiguredOpenTelemetrySdk build() {
|
||||
SpiHelper spiHelper = SpiHelper.create(componentLoader);
|
||||
if (!customized) {
|
||||
customized = true;
|
||||
mergeSdkTracerProviderConfigurer();
|
||||
|
@ -428,7 +429,8 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
|
||||
ConfigProperties config = getConfig();
|
||||
|
||||
AutoConfiguredOpenTelemetrySdk fromFileConfiguration = maybeConfigureFromFile(config);
|
||||
AutoConfiguredOpenTelemetrySdk fromFileConfiguration =
|
||||
maybeConfigureFromFile(config, componentLoader);
|
||||
if (fromFileConfiguration != null) {
|
||||
maybeRegisterShutdownHook(fromFileConfiguration.getOpenTelemetrySdk());
|
||||
maybeSetAsGlobal(fromFileConfiguration.getOpenTelemetrySdk());
|
||||
|
@ -527,7 +529,8 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
}
|
||||
|
||||
@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(
|
||||
|
@ -552,8 +555,10 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
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 =
|
||||
|
@ -608,7 +613,7 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
@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) -> {
|
||||
|
|
|
@ -41,7 +41,7 @@ public final class SpiHelper {
|
|||
|
||||
/** 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}. */
|
||||
|
@ -49,6 +49,16 @@ public final class SpiHelper {
|
|||
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}.
|
||||
|
|
|
@ -49,7 +49,8 @@ final class FileConfigUtil {
|
|||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.fasterxml.jackson.annotation.Nulls;
|
|||
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;
|
||||
|
@ -49,6 +50,8 @@ public final class FileConfiguration {
|
|||
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;
|
||||
|
||||
|
@ -86,9 +89,24 @@ public final class FileConfiguration {
|
|||
* @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}
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
@ -130,7 +148,7 @@ public final class FileConfiguration {
|
|||
*/
|
||||
public static StructuredConfigProperties toConfigProperties(
|
||||
OpenTelemetryConfigurationModel model) {
|
||||
return toConfigProperties((Object) model);
|
||||
return toConfigProperties(model, DEFAULT_COMPONENT_LOADER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,13 +159,14 @@ public final class FileConfiguration {
|
|||
*/
|
||||
public static StructuredConfigProperties toConfigProperties(InputStream configuration) {
|
||||
Object yamlObj = loadYaml(configuration, System.getenv());
|
||||
return toConfigProperties(yamlObj);
|
||||
return toConfigProperties(yamlObj, DEFAULT_COMPONENT_LOADER);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,21 +181,27 @@ public final class FileConfiguration {
|
|||
// 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) {
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -8,6 +8,7 @@ package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
|||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,7 +61,8 @@ final class YamlStructuredConfigProperties implements StructuredConfigProperties
|
|||
* @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<>();
|
||||
|
@ -75,13 +80,15 @@ final class YamlStructuredConfigProperties implements StructuredConfigProperties
|
|||
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;
|
||||
}
|
||||
|
@ -91,7 +98,8 @@ final class YamlStructuredConfigProperties implements StructuredConfigProperties
|
|||
+ "\" 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) {
|
||||
|
@ -292,4 +300,9 @@ final class YamlStructuredConfigProperties implements StructuredConfigProperties
|
|||
mapEntries.forEach((key, value) -> result.put(key, value.toMap()));
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
/** Return the {@link ComponentLoader}. */
|
||||
public ComponentLoader getComponentLoader() {
|
||||
return componentLoader;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue