Spring boot remove logback appender added in code(自动配置)
Spring boot remove logback appender added in code(auto configuration)
我想要 spring 添加 LogstashTcpSocketAppender 的自动配置。
我做了什么:
- LogstashTcpSocketAppender 已从 LogstashAutoConfiguration.java
添加到 LoggerContext
@Configuration
@ConditionalOnProperty(name = "logging.logstash.url")
@RequiredArgsConstructor
public class LogstashAutoConfiguration {
@Value("${spring.application.name:null}")
private String applicationName;
@Value("${logging.logstash.url}")
private String logstashUrl;
@Bean
public LogstashTcpSocketAppender logstashAppender() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
LogstashTcpSocketAppender logstashTcpSocketAppender = new LogstashTcpSocketAppender();
logstashTcpSocketAppender.setName("LOGSTASH");
logstashTcpSocketAppender.setContext(loggerContext);
logstashTcpSocketAppender.addDestination(logstashUrl);
LogstashEncoder encoder = new LogstashEncoder();
encoder.setIncludeMdc(true);
encoder.getFieldNames().setLevelValue(null);
encoder.setCustomFields(String.format("{\"app_name\":\"%s\"}", applicationName));
logstashTcpSocketAppender.setEncoder(encoder);
logstashTcpSocketAppender.start();
loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(logstashTcpSocketAppender);
return logstashTcpSocketAppender;
}
}
- 一段时间后,Spring 启动触发事件将使应用程序重新配置。 (例如,我使用 Consul,所以我只需更改 key/value 存储中的 属性,然后 spring 刷新我的上下文)
- 它调用 AbstractLoggingSystem.java
中的 initializeWithConventions
- 然后它将调用 LogbackLoggingSystem.java
中的 loadConfiguration
- 然后它将 stopAndReset(loggerContext)。在这里它会停止所有的 appender,它会重置 AllListeners();,这将清除所有的 logback 监听器。 (所以我不能再次使用 logback 侦听器来添加附加程序)
是否有通过spring自动配置添加Appender的正确方法?
当 spring 重新配置应用程序时,如何防止从 LoggerContext 中删除 LogstashTcpSocketAppender?
在上面的 Configuration
class 中,目的是为 Logstash
添加一个 appender
并负责发送日志。
如果环境变量发生变化或上下文被刷新,您可以监听相关事件,然后检查您的 Logstash appender 是否已配置。确保仅在缺少 Logstash appender 时才添加它。
这是执行相同操作的 class。
@Configuration
@ConditionalOnProperty(name = "logging.logstash.url")
public class LogstashAppenderConfiguration {
@Value("${spring.application.name:null}")
private String applicationName;
@Value("${logging.logstash.url}")
private String logstashUrl;
@EventListener(ContextRefreshedEvent.class)
public void onContextRefreshedEvent(ContextRefreshedEvent event) {
this.addLogStashAppenderIfMissing();
}
@EventListener(RefreshScopeRefreshedEvent.class)
public void onRefreshScopeRefreshedEvent(RefreshScopeRefreshedEvent event) {
this.addLogStashAppenderIfMissing();
}
@EventListener(EnvironmentChangeEvent.class)
public void onEnvironmentChangeEvent(EnvironmentChangeEvent event) {
this.addLogStashAppenderIfMissing();
}
public void addLogStashAppenderIfMissing() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
synchronized (this) {
if (Objects.isNull(loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).getAppender("LOGSTASH"))) {
LogstashTcpSocketAppender logstashTcpSocketAppender = new LogstashTcpSocketAppender();
logstashTcpSocketAppender.setName("LOGSTASH");
logstashTcpSocketAppender.setContext(loggerContext);
logstashTcpSocketAppender.addDestination(logstashUrl);
LogstashEncoder encoder = new LogstashEncoder();
encoder.setIncludeMdc(true);
encoder.getFieldNames().setLevelValue(null);
encoder.setCustomFields(String.format("{\"app_name\":\"%s\"}", applicationName));
logstashTcpSocketAppender.setEncoder(encoder);
logstashTcpSocketAppender.start();
loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(logstashTcpSocketAppender); ;
}
}
}
}
我想要 spring 添加 LogstashTcpSocketAppender 的自动配置。
我做了什么:
- LogstashTcpSocketAppender 已从 LogstashAutoConfiguration.java 添加到 LoggerContext
@Configuration
@ConditionalOnProperty(name = "logging.logstash.url")
@RequiredArgsConstructor
public class LogstashAutoConfiguration {
@Value("${spring.application.name:null}")
private String applicationName;
@Value("${logging.logstash.url}")
private String logstashUrl;
@Bean
public LogstashTcpSocketAppender logstashAppender() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
LogstashTcpSocketAppender logstashTcpSocketAppender = new LogstashTcpSocketAppender();
logstashTcpSocketAppender.setName("LOGSTASH");
logstashTcpSocketAppender.setContext(loggerContext);
logstashTcpSocketAppender.addDestination(logstashUrl);
LogstashEncoder encoder = new LogstashEncoder();
encoder.setIncludeMdc(true);
encoder.getFieldNames().setLevelValue(null);
encoder.setCustomFields(String.format("{\"app_name\":\"%s\"}", applicationName));
logstashTcpSocketAppender.setEncoder(encoder);
logstashTcpSocketAppender.start();
loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(logstashTcpSocketAppender);
return logstashTcpSocketAppender;
}
}
- 一段时间后,Spring 启动触发事件将使应用程序重新配置。 (例如,我使用 Consul,所以我只需更改 key/value 存储中的 属性,然后 spring 刷新我的上下文)
- 它调用 AbstractLoggingSystem.java 中的 initializeWithConventions
- 然后它将调用 LogbackLoggingSystem.java 中的 loadConfiguration
- 然后它将 stopAndReset(loggerContext)。在这里它会停止所有的 appender,它会重置 AllListeners();,这将清除所有的 logback 监听器。 (所以我不能再次使用 logback 侦听器来添加附加程序)
是否有通过spring自动配置添加Appender的正确方法? 当 spring 重新配置应用程序时,如何防止从 LoggerContext 中删除 LogstashTcpSocketAppender?
在上面的 Configuration
class 中,目的是为 Logstash
添加一个 appender
并负责发送日志。
如果环境变量发生变化或上下文被刷新,您可以监听相关事件,然后检查您的 Logstash appender 是否已配置。确保仅在缺少 Logstash appender 时才添加它。
这是执行相同操作的 class。
@Configuration
@ConditionalOnProperty(name = "logging.logstash.url")
public class LogstashAppenderConfiguration {
@Value("${spring.application.name:null}")
private String applicationName;
@Value("${logging.logstash.url}")
private String logstashUrl;
@EventListener(ContextRefreshedEvent.class)
public void onContextRefreshedEvent(ContextRefreshedEvent event) {
this.addLogStashAppenderIfMissing();
}
@EventListener(RefreshScopeRefreshedEvent.class)
public void onRefreshScopeRefreshedEvent(RefreshScopeRefreshedEvent event) {
this.addLogStashAppenderIfMissing();
}
@EventListener(EnvironmentChangeEvent.class)
public void onEnvironmentChangeEvent(EnvironmentChangeEvent event) {
this.addLogStashAppenderIfMissing();
}
public void addLogStashAppenderIfMissing() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
synchronized (this) {
if (Objects.isNull(loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).getAppender("LOGSTASH"))) {
LogstashTcpSocketAppender logstashTcpSocketAppender = new LogstashTcpSocketAppender();
logstashTcpSocketAppender.setName("LOGSTASH");
logstashTcpSocketAppender.setContext(loggerContext);
logstashTcpSocketAppender.addDestination(logstashUrl);
LogstashEncoder encoder = new LogstashEncoder();
encoder.setIncludeMdc(true);
encoder.getFieldNames().setLevelValue(null);
encoder.setCustomFields(String.format("{\"app_name\":\"%s\"}", applicationName));
logstashTcpSocketAppender.setEncoder(encoder);
logstashTcpSocketAppender.start();
loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(logstashTcpSocketAppender); ;
}
}
}
}