有没有办法阻止 Spring Boot 覆盖我的日志配置?
Is there anyway to stop Spring Boot from overwriting my log config?
我有一个具有以下属性的记录器:
PrivateConfig [loggerConfig=Special, config=org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration@709a148, loggerConfigLevel=INFO, intLevel=400, logger=Special.com:INFO in 73d16e93]
这是一个特殊的记录器,具有我的应用程序所需的特定格式和特定目的地
此特殊记录器是通过以下方式创建的:
Level level = Level.toLevel(logLevel);
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setStatusLevel(level);
builder.setConfigurationName("whatever");
LoggerComponentBuilder specialLogger = builder.newLogger("Special", level);
AppenderComponentBuilder specialAppenderBuilder = builder
.newAppender("Special", "RollingFile")
.otherComponents();
specialAppenderBuilder.add(
builder
.newLayout("PatternLayout")
.otherComponents();
builder.add(specialAppenderBuilder);
specialLogger = specialLogger
.add(builder.newAppenderRef("Special"))
.addAttribute("additivity", false);
builder.add(specialLogger);
LoggerContext ctx = Configurator.initialize(builder.build());
ctx.start();
此记录器在未使用 Spring Boot
的应用程序 A 中工作
我将应用程序 A 的一部分导入到应用程序 B,它是 Spring 基于引导的,但随后完全相同的记录器变为:
PrivateConfig [loggerConfig=root, config=XmlConfiguration[location=jar:file:/Users/stamaki/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/2.4.4/38392ae406009e55efe873baee4633bfa6b766b3/spring-boot-2.4.4.jar!/org/springframework/boot/logging/log4j2/log4j2.xml], loggerConfigLevel=INFO, intLevel=400, logger=Special.com:INFO in 18b4aac2]
请注意,记录器配置正在从 Special
覆盖到 root
,它不再遵循我编写的自定义 BuiltConfiguration
,而是使用 Springboot 内部 xml.
如何阻止 Spring 引导覆盖我的配置?
似乎有一个类似的问题:
但解决方案不起作用
我也试过 Spring Boot: LoggingApplicationListener interfering with Application Server logging 但他们的解决方案仍然对我不起作用,因为它将我的记录器更改为
PrivateConfig [loggerConfig=root, config=org.springframework.boot.logging.log4j2.SpringBootConfigurationFactory$SpringBootConfiguration@16a3cc88, loggerConfigLevel=ERROR, intLevel=200, logger=NonSensitive.com.textiq.precisionenhancer.service.PrecisionEnhancerBackendService:ERROR in 18b4aac2]
即仍然使用 Root Config,而不是我设置的 Special Config,唯一与上面不同的是这是默认的 Root Logger 配置。
请不要提出“更新 XML 以使其具有相同格式”之类的建议,这不够模块化。我只是想使用我的库创建的同一个记录器,而不会被 Spring Boot.
覆盖
弄清楚发生了什么。
LoggerContext ctx = Configurator.initialize(builder.build());
ctx.start();
在应用A和B中,builder.build()
都有正确的信息,但是应用B的ctx
没有自定义配置
调查 Configurator.initalize
,这会尝试触发 Log4jContextFactory
:
public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
final boolean currentContext, final Configuration configuration) {
final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, null);
if (externalContext != null && ctx.getExternalContext() == null) {
ctx.setExternalContext(externalContext);
}
if (ctx.getState() == LifeCycle.State.INITIALIZED) {
ContextAnchor.THREAD_CONTEXT.set(ctx);
try {
ctx.start(configuration);
} finally {
ContextAnchor.THREAD_CONTEXT.remove();
}
}
return ctx;
}
请注意,除非上下文当前具有状态 INITIALIZED
,否则不会使用 configuration
可能是因为Spring会以任何一种方式在内部初始化某种Log4j,即使你设置了-Dorg.springframework.boot.logging.LoggingSystem=none
,返回的ctx总是STARTED
.
它的破解方法是始终调用 reinitailize 以强制将配置更新为内部的任何内容 builder.build()
:
BuiltConfiguration configuration = builder.build();
LoggerContext ctx = Configurator.initialize(configuration);
ctx.reconfigure(configuration);
ctx.start();
我有一个具有以下属性的记录器:
PrivateConfig [loggerConfig=Special, config=org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration@709a148, loggerConfigLevel=INFO, intLevel=400, logger=Special.com:INFO in 73d16e93]
这是一个特殊的记录器,具有我的应用程序所需的特定格式和特定目的地
此特殊记录器是通过以下方式创建的:
Level level = Level.toLevel(logLevel);
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setStatusLevel(level);
builder.setConfigurationName("whatever");
LoggerComponentBuilder specialLogger = builder.newLogger("Special", level);
AppenderComponentBuilder specialAppenderBuilder = builder
.newAppender("Special", "RollingFile")
.otherComponents();
specialAppenderBuilder.add(
builder
.newLayout("PatternLayout")
.otherComponents();
builder.add(specialAppenderBuilder);
specialLogger = specialLogger
.add(builder.newAppenderRef("Special"))
.addAttribute("additivity", false);
builder.add(specialLogger);
LoggerContext ctx = Configurator.initialize(builder.build());
ctx.start();
此记录器在未使用 Spring Boot
的应用程序 A 中工作我将应用程序 A 的一部分导入到应用程序 B,它是 Spring 基于引导的,但随后完全相同的记录器变为:
PrivateConfig [loggerConfig=root, config=XmlConfiguration[location=jar:file:/Users/stamaki/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/2.4.4/38392ae406009e55efe873baee4633bfa6b766b3/spring-boot-2.4.4.jar!/org/springframework/boot/logging/log4j2/log4j2.xml], loggerConfigLevel=INFO, intLevel=400, logger=Special.com:INFO in 18b4aac2]
请注意,记录器配置正在从 Special
覆盖到 root
,它不再遵循我编写的自定义 BuiltConfiguration
,而是使用 Springboot 内部 xml.
如何阻止 Spring 引导覆盖我的配置?
似乎有一个类似的问题:
我也试过 Spring Boot: LoggingApplicationListener interfering with Application Server logging 但他们的解决方案仍然对我不起作用,因为它将我的记录器更改为
PrivateConfig [loggerConfig=root, config=org.springframework.boot.logging.log4j2.SpringBootConfigurationFactory$SpringBootConfiguration@16a3cc88, loggerConfigLevel=ERROR, intLevel=200, logger=NonSensitive.com.textiq.precisionenhancer.service.PrecisionEnhancerBackendService:ERROR in 18b4aac2]
即仍然使用 Root Config,而不是我设置的 Special Config,唯一与上面不同的是这是默认的 Root Logger 配置。
请不要提出“更新 XML 以使其具有相同格式”之类的建议,这不够模块化。我只是想使用我的库创建的同一个记录器,而不会被 Spring Boot.
覆盖弄清楚发生了什么。
LoggerContext ctx = Configurator.initialize(builder.build());
ctx.start();
在应用A和B中,builder.build()
都有正确的信息,但是应用B的ctx
没有自定义配置
调查 Configurator.initalize
,这会尝试触发 Log4jContextFactory
:
public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
final boolean currentContext, final Configuration configuration) {
final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, null);
if (externalContext != null && ctx.getExternalContext() == null) {
ctx.setExternalContext(externalContext);
}
if (ctx.getState() == LifeCycle.State.INITIALIZED) {
ContextAnchor.THREAD_CONTEXT.set(ctx);
try {
ctx.start(configuration);
} finally {
ContextAnchor.THREAD_CONTEXT.remove();
}
}
return ctx;
}
请注意,除非上下文当前具有状态 INITIALIZED
configuration
可能是因为Spring会以任何一种方式在内部初始化某种Log4j,即使你设置了-Dorg.springframework.boot.logging.LoggingSystem=none
,返回的ctx总是STARTED
.
它的破解方法是始终调用 reinitailize 以强制将配置更新为内部的任何内容 builder.build()
:
BuiltConfiguration configuration = builder.build();
LoggerContext ctx = Configurator.initialize(configuration);
ctx.reconfigure(configuration);
ctx.start();