Java Spring Boot 编程日志配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20507341/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:24:27  来源:igfitidea点击:

Spring Boot programmatic logging configuration

javaloggingspring-boot

提问by Axel Fontaine

How can I configure logging programmaticallyin a spring boot application?

如何在 Spring Boot 应用程序中以编程方式配置日志记录?

Using an xml or properties file is not flexible enough for my needs.

使用 xml 或属性文件不足以满足我的需要。

Update:I want to achieve something like this:

更新:我想实现这样的目标:

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

All I have per environment is:

我每个环境所拥有的只是:

  • logging.level.root=[INFO, DEBUG, ..]
  • logging.level.myApp=[INFO, DEBUG, ..]
  • logging.file=[true | false]
  • logging.level.root=[信息,调试,..]
  • logging.level.myApp=[信息,调试,..]
  • logging.file=[真| 错误的]

No duplication of XML, Groovy and other formats I really don't want to deal with.

没有重复的 XML、Groovy 和其他我真的不想处理的格式。

At the end of the day, this is really about achieving the same flexibility for logging as Spring JavaConfig did for beans. XML or other file formats are simply too static, require too much duplication and not integrated well enough with the rest of the configuration of the application.

归根结底,这实际上是为了实现与 Spring JavaConfig 为 bean 所做的相同的日志记录灵活性。XML 或其他文件格式太静态,需要太多重复,并且与应用程序的其余配置集成得不够好。

Why should logging be configured differently than any other bean or service?It makes no sense.

为什么日志记录的配置应该与任何其他 bean 或服务不同?这没有道理。

采纳答案by Dave Syer

I'm not sure you want or need to disable the default XML configuration of the logging system, but you do want to execute your customization calls afterthat was done. Fortunately that's pretty easy as it's done as early as possible in the initializer chain for a SpringApplication. The easiest place to put your code is probably a SpringApplicationInitializer(it has to implement ApplicationContextInitializeras well so it can be added to the SpringApplication). E.g.

我不确定您是否想要或需要禁用日志系统的默认 XML 配置,但您确实希望在完成执行自定义调用。幸运的是,这很容易,因为它尽可能早地在SpringApplication. 最容易放置代码的地方可能是 a SpringApplicationInitializer(它也必须实现ApplicationContextInitializer,以便可以添加到SpringApplication)。例如

SpringApplication application = new SpringApplication(MySources.class);
application.addInitializers(new LoggingInitializer());
application.run(args);

You won't be able to do dependency injection into the initializer if you do it that way, but it will ensure that it gets called as early as possible in the lifecycle. If your initializer implements EnvironmentAwarethen you will also be passed an instance of Environmentbefore the call to SpringApplicationInitializer.initialize()- using that you can resolve the environment dependent pieces in your sample, e.g.

如果这样做,您将无法对初始化程序进行依赖注入,但它会确保在生命周期中尽早调用它。如果您的初始值设定项实现,EnvironmentAware那么您还将Environment在调用之前传递一个实例SpringApplicationInitializer.initialize()- 使用它您可以解析示例中的环境相关部分,例如

String loggingLevelRoot = environment.getProperty("logging.level.root");

Once you have it working, to avoid having to do the same thing for all apps you can make it declarative by adding a META-INF/spring.factoriescontaining your initializer class:

一旦你让它工作,为了避免对所有应用程序做同样的事情,你可以通过添加一个META-INF/spring.factories包含你的初始化器类来使其声明性:

org.springframework.context.ApplicationContextInitializer=\
my.pkg.for.LoggingInitializer

If you really need dependency injection and @Valueresolution I think you are going to have to accept that the ApplicationContextwill have fully refreshed before you get a chance to configure anything. If that's an acceptable compromise I recommend just adding a LoggingInitializerto your context and have it implement CommandLineRunner.

如果你真的需要依赖注入和@Value解析,我认为你将不得不接受ApplicationContext在你有机会配置任何东西之前已经完全刷新。如果这是一个可以接受的妥协,我建议只LoggingInitializer在您的上下文中添加 a并让它实现CommandLineRunner.