在Spring Boot Starter中注册自定义日志附加程序 [英] register custom log appender in spring boot starter

查看:112
本文介绍了在Spring Boot Starter中注册自定义日志附加程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring Boot 1.5.4,并且正在尝试编写一个启动程序,该启动程序将为使用它的任何应用程序包括一个自定义日志附加程序.这就是我的注册方式:

I'm using Spring Boot 1.5.4 and I'm trying to write a starter that would include a custom log appender for any application using it. This is how I register it :

@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记录器.在应用程序启动期间,它实际上已经工作了几秒钟.

This gets called, and I can see ROOT logger having the appender. It's actually working for a couple of seconds during application startup.

但是很快,在应用程序启动期间,会触发ApplicationEnvironmentPreparedEvent,这会触发LoggingApplicationListener中的某种重新初始化.

But very quickly, later during the application startup, an ApplicationEnvironmentPreparedEvent gets fired, which triggers a kind of re-initialization in LoggingApplicationListener.

这是在我在日志中看到后立即发生的:

This happens right after I see in the logs :

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

在LogbackLoggingSystem中,我可以看到对stopAndReset方法的调用,该方法在Loggers上调用recursiveReset方法.之后,Spring默认配置被加载,而我的自定义追加器不再存在.

in LogbackLoggingSystem, I can see a call to stopAndReset method, which calls recursiveReset method on Loggers. After that, Spring default config gets loaded, and my custom appender is not there anymore.

如何避免这种情况发生,以便我的自定义附加程序尽早获取一些日志并保持与ROOT记录器的连接?

How can I avoid this to happen, so that my custom appender gets some logs as early as possible and stays attached to ROOT logger ?

或者至少在所有初始化之后如何注册我的appender? (在那种情况下,我想我会错过一些日志,所以这不是我的目标解决方案)

or at least how can I register my appender after everything has been initialized ? (in that case, I guess I would miss some logs, so it's not my target solution)

谢谢!

推荐答案

Spring的LoggingApplicationListener是....

Spring's LoggingApplicationListener is ....

  • 使用Ordered.HIGHEST_PRECEDENCE + 20
  • 配置
  • 绑定到以下事件类型:ApplicationStartingEvent.class, ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class, ContextClosedEvent.class, ApplicationFailedEvent.class
  • Configured with Ordered.HIGHEST_PRECEDENCE + 20
  • Bound to the following event types: ApplicationStartingEvent.class, ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class, ContextClosedEvent.class, ApplicationFailedEvent.class

因此,LoggingApplicationListener绑定到(即响应)与您的侦听器(ContextRefreshedEvent)相同的应用程序事件,并且由于它以很高的优先级(Ordered.HIGHEST_PRECEDENCE + 20)运行,因此它通过运行来取代您的侦听器之后.

So, LoggingApplicationListener is binding to (i.e. responding to) the same application event as your listener (ContextRefreshedEvent) and since it is running with such a high precedence (Ordered.HIGHEST_PRECEDENCE + 20) it is superceding your listener by running after it.

您需要更改侦听器的优先级,以便保持与ROOT记录器的连接"并绑定到其他事件,以便尽早获取一些日志".

You'll need to change the precedence of your listener in order to "stay attached to ROOT logger" and bind to a different event in order to "get some logs as early as possible".

这是一个示例实现:

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

您可以将该监听器与Spring Boot应用程序关联起来,如下所示:

You associate this listener with your Spring Boot application as follows:

@SpringBootApplication
public class Application {

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

通过此实现,您将尽早重新配置LoggerContext(当SpringApplication启动并且所有bean定义都已加载时),并且您的更改将不会被Spring的LoggingApplicationListener覆盖.

With this implementation you'll reconfigure the LoggerContext early (when the SpringApplication is starting up and all bean definitions have been loaded) and your changes will not be overriden by Spring's LoggingApplicationListener.

以下是带有上述侦听器的示例日志,这些日志显示(a)已添加自定义附加程序,以及(b)在应用程序启动后仍存在自定义附加程序:

Here are some example logs with the above listener in place, these show (a) the custom appender being added and (b) that the custom appender is still present after the applicaiotn has started:

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

这篇关于在Spring Boot Starter中注册自定义日志附加程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆