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.propagators.PropagationAutoConfiguration,\
|
||||
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");
|
||||
|
||||
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 -> {
|
||||
assertThat(logRecord.getInstrumentationScopeInfo().getName()).isEqualTo("test");
|
||||
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