Skip to content

Commit

Permalink
Add an SPI for customizing Config just before it's set (#6010)
Browse files Browse the repository at this point in the history
* Add an SPI for customizing Config just before it's set

* deprecate ConfigPropertySource in favor of ConfigCustomizer

* errorprone
  • Loading branch information
Mateusz Rzeszutek committed May 16, 2022
1 parent 18352ff commit cb7421c
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,12 @@ private <T> T getTypedProperty(String name, ConfigValueParser<T> parser) {
private String getRawProperty(String name, String defaultValue) {
return getAllProperties().getOrDefault(NamingConvention.DOT.normalize(name), defaultValue);
}

/**
* Returns a new {@link ConfigBuilder} instance populated with the properties of this {@link
* Config}.
*/
public ConfigBuilder toBuilder() {
return new ConfigBuilder(getAllProperties());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@
/** A builder of a {@link Config}. */
public final class ConfigBuilder {

private final Map<String, String> allProperties = new HashMap<>();
private final Map<String, String> allProperties;

/** Constructs a new {@link ConfigBuilder}. */
ConfigBuilder() {}
ConfigBuilder() {
allProperties = new HashMap<>();
}

ConfigBuilder(Map<String, String> propertiesToCopy) {
allProperties = new HashMap<>(propertiesToCopy);
}

/** Adds a single property to the config. */
public ConfigBuilder addProperty(String name, @Nullable String value) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.extension.config;

import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.javaagent.extension.Ordered;
import java.util.Collections;
import java.util.Map;

/**
* A service provider that allows to override default OTel javaagent configuration, and customize
* the config just before it is set as the global.
*
* <p>This is a service provider interface that requires implementations to be registered in a
* provider-configuration file stored in the {@code META-INF/services} resource directory.
*/
public interface ConfigCustomizer extends Ordered {

/**
* Returns properties with their default values. Properties returned by implementations of this
* interface will be used after the following methods fail to find a non-empty property value:
* system properties, environment variables, properties configuration file.
*
* <p>Key of the map is the propertyName (same as system property name, e.g. {@code
* otel.traces.exporter}), value is the property value.
*/
default Map<String, String> defaultProperties() {
return Collections.emptyMap();
}

/** Allows to change the javaagent configuration just before it is first used. */
default Config customize(Config config) {
return config;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@
*
* <p>This is a service provider interface that requires implementations to be registered in a
* provider-configuration file stored in the {@code META-INF/services} resource directory.
*
* @deprecated Use {@link ConfigCustomizer} instead.
*/
@Deprecated
public interface ConfigPropertySource extends Ordered {

/**
* Returns all properties whose default values are overridden by this property source. Key of the
* map is the propertyName (same as system property name, e.g. {@code otel.traces.exporter}),
* value is the property value.
*
* @deprecated Use {@link ConfigCustomizer#defaultProperties()} instead.
*/
@Deprecated
Map<String, String> getProperties();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
import static java.util.logging.Level.SEVERE;

import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.javaagent.extension.config.ConfigPropertySource;
import io.opentelemetry.javaagent.extension.config.ConfigCustomizer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

Expand All @@ -27,7 +28,12 @@ public final class ConfigInitializer {
static final String CONFIGURATION_FILE_ENV_VAR = "OTEL_JAVAAGENT_CONFIGURATION_FILE";

public static void initialize() {
Config.internalInitializeConfig(create(loadSpiConfiguration(), loadConfigurationFile()));
List<ConfigCustomizer> customizers = loadOrdered(ConfigCustomizer.class);
Config config = create(loadSpiConfiguration(customizers), loadConfigurationFile());
for (ConfigCustomizer customizer : customizers) {
config = customizer.customize(config);
}
Config.internalInitializeConfig(config);
}

// visible for testing
Expand All @@ -41,11 +47,16 @@ static Config create(Properties spiConfiguration, Properties configurationFile)
}

/** Retrieves all default configuration overloads using SPI and initializes Config. */
private static Properties loadSpiConfiguration() {
@SuppressWarnings("deprecation") // loads the old config SPI
private static Properties loadSpiConfiguration(List<ConfigCustomizer> customizers) {
Properties propertiesFromSpi = new Properties();
for (ConfigPropertySource propertySource : loadOrdered(ConfigPropertySource.class)) {
for (io.opentelemetry.javaagent.extension.config.ConfigPropertySource propertySource :
loadOrdered(io.opentelemetry.javaagent.extension.config.ConfigPropertySource.class)) {
propertiesFromSpi.putAll(propertySource.getProperties());
}
for (ConfigCustomizer customizer : customizers) {
propertiesFromSpi.putAll(customizer.defaultProperties());
}
return propertiesFromSpi;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
package io.opentelemetry.javaagent.testing.exporter;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.config.ConfigPropertySource;
import io.opentelemetry.javaagent.extension.config.ConfigCustomizer;
import java.util.HashMap;
import java.util.Map;

@AutoService(ConfigPropertySource.class)
public class AgentTestingExporterPropertySource implements ConfigPropertySource {
@AutoService(ConfigCustomizer.class)
public class AgentTestingExporterPropertySource implements ConfigCustomizer {

@Override
public Map<String, String> getProperties() {
public Map<String, String> defaultProperties() {
Map<String, String> properties = new HashMap<>();
properties.put("otel.logs.exporter", "none");
properties.put("otel.metrics.exporter", "none");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
package io.opentelemetry.javaagent.testing.http;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.config.ConfigPropertySource;
import io.opentelemetry.javaagent.extension.config.ConfigCustomizer;
import java.util.HashMap;
import java.util.Map;

@AutoService(ConfigPropertySource.class)
public class CapturedHttpHeadersTestConfigSource implements ConfigPropertySource {
@AutoService(ConfigCustomizer.class)
public class CapturedHttpHeadersTestConfigSource implements ConfigCustomizer {

@Override
public Map<String, String> getProperties() {
public Map<String, String> defaultProperties() {
Map<String, String> testConfig = new HashMap<>();
testConfig.put("otel.instrumentation.http.capture-headers.client.request", "X-Test-Request");
testConfig.put("otel.instrumentation.http.capture-headers.client.response", "X-Test-Response");
Expand Down

0 comments on commit cb7421c

Please sign in to comment.