Skip to content

Commit f6af6c1

Browse files
committed
add spring starter declarative config span logging
./gradlew spotlessApply
1 parent 823068d commit f6af6c1

File tree

5 files changed

+209
-55
lines changed

5 files changed

+209
-55
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging;
7+
8+
import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty;
9+
10+
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
11+
import io.opentelemetry.exporter.logging.LoggingSpanExporter;
12+
import io.opentelemetry.instrumentation.logging.internal.AbstractSpanLoggingCustomizerProvider;
13+
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelEnabled;
14+
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider;
15+
import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider;
16+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
17+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
18+
import org.springframework.context.annotation.Bean;
19+
import org.springframework.context.annotation.Conditional;
20+
import org.springframework.context.annotation.Configuration;
21+
22+
/**
23+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
24+
* any time.
25+
*/
26+
@Conditional(OtelEnabled.class)
27+
@ConditionalOnClass(LoggingSpanExporter.class)
28+
@Configuration
29+
public class DeclarativeConfigLoggingExporterAutoConfiguration {
30+
@Bean
31+
public DeclarativeConfigurationCustomizerProvider spanLoggingCustomizerProvider() {
32+
return new SpanLoggingCustomizerProvider();
33+
}
34+
35+
static class SpanLoggingCustomizerProvider extends AbstractSpanLoggingCustomizerProvider {
36+
@Override
37+
protected boolean isEnabled(OpenTelemetryConfigurationModel model) {
38+
DeclarativeConfigProperties instrumentation =
39+
SdkConfigProvider.create(model).getInstrumentationConfig();
40+
if (instrumentation == null) {
41+
return false;
42+
}
43+
44+
return instrumentation
45+
.getStructured("java", empty())
46+
.getStructured("spring_starter", empty())
47+
.getBoolean("debug", false);
48+
}
49+
}
50+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration;
11+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
12+
import java.io.ByteArrayInputStream;
13+
import java.nio.charset.StandardCharsets;
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
import java.util.function.Function;
17+
import org.junit.jupiter.params.ParameterizedTest;
18+
import org.junit.jupiter.params.provider.CsvSource;
19+
20+
class SpanLoggingCustomizerProviderTest {
21+
22+
@ParameterizedTest
23+
@CsvSource({
24+
"true, false, true",
25+
"false, false, false",
26+
", false, false", // empty value means property is not set
27+
"invalid, false, false",
28+
"true, true, true",
29+
})
30+
void addSpanLoggingExporter(String propertyValue, boolean alreadyAdded, boolean expected) {
31+
String debug =
32+
propertyValue == null
33+
? ""
34+
: "instrumentation/development: \n"
35+
+ " java: \n"
36+
+ " spring_starter: \n"
37+
+ " debug: "
38+
+ propertyValue;
39+
40+
String yaml =
41+
alreadyAdded
42+
? "file_format: \"1.0-rc.1\"\n"
43+
+ "tracer_provider:\n"
44+
+ " processors:\n"
45+
+ " - simple:\n"
46+
+ " exporter:\n"
47+
+ " console: {}\n"
48+
: "file_format: \"1.0-rc.1\"\n" + debug;
49+
50+
OpenTelemetryConfigurationModel model =
51+
applyCustomizer(
52+
DeclarativeConfiguration.parse(
53+
new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))),
54+
new DeclarativeConfigLoggingExporterAutoConfiguration.SpanLoggingCustomizerProvider());
55+
56+
String console = "ConsoleExporterModel";
57+
if (expected) {
58+
assertThat(model.toString()).containsOnlyOnce(console);
59+
} else {
60+
assertThat(model.toString()).doesNotContain(console);
61+
}
62+
}
63+
64+
private static OpenTelemetryConfigurationModel applyCustomizer(
65+
OpenTelemetryConfigurationModel model,
66+
DeclarativeConfigLoggingExporterAutoConfiguration.SpanLoggingCustomizerProvider provider) {
67+
List<Function<OpenTelemetryConfigurationModel, OpenTelemetryConfigurationModel>> customizers =
68+
new ArrayList<>();
69+
provider.customize(c -> customizers.add(c));
70+
for (Function<OpenTelemetryConfigurationModel, OpenTelemetryConfigurationModel> customizer :
71+
customizers) {
72+
model = customizer.apply(model);
73+
}
74+
return model;
75+
}
76+
}

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SpanLoggingCustomizerProvider.java

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,69 +7,18 @@
77

88
import com.google.auto.service.AutoService;
99
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
10-
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer;
10+
import io.opentelemetry.instrumentation.logging.internal.AbstractSpanLoggingCustomizerProvider;
1111
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider;
12-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ConsoleExporterModel;
1312
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
14-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel;
15-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel;
16-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel;
17-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel;
1813

1914
/** Adds span logging exporter for debug mode */
2015
@AutoService(DeclarativeConfigurationCustomizerProvider.class)
21-
public class SpanLoggingCustomizerProvider implements DeclarativeConfigurationCustomizerProvider {
16+
public class SpanLoggingCustomizerProvider extends AbstractSpanLoggingCustomizerProvider {
2217

2318
@Override
24-
public void customize(DeclarativeConfigurationCustomizer customizer) {
25-
customizer.addModelCustomizer(
26-
model -> {
27-
maybeEnableLoggingExporter(model);
28-
return model;
29-
});
30-
}
31-
32-
private static void maybeEnableLoggingExporter(OpenTelemetryConfigurationModel model) {
19+
protected boolean isEnabled(OpenTelemetryConfigurationModel model) {
3320
// read from system properties as it's an early init property and the config bridge is not
3421
// available here
35-
if (!ConfigPropertiesUtil.getBoolean("otel.javaagent.debug", false)) {
36-
return;
37-
}
38-
// don't install another instance if the user has already explicitly requested it.
39-
if (loggingExporterIsAlreadyConfigured(model)) {
40-
return;
41-
}
42-
TracerProviderModel tracerProvider = model.getTracerProvider();
43-
if (tracerProvider == null) {
44-
tracerProvider = new TracerProviderModel();
45-
model.withTracerProvider(tracerProvider);
46-
}
47-
SpanProcessorModel processor =
48-
new SpanProcessorModel()
49-
.withSimple(
50-
new SimpleSpanProcessorModel()
51-
.withExporter(new SpanExporterModel().withConsole(new ConsoleExporterModel())));
52-
tracerProvider.getProcessors().add(processor);
53-
}
54-
55-
private static boolean loggingExporterIsAlreadyConfigured(OpenTelemetryConfigurationModel model) {
56-
TracerProviderModel tracerProvider = model.getTracerProvider();
57-
if (tracerProvider == null) {
58-
return false;
59-
}
60-
for (SpanProcessorModel processor : tracerProvider.getProcessors()) {
61-
SimpleSpanProcessorModel simple = processor.getSimple();
62-
if (simple == null) {
63-
continue;
64-
}
65-
SpanExporterModel exporter = simple.getExporter();
66-
if (exporter == null) {
67-
continue;
68-
}
69-
if (exporter.getConsole() != null) {
70-
return true;
71-
}
72-
}
73-
return false;
22+
return ConfigPropertiesUtil.getBoolean("otel.javaagent.debug", false);
7423
}
7524
}

sdk-autoconfigure-support/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ group = "io.opentelemetry.instrumentation"
77

88
dependencies {
99
api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
10+
api("io.opentelemetry:opentelemetry-sdk-extension-incubator")
1011

1112
compileOnly("com.google.code.findbugs:annotations")
1213
testCompileOnly("com.google.code.findbugs:annotations")
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.logging.internal;
7+
8+
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer;
9+
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider;
10+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ConsoleExporterModel;
11+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
12+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel;
13+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel;
14+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel;
15+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel;
16+
17+
/**
18+
* Adds span logging exporter for debug mode
19+
*
20+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
21+
* at any time.
22+
*/
23+
public abstract class AbstractSpanLoggingCustomizerProvider
24+
implements DeclarativeConfigurationCustomizerProvider {
25+
26+
protected abstract boolean isEnabled(OpenTelemetryConfigurationModel model);
27+
28+
@Override
29+
public void customize(DeclarativeConfigurationCustomizer customizer) {
30+
customizer.addModelCustomizer(
31+
model -> {
32+
maybeEnableLoggingExporter(model);
33+
return model;
34+
});
35+
}
36+
37+
private void maybeEnableLoggingExporter(OpenTelemetryConfigurationModel model) {
38+
if (!isEnabled(model)) {
39+
return;
40+
}
41+
// don't install another instance if the user has already explicitly requested it.
42+
if (loggingExporterIsAlreadyConfigured(model)) {
43+
return;
44+
}
45+
TracerProviderModel tracerProvider = model.getTracerProvider();
46+
if (tracerProvider == null) {
47+
tracerProvider = new TracerProviderModel();
48+
model.withTracerProvider(tracerProvider);
49+
}
50+
SpanProcessorModel processor =
51+
new SpanProcessorModel()
52+
.withSimple(
53+
new SimpleSpanProcessorModel()
54+
.withExporter(new SpanExporterModel().withConsole(new ConsoleExporterModel())));
55+
tracerProvider.getProcessors().add(processor);
56+
}
57+
58+
private static boolean loggingExporterIsAlreadyConfigured(OpenTelemetryConfigurationModel model) {
59+
TracerProviderModel tracerProvider = model.getTracerProvider();
60+
if (tracerProvider == null) {
61+
return false;
62+
}
63+
for (SpanProcessorModel processor : tracerProvider.getProcessors()) {
64+
SimpleSpanProcessorModel simple = processor.getSimple();
65+
if (simple == null) {
66+
continue;
67+
}
68+
SpanExporterModel exporter = simple.getExporter();
69+
if (exporter == null) {
70+
continue;
71+
}
72+
if (exporter.getConsole() != null) {
73+
return true;
74+
}
75+
}
76+
return false;
77+
}
78+
}

0 commit comments

Comments
 (0)