Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging;

import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty;

import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
import io.opentelemetry.exporter.logging.LoggingSpanExporter;
import io.opentelemetry.instrumentation.logging.internal.AbstractSpanLoggingCustomizerProvider;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelEnabled;
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
@Conditional(OtelEnabled.class)
@ConditionalOnClass(LoggingSpanExporter.class)
@Configuration
public class DeclarativeConfigLoggingExporterAutoConfiguration {
@Bean
public DeclarativeConfigurationCustomizerProvider spanLoggingCustomizerProvider() {
return new SpanLoggingCustomizerProvider();
}

static class SpanLoggingCustomizerProvider extends AbstractSpanLoggingCustomizerProvider {
@Override
protected boolean isEnabled(OpenTelemetryConfigurationModel model) {
DeclarativeConfigProperties instrumentation =
SdkConfigProvider.create(model).getInstrumentationConfig();
if (instrumentation == null) {
return false;
}

return instrumentation
.getStructured("java", empty())
.getStructured("spring_starter", empty())
.getBoolean("debug", false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging;

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;

class SpanLoggingCustomizerProviderTest {

@ParameterizedTest
@CsvSource({
"true, false, true",
"false, false, false",
", false, false", // empty value means property is not set
"invalid, false, false",
"true, true, true",
})
@SuppressWarnings("StringConcatToTextBlock") // latest dep allows text blocks
void addSpanLoggingExporter(String propertyValue, boolean alreadyAdded, boolean expected) {
String debug =
propertyValue == null
? ""
: "instrumentation/development: \n"
+ " java: \n"
+ " spring_starter: \n"
+ " 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" + debug;

OpenTelemetryConfigurationModel model =
applyCustomizer(
DeclarativeConfiguration.parse(
new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))),
new DeclarativeConfigLoggingExporterAutoConfiguration.SpanLoggingCustomizerProvider());

String console = "ConsoleExporterModel";
if (expected) {
assertThat(model.toString()).containsOnlyOnce(console);
} else {
assertThat(model.toString()).doesNotContain(console);
}
}

private static OpenTelemetryConfigurationModel applyCustomizer(
OpenTelemetryConfigurationModel model,
DeclarativeConfigLoggingExporterAutoConfiguration.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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,69 +7,18 @@

import com.google.auto.service.AutoService;
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer;
import io.opentelemetry.instrumentation.logging.internal.AbstractSpanLoggingCustomizerProvider;
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 {
public class SpanLoggingCustomizerProvider extends AbstractSpanLoggingCustomizerProvider {

@Override
public void customize(DeclarativeConfigurationCustomizer customizer) {
customizer.addModelCustomizer(
model -> {
maybeEnableLoggingExporter(model);
return model;
});
}

private static void maybeEnableLoggingExporter(OpenTelemetryConfigurationModel model) {
protected boolean isEnabled(OpenTelemetryConfigurationModel model) {
// read from system properties as it's an early init property and the config bridge is not
// available here
if (!ConfigPropertiesUtil.getBoolean("otel.javaagent.debug", false)) {
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;
return ConfigPropertiesUtil.getBoolean("otel.javaagent.debug", false);
}
}
1 change: 1 addition & 0 deletions sdk-autoconfigure-support/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ group = "io.opentelemetry.instrumentation"

dependencies {
api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
api("io.opentelemetry:opentelemetry-sdk-extension-incubator")

compileOnly("com.google.code.findbugs:annotations")
testCompileOnly("com.google.code.findbugs:annotations")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.logging.internal;

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
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public abstract class AbstractSpanLoggingCustomizerProvider
implements DeclarativeConfigurationCustomizerProvider {

protected abstract boolean isEnabled(OpenTelemetryConfigurationModel model);

@Override
public void customize(DeclarativeConfigurationCustomizer customizer) {
customizer.addModelCustomizer(
model -> {
maybeEnableLoggingExporter(model);
return model;
});
}

private void maybeEnableLoggingExporter(OpenTelemetryConfigurationModel model) {
if (!isEnabled(model)) {
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;
}
}
Loading