This commit is contained in:
Gregor Zeitlinger 2025-09-19 15:05:17 +03:00 committed by GitHub
commit b4221441c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 157 additions and 0 deletions

View File

@ -0,0 +1,74 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.tooling;
import com.google.auto.service.AutoService;
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer;
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ConsoleExporterModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel;
/** Adds span logging exporter for debug mode */
@AutoService(DeclarativeConfigurationCustomizerProvider.class)
public class SpanLoggingCustomizerProvider implements DeclarativeConfigurationCustomizerProvider {
@Override
public void customize(DeclarativeConfigurationCustomizer customizer) {
customizer.addModelCustomizer(
model -> {
maybeEnableLoggingExporter(model);
return model;
});
}
private static void maybeEnableLoggingExporter(OpenTelemetryConfigurationModel model) {
// read from system properties as it's an early init property and the config bridge is not
// available here
if (!"true".equals(System.getProperty("otel.javaagent.debug"))) {
return;
}
// don't install another instance if the user has already explicitly requested it.
if (loggingExporterIsAlreadyConfigured(model)) {
return;
}
TracerProviderModel tracerProvider = model.getTracerProvider();
if (tracerProvider == null) {
tracerProvider = new TracerProviderModel();
model.withTracerProvider(tracerProvider);
}
SpanProcessorModel processor =
new SpanProcessorModel()
.withSimple(
new SimpleSpanProcessorModel()
.withExporter(new SpanExporterModel().withConsole(new ConsoleExporterModel())));
tracerProvider.getProcessors().add(processor);
}
private static boolean loggingExporterIsAlreadyConfigured(OpenTelemetryConfigurationModel model) {
TracerProviderModel tracerProvider = model.getTracerProvider();
if (tracerProvider == null) {
return false;
}
for (SpanProcessorModel processor : tracerProvider.getProcessors()) {
SimpleSpanProcessorModel simple = processor.getSimple();
if (simple == null) {
continue;
}
SpanExporterModel exporter = simple.getExporter();
if (exporter == null) {
continue;
}
if (exporter.getConsole() != null) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.tooling;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junitpioneer.jupiter.ClearSystemProperty;
class SpanLoggingCustomizerProviderTest {
@ParameterizedTest
@CsvSource({
"true, true, false",
"false, false, false",
", false, false", // empty value means property is not set
"invalid, false, false",
"true, true, true",
})
@ClearSystemProperty(key = "otel.javaagent.debug")
void addSpanLoggingExporter(String propertyValue, boolean expected, boolean alreadyAdded) {
if (propertyValue != null) {
System.setProperty("otel.javaagent.debug", propertyValue);
}
String yaml =
alreadyAdded
? "file_format: \"1.0-rc.1\"\n"
+ "tracer_provider:\n"
+ " processors:\n"
+ " - simple:\n"
+ " exporter:\n"
+ " console: {}\n"
: "file_format: \"1.0-rc.1\"\n";
OpenTelemetryConfigurationModel model =
applyCustomizer(
DeclarativeConfiguration.parse(
new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))),
new SpanLoggingCustomizerProvider());
String console = "ConsoleExporterModel";
if (expected) {
assertThat(model.toString()).containsOnlyOnce(console);
} else {
assertThat(model.toString()).doesNotContain(console);
}
}
private static OpenTelemetryConfigurationModel applyCustomizer(
OpenTelemetryConfigurationModel model, SpanLoggingCustomizerProvider provider) {
List<Function<OpenTelemetryConfigurationModel, OpenTelemetryConfigurationModel>> customizers =
new ArrayList<>();
provider.customize(c -> customizers.add(c));
for (Function<OpenTelemetryConfigurationModel, OpenTelemetryConfigurationModel> customizer :
customizers) {
model = customizer.apply(model);
}
return model;
}
}

View File

@ -26,6 +26,12 @@ import java.util.Collections;
import java.util.List; import java.util.List;
public class TestExporterCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { public class TestExporterCustomizerProvider implements DeclarativeConfigurationCustomizerProvider {
@Override
public int order() {
return Integer.MIN_VALUE; // run before other customizers that might add exporters
}
@Override @Override
public void customize(DeclarativeConfigurationCustomizer customizer) { public void customize(DeclarativeConfigurationCustomizer customizer) {
if (TestSpanExporterComponentProvider.getSpanExporter() == null) { if (TestSpanExporterComponentProvider.getSpanExporter() == null) {

View File

@ -30,6 +30,12 @@ import java.util.List;
@AutoService(DeclarativeConfigurationCustomizerProvider.class) @AutoService(DeclarativeConfigurationCustomizerProvider.class)
public class AgentTestExporterCustomizerProvider public class AgentTestExporterCustomizerProvider
implements DeclarativeConfigurationCustomizerProvider { implements DeclarativeConfigurationCustomizerProvider {
@Override
public int order() {
return Integer.MIN_VALUE; // run before other customizers that might add exporters
}
@Override @Override
public void customize(DeclarativeConfigurationCustomizer customizer) { public void customize(DeclarativeConfigurationCustomizer customizer) {
TestExportersUtil.initTestExporters(); TestExportersUtil.initTestExporters();