Support declarative configuration (#12265)
This commit is contained in:
parent
d8eddfc726
commit
780cdf4a93
|
|
@ -15,7 +15,6 @@ import io.opentelemetry.instrumentation.jmx.engine.MetricConfiguration;
|
||||||
import io.opentelemetry.instrumentation.jmx.yaml.RuleParser;
|
import io.opentelemetry.instrumentation.jmx.yaml.RuleParser;
|
||||||
import io.opentelemetry.javaagent.extension.AgentListener;
|
import io.opentelemetry.javaagent.extension.AgentListener;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
@ -29,7 +28,7 @@ public class JmxMetricInsightInstaller implements AgentListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
||||||
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);
|
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredSdk);
|
||||||
|
|
||||||
if (config.getBoolean("otel.jmx.enabled", true)) {
|
if (config.getBoolean("otel.jmx.enabled", true)) {
|
||||||
JmxMetricInsight service =
|
JmxMetricInsight service =
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ package io.opentelemetry.javaagent.instrumentation.oshi;
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import io.opentelemetry.javaagent.extension.AgentListener;
|
import io.opentelemetry.javaagent.extension.AgentListener;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
|
@ -21,7 +20,7 @@ public class OshiMetricsInstaller implements AgentListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
||||||
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);
|
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredSdk);
|
||||||
|
|
||||||
boolean defaultEnabled = config.getBoolean("otel.instrumentation.common.default-enabled", true);
|
boolean defaultEnabled = config.getBoolean("otel.instrumentation.common.default-enabled", true);
|
||||||
if (!config.getBoolean("otel.instrumentation.oshi.enabled", defaultEnabled)) {
|
if (!config.getBoolean("otel.instrumentation.oshi.enabled", defaultEnabled)) {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetrics;
|
||||||
import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetricsBuilder;
|
import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetricsBuilder;
|
||||||
import io.opentelemetry.javaagent.extension.AgentListener;
|
import io.opentelemetry.javaagent.extension.AgentListener;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
|
||||||
/** An {@link AgentListener} that enables runtime metrics during agent startup. */
|
/** An {@link AgentListener} that enables runtime metrics during agent startup. */
|
||||||
|
|
@ -21,7 +20,7 @@ public class Java17RuntimeMetricsInstaller implements AgentListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
||||||
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);
|
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredSdk);
|
||||||
|
|
||||||
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
|
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
|
||||||
RuntimeMetricsBuilder builder = null;
|
RuntimeMetricsBuilder builder = null;
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ package io.opentelemetry.instrumentation.javaagent.runtimemetrics.java8;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder;
|
import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder;
|
||||||
|
import io.opentelemetry.javaagent.extension.AgentListener;
|
||||||
import io.opentelemetry.javaagent.tooling.BeforeAgentListener;
|
import io.opentelemetry.javaagent.tooling.BeforeAgentListener;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
|
|
||||||
|
|
@ -19,7 +19,8 @@ public class JarAnalyzerInstaller implements BeforeAgentListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
|
public void beforeAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
|
||||||
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk);
|
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredOpenTelemetrySdk);
|
||||||
|
|
||||||
boolean enabled =
|
boolean enabled =
|
||||||
config.getBoolean("otel.instrumentation.runtime-telemetry.package-emitter.enabled", false);
|
config.getBoolean("otel.instrumentation.runtime-telemetry.package-emitter.enabled", false);
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.Experiment
|
||||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
||||||
import io.opentelemetry.javaagent.extension.AgentListener;
|
import io.opentelemetry.javaagent.extension.AgentListener;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -30,7 +29,7 @@ public class Java8RuntimeMetricsInstaller implements AgentListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
||||||
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);
|
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredSdk);
|
||||||
|
|
||||||
boolean defaultEnabled = config.getBoolean("otel.instrumentation.common.default-enabled", true);
|
boolean defaultEnabled = config.getBoolean("otel.instrumentation.common.default-enabled", true);
|
||||||
if (!config.getBoolean("otel.instrumentation.runtime-telemetry.enabled", defaultEnabled)
|
if (!config.getBoolean("otel.instrumentation.runtime-telemetry.enabled", defaultEnabled)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ dependencies {
|
||||||
// autoconfigure is unstable, do not expose as api
|
// autoconfigure is unstable, do not expose as api
|
||||||
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
|
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
|
||||||
|
|
||||||
|
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator")
|
||||||
|
|
||||||
// Used by byte-buddy but not brought in as a transitive dependency.
|
// Used by byte-buddy but not brought in as a transitive dependency.
|
||||||
compileOnly("com.google.code.findbugs:annotations")
|
compileOnly("com.google.code.findbugs:annotations")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@
|
||||||
package io.opentelemetry.javaagent.extension;
|
package io.opentelemetry.javaagent.extension;
|
||||||
|
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
|
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||||
|
|
||||||
|
|
@ -25,4 +28,22 @@ public interface AgentListener extends Ordered {
|
||||||
* on an {@link Instrumentation}.
|
* on an {@link Instrumentation}.
|
||||||
*/
|
*/
|
||||||
void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk);
|
void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk);
|
||||||
|
|
||||||
|
/** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */
|
||||||
|
static ConfigProperties resolveConfigProperties(
|
||||||
|
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
|
||||||
|
ConfigProperties sdkConfigProperties =
|
||||||
|
AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk);
|
||||||
|
if (sdkConfigProperties != null) {
|
||||||
|
return sdkConfigProperties;
|
||||||
|
}
|
||||||
|
StructuredConfigProperties structuredConfigProperties =
|
||||||
|
AutoConfigureUtil.getStructuredConfig(autoConfiguredOpenTelemetrySdk);
|
||||||
|
if (structuredConfigProperties != null) {
|
||||||
|
return new StructuredConfigPropertiesBridge(structuredConfigProperties);
|
||||||
|
}
|
||||||
|
// Should never happen
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or StructuredConfigProperties. This is likely a programming error in opentelemetry-java");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.extension;
|
||||||
|
|
||||||
|
import static io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties.empty;
|
||||||
|
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ConfigProperties} which resolves properties based on {@link StructuredConfigProperties}.
|
||||||
|
*
|
||||||
|
* <p>Only properties starting with "otel.instrumentation." are resolved. Others return null (or
|
||||||
|
* default value if provided).
|
||||||
|
*
|
||||||
|
* <p>To resolve:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>"otel.instrumentation" refers to the ".instrumentation.java" node
|
||||||
|
* <li>The portion of the property after "otel.instrumentation." is split into segments based on
|
||||||
|
* ".".
|
||||||
|
* <li>For each N-1 segment, we walk down the tree to find the relevant leaf {@link
|
||||||
|
* StructuredConfigProperties}.
|
||||||
|
* <li>We extract the property from the resolved {@link StructuredConfigProperties} using the last
|
||||||
|
* segment as the property key.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>For example, given the following YAML, asking for {@code
|
||||||
|
* ConfigProperties#getString("otel.instrumentation.common.string_key")} yields "value":
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* instrumentation:
|
||||||
|
* java:
|
||||||
|
* common:
|
||||||
|
* string_key: value
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
final class StructuredConfigPropertiesBridge implements ConfigProperties {
|
||||||
|
|
||||||
|
private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation.";
|
||||||
|
|
||||||
|
// The node at .instrumentation.java
|
||||||
|
private final StructuredConfigProperties instrumentationJavaNode;
|
||||||
|
|
||||||
|
StructuredConfigPropertiesBridge(StructuredConfigProperties rootStructuredConfigProperties) {
|
||||||
|
instrumentationJavaNode =
|
||||||
|
rootStructuredConfigProperties
|
||||||
|
.getStructured("instrumentation", empty())
|
||||||
|
.getStructured("java", empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getString(String propertyName) {
|
||||||
|
return getPropertyValue(propertyName, StructuredConfigProperties::getString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Boolean getBoolean(String propertyName) {
|
||||||
|
return getPropertyValue(propertyName, StructuredConfigProperties::getBoolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Integer getInt(String propertyName) {
|
||||||
|
return getPropertyValue(propertyName, StructuredConfigProperties::getInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Long getLong(String propertyName) {
|
||||||
|
return getPropertyValue(propertyName, StructuredConfigProperties::getLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Double getDouble(String propertyName) {
|
||||||
|
return getPropertyValue(propertyName, StructuredConfigProperties::getDouble);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Duration getDuration(String propertyName) {
|
||||||
|
Long millis = getPropertyValue(propertyName, StructuredConfigProperties::getLong);
|
||||||
|
if (millis == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Duration.ofMillis(millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getList(String propertyName) {
|
||||||
|
List<String> propertyValue =
|
||||||
|
getPropertyValue(
|
||||||
|
propertyName,
|
||||||
|
(properties, lastPart) -> properties.getScalarList(lastPart, String.class));
|
||||||
|
return propertyValue == null ? Collections.emptyList() : propertyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMap(String propertyName) {
|
||||||
|
StructuredConfigProperties propertyValue =
|
||||||
|
getPropertyValue(propertyName, StructuredConfigProperties::getStructured);
|
||||||
|
if (propertyValue == null) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
Map<String, String> result = new HashMap<>();
|
||||||
|
propertyValue
|
||||||
|
.getPropertyKeys()
|
||||||
|
.forEach(
|
||||||
|
key -> {
|
||||||
|
String value = propertyValue.getString(key);
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result.put(key, value);
|
||||||
|
});
|
||||||
|
return Collections.unmodifiableMap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private <T> T getPropertyValue(
|
||||||
|
String property, BiFunction<StructuredConfigProperties, String, T> extractor) {
|
||||||
|
if (!property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String suffix = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
|
||||||
|
// Split the remainder of the property on ".", and walk to the N-1 entry
|
||||||
|
String[] segments = suffix.split("\\.");
|
||||||
|
if (segments.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StructuredConfigProperties target = instrumentationJavaNode;
|
||||||
|
if (segments.length > 1) {
|
||||||
|
for (int i = 0; i < segments.length - 1; i++) {
|
||||||
|
target = target.getStructured(segments[i], empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String lastPart = segments[segments.length - 1];
|
||||||
|
return extractor.apply(target, lastPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.extension;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.FileConfiguration;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class StructuredConfigPropertiesBridgeTest {
|
||||||
|
|
||||||
|
private static final String YAML =
|
||||||
|
"file_format: 0.3\n"
|
||||||
|
+ "instrumentation:\n"
|
||||||
|
+ " java:\n"
|
||||||
|
+ " common:\n"
|
||||||
|
+ " default-enabled: true\n"
|
||||||
|
+ " runtime-telemetry:\n"
|
||||||
|
+ " enabled: false\n"
|
||||||
|
+ " example-instrumentation:\n"
|
||||||
|
+ " string_key: value\n"
|
||||||
|
+ " bool_key: true\n"
|
||||||
|
+ " int_key: 1\n"
|
||||||
|
+ " double_key: 1.1\n"
|
||||||
|
+ " list_key:\n"
|
||||||
|
+ " - value1\n"
|
||||||
|
+ " - value2\n"
|
||||||
|
+ " - true\n"
|
||||||
|
+ " map_key:\n"
|
||||||
|
+ " string_key1: value1\n"
|
||||||
|
+ " string_key2: value2\n"
|
||||||
|
+ " bool_key: true\n";
|
||||||
|
|
||||||
|
private final StructuredConfigProperties structuredConfigProperties =
|
||||||
|
FileConfiguration.toConfigProperties(
|
||||||
|
new ByteArrayInputStream(YAML.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
private final ConfigProperties bridge =
|
||||||
|
new StructuredConfigPropertiesBridge(structuredConfigProperties);
|
||||||
|
private final ConfigProperties emptyBridge =
|
||||||
|
new StructuredConfigPropertiesBridge(
|
||||||
|
FileConfiguration.toConfigProperties(
|
||||||
|
new ByteArrayInputStream("file_format: 0.3\n".getBytes(StandardCharsets.UTF_8))));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getProperties() {
|
||||||
|
// only properties starting with "otel.instrumentation." are resolved
|
||||||
|
// asking for properties which don't exist or inaccessible shouldn't result in an error
|
||||||
|
assertThat(bridge.getString("file_format")).isNull();
|
||||||
|
assertThat(bridge.getString("file_format", "foo")).isEqualTo("foo");
|
||||||
|
assertThat(emptyBridge.getBoolean("otel.instrumentation.common.default-enabled")).isNull();
|
||||||
|
assertThat(emptyBridge.getBoolean("otel.instrumentation.common.default-enabled", true))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
|
// common cases
|
||||||
|
assertThat(bridge.getBoolean("otel.instrumentation.common.default-enabled")).isTrue();
|
||||||
|
assertThat(bridge.getBoolean("otel.instrumentation.runtime-telemetry.enabled")).isFalse();
|
||||||
|
|
||||||
|
// check all the types
|
||||||
|
Map<String, String> expectedMap = new HashMap<>();
|
||||||
|
expectedMap.put("string_key1", "value1");
|
||||||
|
expectedMap.put("string_key2", "value2");
|
||||||
|
assertThat(bridge.getString("otel.instrumentation.example-instrumentation.string_key"))
|
||||||
|
.isEqualTo("value");
|
||||||
|
assertThat(bridge.getBoolean("otel.instrumentation.example-instrumentation.bool_key")).isTrue();
|
||||||
|
assertThat(bridge.getInt("otel.instrumentation.example-instrumentation.int_key")).isEqualTo(1);
|
||||||
|
assertThat(bridge.getLong("otel.instrumentation.example-instrumentation.int_key"))
|
||||||
|
.isEqualTo(1L);
|
||||||
|
assertThat(bridge.getDuration("otel.instrumentation.example-instrumentation.int_key"))
|
||||||
|
.isEqualTo(Duration.ofMillis(1));
|
||||||
|
assertThat(bridge.getDouble("otel.instrumentation.example-instrumentation.double_key"))
|
||||||
|
.isEqualTo(1.1);
|
||||||
|
assertThat(bridge.getList("otel.instrumentation.example-instrumentation.list_key"))
|
||||||
|
.isEqualTo(Arrays.asList("value1", "value2"));
|
||||||
|
assertThat(bridge.getMap("otel.instrumentation.example-instrumentation.map_key"))
|
||||||
|
.isEqualTo(expectedMap);
|
||||||
|
|
||||||
|
// asking for properties with the wrong type returns null
|
||||||
|
assertThat(bridge.getBoolean("otel.instrumentation.example-instrumentation.string_key"))
|
||||||
|
.isNull();
|
||||||
|
assertThat(bridge.getString("otel.instrumentation.example-instrumentation.bool_key")).isNull();
|
||||||
|
assertThat(bridge.getString("otel.instrumentation.example-instrumentation.int_key")).isNull();
|
||||||
|
assertThat(bridge.getString("otel.instrumentation.example-instrumentation.double_key"))
|
||||||
|
.isNull();
|
||||||
|
assertThat(bridge.getString("otel.instrumentation.example-instrumentation.list_key")).isNull();
|
||||||
|
assertThat(bridge.getString("otel.instrumentation.example-instrumentation.map_key")).isNull();
|
||||||
|
|
||||||
|
// check all the types
|
||||||
|
assertThat(bridge.getString("otel.instrumentation.other-instrumentation.string_key", "value"))
|
||||||
|
.isEqualTo("value");
|
||||||
|
assertThat(bridge.getBoolean("otel.instrumentation.other-instrumentation.bool_key", true))
|
||||||
|
.isTrue();
|
||||||
|
assertThat(bridge.getInt("otel.instrumentation.other-instrumentation.int_key", 1)).isEqualTo(1);
|
||||||
|
assertThat(bridge.getLong("otel.instrumentation.other-instrumentation.int_key", 1L))
|
||||||
|
.isEqualTo(1L);
|
||||||
|
assertThat(
|
||||||
|
bridge.getDuration(
|
||||||
|
"otel.instrumentation.other-instrumentation.int_key", Duration.ofMillis(1)))
|
||||||
|
.isEqualTo(Duration.ofMillis(1));
|
||||||
|
assertThat(bridge.getDouble("otel.instrumentation.other-instrumentation.double_key", 1.1))
|
||||||
|
.isEqualTo(1.1);
|
||||||
|
assertThat(
|
||||||
|
bridge.getList(
|
||||||
|
"otel.instrumentation.other-instrumentation.list_key",
|
||||||
|
Arrays.asList("value1", "value2")))
|
||||||
|
.isEqualTo(Arrays.asList("value1", "value2"));
|
||||||
|
assertThat(bridge.getMap("otel.instrumentation.other-instrumentation.map_key", expectedMap))
|
||||||
|
.isEqualTo(expectedMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -42,7 +42,6 @@ import io.opentelemetry.javaagent.tooling.muzzle.AgentTooling;
|
||||||
import io.opentelemetry.javaagent.tooling.util.Trie;
|
import io.opentelemetry.javaagent.tooling.util.Trie;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
|
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
|
||||||
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
|
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -121,7 +120,7 @@ public class AgentInstaller {
|
||||||
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
|
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
|
||||||
installOpenTelemetrySdk(extensionClassLoader);
|
installOpenTelemetrySdk(extensionClassLoader);
|
||||||
|
|
||||||
ConfigProperties sdkConfig = AutoConfigureUtil.getConfig(autoConfiguredSdk);
|
ConfigProperties sdkConfig = AgentListener.resolveConfigProperties(autoConfiguredSdk);
|
||||||
AgentInstrumentationConfig.internalInitializeConfig(new ConfigPropertiesBridge(sdkConfig));
|
AgentInstrumentationConfig.internalInitializeConfig(new ConfigPropertiesBridge(sdkConfig));
|
||||||
copyNecessaryConfigToSystemProperties(sdkConfig);
|
copyNecessaryConfigToSystemProperties(sdkConfig);
|
||||||
|
|
||||||
|
|
@ -196,7 +195,7 @@ public class AgentInstaller {
|
||||||
|
|
||||||
addHttpServerResponseCustomizers(extensionClassLoader);
|
addHttpServerResponseCustomizers(extensionClassLoader);
|
||||||
|
|
||||||
runAfterAgentListeners(agentListeners, autoConfiguredSdk);
|
runAfterAgentListeners(agentListeners, autoConfiguredSdk, sdkConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void copyNecessaryConfigToSystemProperties(ConfigProperties config) {
|
private static void copyNecessaryConfigToSystemProperties(ConfigProperties config) {
|
||||||
|
|
@ -268,7 +267,9 @@ public class AgentInstaller {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void runAfterAgentListeners(
|
private static void runAfterAgentListeners(
|
||||||
Iterable<AgentListener> agentListeners, AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
|
Iterable<AgentListener> agentListeners,
|
||||||
|
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk,
|
||||||
|
ConfigProperties sdkConfigProperties) {
|
||||||
// java.util.logging.LogManager maintains a final static LogManager, which is created during
|
// java.util.logging.LogManager maintains a final static LogManager, which is created during
|
||||||
// class initialization. Some AgentListener implementations may use JRE bootstrap classes
|
// class initialization. Some AgentListener implementations may use JRE bootstrap classes
|
||||||
// which touch this class (e.g. JFR classes or some MBeans).
|
// which touch this class (e.g. JFR classes or some MBeans).
|
||||||
|
|
@ -286,8 +287,7 @@ public class AgentInstaller {
|
||||||
// the application is already setting the global LogManager and AgentListener won't be able
|
// the application is already setting the global LogManager and AgentListener won't be able
|
||||||
// to touch it due to class loader locking.
|
// to touch it due to class loader locking.
|
||||||
boolean shouldForceSynchronousAgentListenersCalls =
|
boolean shouldForceSynchronousAgentListenersCalls =
|
||||||
AutoConfigureUtil.getConfig(autoConfiguredSdk)
|
sdkConfigProperties.getBoolean(FORCE_SYNCHRONOUS_AGENT_LISTENERS_CONFIG, false);
|
||||||
.getBoolean(FORCE_SYNCHRONOUS_AGENT_LISTENERS_CONFIG, false);
|
|
||||||
boolean javaBefore9 = isJavaBefore9();
|
boolean javaBefore9 = isJavaBefore9();
|
||||||
if (!shouldForceSynchronousAgentListenersCalls && javaBefore9 && isAppUsingCustomLogManager()) {
|
if (!shouldForceSynchronousAgentListenersCalls && javaBefore9 && isAppUsingCustomLogManager()) {
|
||||||
logger.fine("Custom JUL LogManager detected: delaying AgentListener#afterAgent() calls");
|
logger.fine("Custom JUL LogManager detected: delaying AgentListener#afterAgent() calls");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
instrumentation:
|
||||||
|
java:
|
||||||
|
common:
|
||||||
|
default-enabled: true
|
||||||
|
runtime-telemetry:
|
||||||
|
enabled: false
|
||||||
|
external-annotations:
|
||||||
|
enabled: true
|
||||||
|
example-instrumentation:
|
||||||
|
string_key: value
|
||||||
|
bool_key: true
|
||||||
|
int_key: 1
|
||||||
|
double_key: 1.1
|
||||||
|
list_key:
|
||||||
|
- value1
|
||||||
|
- value2
|
||||||
|
map_key:
|
||||||
|
string_key1: value1
|
||||||
|
string_key2: value2
|
||||||
|
bool_key: true
|
||||||
Loading…
Reference in New Issue