2017-08-22 2 views
2

J'utilise Spring Boot 1.5.4 et j'essaye d'écrire un démarreur qui inclurait un appender journal personnalisé pour toute application l'utilisant. Voici comment je l'enregistre:enregistrer appender journal personnalisé dans le démarreur de démarrage au printemps

@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; 
    } 
} 

Ceci est appelé, et je peux voir l'enregistreur racine ayant l'appender. Cela fonctionne réellement pendant quelques secondes au démarrage de l'application.

Mais très rapidement, plus tard au cours du démarrage de l'application, un événement ApplicationEnvironmentPreparedEvent est déclenché, ce qui déclenche une sorte de réinitialisation dans LoggingApplicationListener.

Cela se produit juste après que je vois dans les journaux:

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

dans LogbackLoggingSystem, je peux voir un appel à la méthode stopAndReset, qui appelle la méthode recursiveReset sur Bûcherons. Après cela, Spring config par défaut est chargé, et mon appender personnalisé n'est plus là.

Comment puis-je éviter que cela se produise, afin que mon appender personnalisé obtienne des journaux le plus tôt possible et reste attaché à l'enregistreur ROOT?

ou au moins comment puis-je enregistrer mon appender après que tout a été initialisé? (dans ce cas, je suppose que je manquerais certains journaux, donc ce n'est pas ma solution cible)

Merci!

Répondre

2

LoggingApplicationListener Printemps est ....

  • Configuré avec Ordered.HIGHEST_PRECEDENCE + 20
  • lié aux types d'événements suivants: ApplicationStartingEvent.class, ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class, ContextClosedEvent.class, ApplicationFailedEvent.class

Ainsi, LoggingApplicationListener lie à (c.-à-répondre à) la même Evénement d'application en tant qu'auditeur (ContextRefreshedEvent) et comme il s'exécute avec une telle priorité (Ordered.HIGHEST_PRECEDENCE + 20) il remplace votre écouteur en l'exécutant.

Vous devrez modifier la priorité de votre programme d'écoute afin de «rester connecté à l'enregistreur ROOT» et de vous lier à un événement différent afin de «récupérer certains journaux le plus tôt possible».

Voici un exemple d'implémentation:

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; 
    } 
} 

Vous associez cet écouteur avec votre application de démarrage Spring comme suit:

@SpringBootApplication 
public class Application { 

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

Avec cette implémentation vous reconfiguré au début LoggerContext (lorsque le SpringApplication est démarrage et toutes les définitions de bean ont été chargées) et vos modifications ne seront pas remplacées par LoggingApplicationListener de Spring.

Voici quelques exemples de journaux avec l'auditeur ci-dessus en place, ce spectacle (a) la coutume appender étant ajoutée et (b) que le appender personnalisé est toujours présent après la applicaiotn a commencé:

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

Merci, ça marche! J'avais un sale problème qui consistait à le ré-attacher chaque fois que je trouvais que ce n'était plus là, mais c'est beaucoup mieux! –

+0

Note supplémentaire: avec la configuration automatique activée, pas besoin d'ajouter l'écouteur manuellement dans la méthode principale de l'application avec des écouteurs (..): l'auditeur sera automatiquement enregistré –

0

aussi, voir Listener not receiving ApplicationPreparedEvent pour plus d'infos sur la dépendance requise. La réponse de @glytching a fonctionné directement parce que j'avais les bonnes dépendances dans mon projet, mais ce n'était pas le cas dans d'autres projets