I’d like to have spring auto configuration which adds LogstashTcpSocketAppender.
What I have done:
@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;
}
}
Are there correct way add Appender through spring auto configuration? How can I prevent remove LogstashTcpSocketAppender from LoggerContext when spring makes the app reconfig?
In the above Configuration
class, the intent is to add an appender
for Logstash
and that takes care of sending the logs.
In case of an environment variable changes or the context gets refreshed, you can listen to the relevant events, then check if your Logstash appender is configured or not. Make sure you add the Logstash appender only if it is missing.
Here is the class that would do the same.
@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); ;
}
}
}
}