В коде добавлено приложение Spring Boot для удаления журнала (автоматическая настройка)

Я хотел бы иметь автоматическую конфигурацию spring, которая добавляет LogstashTcpSocketAppender.

Что я сделал:

  1. LogstashTcpSocketAppender был добавлен в LoggerContext из LogstashAutoConfiguration.java.
@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;
    }
}

  1. Через некоторое время Spring Boot инициирует событие, которое заставит приложение перенастроиться. (например, я использую Consul, поэтому я просто меняю свойство в хранилище ключей/значений, а затем Spring обновляю свой контекст)
  2. Он вызывает InitializeWithConventions в файле AbstractLoggingSystem.java.
  3. затем он вызовет loadConfiguration в LogbackLoggingSystem.java.
  4. затем он остановитAndReset(loggerContext). здесь он остановит все добавления и сбросит AllListeners();, что очистит все прослушиватели журнала. (поэтому я не могу снова использовать прослушиватели журнала для добавления приложений)

Есть ли правильный способ добавить Appender через автоматическую настройку Spring? Как я могу предотвратить удаление LogstashTcpSocketAppender из LoggerContext, когда Spring делает перенастройку приложения?


comment
Ну, может быть, вы можете попробовать заказать создание таких компонентов конфигурации, используя аннотации DependsOn или Order. Не знаю, сработает ли, но попробовать стоит. Ознакомьтесь с stackoverflow.com/questions/44314418/ и документы. spring.io/spring-framework/docs/current/javadoc-api/org/   -  person Onur Baştürk    schedule 20.09.2020
comment
@wakedeer дайте мне знать, если приведенный ниже ответ не работает.   -  person GSSwain    schedule 28.09.2020


Ответы (1)


В приведенном выше классе Configuration цель состоит в том, чтобы добавить appender для Logstash, и это позаботится об отправке журналов.

В случае изменения переменной среды или обновления контекста вы можете прослушать соответствующие события, а затем проверить, настроен ли ваш модуль приложения Logstash или нет. Убедитесь, что вы добавили приложение Logstash, только если оно отсутствует.

Вот класс, который сделает то же самое.

@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);                                                                                      ;
            }
        }
    }
}
person GSSwain    schedule 27.09.2020