Spring Boot 程序化日志配置
Posted
技术标签:
【中文标题】Spring Boot 程序化日志配置【英文标题】:Spring Boot programmatic logging configuration 【发布时间】:2013-12-28 17:30:47 【问题描述】:如何在 Spring Boot 应用程序中以编程方式配置日志记录?
使用 xml 或属性文件对我的需要不够灵活。
更新:我想实现这样的目标:
@Value("$logging.level.root")
private String loggingLevelRoot;
@Value("$logging.level.myApp")
private String loggingLevelMyApp;
@Value("$logging.file")
private boolean fileAppenderEnabled;
....
setLevel(Logger.ROOT_LOGGER_NAME, Level.toLevel(loggingLevelRoot)));
setLevel("com.myapp", Level.toLevel(loggingLevelMyApp)));
setLevel("org.springframework", Level.WARN);
setLevel("org.apache.coyote", Level.INFO);
setLevel("org.apache.catalina", Level.INFO);
setLevel("org.apache.catalina.startup.DigesterFactory", Level.ERROR);
setLevel("org.apache.catalina.util.LifecycleMBeanBase", Level.ERROR);
Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
logger.addAppender(createConsoleAppender());
if (fileAppenderEnabled)
logger.addAppender(createFileAppender());
每个环境我只有:
logging.level.root=[信息,调试,..] logging.level.myApp=[INFO, DEBUG, ..] logging.file=[真 |假]没有重复我真的不想处理的 XML、Groovy 和其他格式。
归根结底,这实际上是为了实现与 Spring JavaConfig 为 bean 所做的相同的日志记录灵活性。 XML 或其他文件格式太静态了,需要太多重复,并且与应用程序的其余配置集成得不够好。
为什么日志记录的配置应该与任何其他 bean 或服务不同?这没有任何意义。
【问题讨论】:
什么是使用xml不够灵活?如果你使用 Logback,你可以使用 Groovy 来配置 logback。 @M.Deinum 不,你不能; Spring Boot(实际上,我认为是 Spring Autoconfig)踩踏了 Groovy 配置。 我还需要对每个环境进行不同的配置,使用不同的 appender 类型,......所以不,XML 不会削减它。 @chrylislogback.groovy
应该在 Spring Boot 中得到明确支持(至少从 M6 开始,也许在那之前我忘记了)。如果它不起作用我建议你在 github 中提出一个问题并解释一下。
@AxelFontaine 您可以为每个环境提供不同的 XML(或 groovy 或其他)配置,只需更改每个 Spring 配置文件的 logging.config
(或仅作为启动时的系统属性)。这还不够灵活吗?
【参考方案1】:
我不确定您是否想要或需要禁用日志系统的默认 XML 配置,但您确实希望在完成之后执行自定义调用。。幸运的是,这很容易,因为它在 SpringApplication
的初始化链中尽早完成。最容易放置代码的地方可能是SpringApplicationInitializer
(它还必须实现ApplicationContextInitializer
,以便可以将其添加到SpringApplication
)。例如
SpringApplication application = new SpringApplication(MySources.class);
application.addInitializers(new LoggingInitializer());
application.run(args);
如果这样做,您将无法将依赖项注入到初始化程序中,但它会确保在生命周期中尽早调用它。如果您的初始化程序实现了EnvironmentAware
,那么您还将在调用SpringApplicationInitializer.initialize()
之前传递一个Environment
的实例 - 使用它您可以解析示例中与环境相关的部分,例如
String loggingLevelRoot = environment.getProperty("logging.level.root");
一旦你让它工作起来,为了避免对所有应用都做同样的事情,你可以通过添加一个包含你的初始化程序类的 META-INF/spring.factories
使它成为声明性的:
org.springframework.context.ApplicationContextInitializer=\
my.pkg.for.LoggingInitializer
如果您真的需要依赖注入和@Value
解析,我认为您将不得不接受ApplicationContext
将在您有机会配置任何内容之前完全刷新。如果这是一个可以接受的折衷方案,我建议在您的上下文中添加一个 LoggingInitializer
并让它实现 CommandLineRunner
。
【讨论】:
自定义的LoggingSystem
实现也可以完成这项工作,不是吗?但是它不会被自动检测到,所以你应该添加-Dorg.springframework.boot.logging.LoggingSystem=<class name>
(或设置系统属性)。
@DaveSyer EnvironmentAware
在这种情况下不起作用。如果您需要 Environment 实例,那么最好从 initialize()
方法内的应用程序上下文实例中获取它。
我发现这种对替代策略的解释非常有帮助。我确实需要参考这个问题,以获取如何执行此处推荐的一些操作的示例:***.com/questions/46636599/…以上是关于Spring Boot 程序化日志配置的主要内容,如果未能解决你的问题,请参考以下文章