2017-08-22 116 views
2

我正在使用春季啓動1.5.4,我正在嘗試編寫一個啓動程序,包括任何使用它的應用程序的自定義日誌appender。這是我如何註冊它:在春季啓動啓動器註冊自定義日誌appender

@Override 
synchronized public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { 
    if (!addedCustomAppender && metricProperties.isEnabled()) { 
     //Add log appender for Monitoring 
     EventsPublisher eventsPublisher = contextRefreshedEvent.getApplicationContext().getBean(EventsPublisher.class); 
     final Appender<ILoggingEvent> newAppender = new CustomLogbackAppender(eventsPublisher); 
     LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); 
     final Logger root = context.getLogger("ROOT"); 
     newAppender.setName("Custom Appender"); 
     newAppender.setContext(context); 
     newAppender.start(); 
     root.addAppender(newAppender); 
     addedCustomAppender = true; 
    } 
} 

這被調用,我可以看到ROOT記錄器有appender。實際上它在應用程序啓動期間工作了幾秒鐘。

但是很快,在應用程序啓動後期,ApplicationEnvironmentPreparedEvent被觸發,這觸發了LoggingApplicationListener中的一種重新初始化。

出現這種情況之後我在日誌中看到:

INFO 15888 --- [   main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase -2147482648 

在LogbackLoggingSystem,我可以看到stopAndReset方法,它調用記錄器recursiveReset方法的調用。之後,Spring默認配置被加載,並且我的自定義appender不再存在。

我該如何避免這種情況發生,以便我的自定義appender儘可能早地獲取一些日誌並保持連接到ROOT記錄器?

或者至少我怎麼能在所有事情都被初始化後註冊我的appender? (在這種情況下,我想我會錯過一些日誌,所以這不是我的目標解決方案)

謝謝!

回答

2

Spring的LoggingApplicationListener是....

  • Ordered.HIGHEST_PRECEDENCE + 20
  • 綁定到以下事件類型配置:ApplicationStartingEvent.class, ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class, ContextClosedEvent.class, ApplicationFailedEvent.class

所以,LoggingApplicationListener的結合(即響應)相同應用程序事件作爲您的偵聽器(ContextRefreshedEvent),並且由於它以如此高的優先級運行(Ordered.HIGHEST_PRECEDENCE + 20),因此它將通過在偵聽器之後運行來取代偵聽器。

您需要更改偵聽器的優先級,以便「保持連接到ROOT記錄器」並綁定到不同的事件,以便「儘早獲取某些日誌」。

下面是一個示例實現:

public class LoggingConfigurationApplicationListener implements GenericApplicationListener { 
    private static final Logger logger = LoggerFactory.getLogger(LoggingConfigurer.class); 

    private boolean addedCustomAppender; 

    @Override 
    public void onApplicationEvent(ApplicationEvent event) { 
     if (!addedCustomAppender && metricProperties.isEnabled()) { 
      ApplicationPreparedEvent applicationEvent = (ApplicationPreparedEvent) event; 
      EventsPublisher eventPublisher = applicationEvent.getApplicationContext().getBean(EventsPublisher.class); 
      //Add log appender for Monitoring 
      final Appender<ILoggingEvent> newAppender = new CustomLogbackAppender(eventPublisher); 
      LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); 
      final ch.qos.logback.classic.Logger root = context.getLogger("ROOT"); 
      newAppender.setName("Custom Appender"); 
      newAppender.setContext(context); 
      newAppender.start(); 
      root.addAppender(newAppender); 
      logger.info("Added custom log appender"); 
      addedCustomAppender = true; 
     } 
    } 

    @Override 
    public int getOrder() { 
     // this must be higher than LoggingApplicationListener.DEFAULT_ORDER 
     return Ordered.HIGHEST_PRECEDENCE + 21; 
    } 

    @Override 
    public boolean supportsEventType(ResolvableType eventType) { 
     // this is the earliest 'event type' which is capable of exposing the application context 
     return ApplicationPreparedEvent.class.isAssignableFrom(eventType.getRawClass()); 
    } 

    @Override 
    public boolean supportsSourceType(Class<?> sourceType) { 
     return true; 
    } 
} 

您如下這個監聽器與彈簧啓動應用程序相關聯:

@SpringBootApplication 
public class Application { 

    public static void main(String[] args) { 
     new SpringApplicationBuilder(Application.class) 
       .listeners(new LoggingConfigurationApplicationListener()) 
       .run(args); 
    } 
} 

使用這種實現,你會重新配置LoggerContext早期(當SpringApplication是啓動和所有的bean定義已經被加載),你的改變不會被Spring的LoggingApplicationListener覆蓋。

下面是與代替上述聽者一些示例性日誌,這些顯示(a)所述自定義附加器被添加和(b)的自定義附加器仍然存在的applicaiotn開始後:

2017-08-22 09:25:01|restartedMain|INFO |c.s.s.logging.LoggingConfigurer|Added custom log appender 
2017-08-22 09:25:01|restartedMain|INFO |c.s.springboot.Application|Starting Application on ... with PID 92710 ... 
2017-08-22 09:25:01|restartedMain|INFO |c.s.springboot.Application|No active profile set, falling back to default profiles: default 
2017-08-22 09:25:07|restartedMain|INFO |o.a.catalina.core.StandardService|Starting service [Tomcat] 
2017-08-22 09:25:07|restartedMain|INFO |o.a.catalina.core.StandardEngine|Starting Servlet Engine: Apache Tomcat/8.5.16 
2017-08-22 09:25:07|localhost-startStop-1|INFO |o.a.c.c.C.[.[.[/spring-boot]|Initializing Spring embedded WebApplicationContext 
2017-08-22 09:25:09|Thread-6|INFO |c.s.s.logging.LoggingVerifier|Custom appender is present 
2017-08-22 09:25:10|Thread-6|INFO |c.s.s.logging.LoggingVerifier|Custom appender is present 
+0

謝謝,它的工作原理!我有一個骯髒的修復程序,包括在每當我發現它不再存在時重新附加它,但這更好! –

+0

附加說明:啓用自動配置後,無需在監聽器(..)的app main方法中手動添加監聽器:偵聽器將自動註冊 –