Automatic addition of the OTel Logback appender by the OTel starter (#10306)
This commit is contained in:
parent
7d544f1476
commit
8825359748
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging;
|
||||||
|
|
||||||
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
|
import ch.qos.logback.core.Appender;
|
||||||
|
import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import org.slf4j.ILoggerFactory;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||||
|
import org.springframework.boot.context.logging.LoggingApplicationListener;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
import org.springframework.context.event.GenericApplicationListener;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
|
|
||||||
|
public class LogbackAppenderApplicationListener implements GenericApplicationListener {
|
||||||
|
|
||||||
|
private static final Class<?>[] SOURCE_TYPES = {
|
||||||
|
SpringApplication.class, ApplicationContext.class
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Class<?>[] EVENT_TYPES = {ApplicationEnvironmentPreparedEvent.class};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsSourceType(Class<?> sourceType) {
|
||||||
|
return isAssignableFrom(sourceType, SOURCE_TYPES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsEventType(ResolvableType resolvableType) {
|
||||||
|
return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
|
||||||
|
if (type != null) {
|
||||||
|
for (Class<?> supportedType : supportedTypes) {
|
||||||
|
if (supportedType.isAssignableFrom(type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ApplicationEvent event) {
|
||||||
|
if (event instanceof ApplicationEnvironmentPreparedEvent // Event for which
|
||||||
|
// org.springframework.boot.context.logging.LoggingApplicationListener
|
||||||
|
// initializes logging
|
||||||
|
&& !isOpenTelemetryAppenderAlreadyConfigured()) {
|
||||||
|
ch.qos.logback.classic.Logger logger =
|
||||||
|
(ch.qos.logback.classic.Logger)
|
||||||
|
LoggerFactory.getILoggerFactory().getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
|
||||||
|
OpenTelemetryAppender appender = new OpenTelemetryAppender();
|
||||||
|
appender.start();
|
||||||
|
logger.addAppender(appender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isOpenTelemetryAppenderAlreadyConfigured() {
|
||||||
|
ILoggerFactory loggerFactorySpi = LoggerFactory.getILoggerFactory();
|
||||||
|
if (!(loggerFactorySpi instanceof LoggerContext)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LoggerContext loggerContext = (LoggerContext) loggerFactorySpi;
|
||||||
|
for (ch.qos.logback.classic.Logger logger : loggerContext.getLoggerList()) {
|
||||||
|
Iterator<Appender<ILoggingEvent>> appenderIterator = logger.iteratorForAppenders();
|
||||||
|
while (appenderIterator.hasNext()) {
|
||||||
|
Appender<ILoggingEvent> appender = appenderIterator.next();
|
||||||
|
if (appender instanceof OpenTelemetryAppender) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return LoggingApplicationListener.DEFAULT_ORDER + 1; // To execute this listener just after
|
||||||
|
// org.springframework.boot.context.logging.LoggingApplicationListener
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,3 +15,6 @@ io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux.Sp
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration,\
|
io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration,\
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.propagators.PropagationAutoConfiguration,\
|
io.opentelemetry.instrumentation.spring.autoconfigure.propagators.PropagationAutoConfiguration,\
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration
|
io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration
|
||||||
|
|
||||||
|
org.springframework.context.ApplicationListener=\
|
||||||
|
io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging.LogbackAppenderApplicationListener
|
||||||
|
|
|
@ -60,7 +60,9 @@ class LogbackAppenderTest {
|
||||||
LoggerFactory.getLogger("test").info("test log message");
|
LoggerFactory.getLogger("test").info("test log message");
|
||||||
|
|
||||||
assertThat(testing.logRecords())
|
assertThat(testing.logRecords())
|
||||||
.anySatisfy(
|
.satisfiesOnlyOnce(
|
||||||
|
// OTel appender automatically added or from an XML file, it should not
|
||||||
|
// be added a second time by LogbackAppenderApplicationListener
|
||||||
logRecord -> {
|
logRecord -> {
|
||||||
assertThat(logRecord.getInstrumentationScopeInfo().getName()).isEqualTo("test");
|
assertThat(logRecord.getInstrumentationScopeInfo().getName()).isEqualTo("test");
|
||||||
assertThat(logRecord.getBody().asString()).contains("test log message");
|
assertThat(logRecord.getBody().asString()).contains("test log message");
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
|
|
||||||
<appender name="OpenTelemetry"
|
|
||||||
class="io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender">
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root level="INFO">
|
|
||||||
<appender-ref ref="OpenTelemetry"/>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
</configuration>
|
|
Loading…
Reference in New Issue