Java 是否可以在命令行上配置 logback 记录器级别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23253916/
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 21:32:21  来源:igfitidea点击:

Is it possible to configure logback logger levels on the command line?

javalogginglog4jlogback

提问by bfancher

Log4J allows you to pass the level you'd like particular loggers in your application to log at from the command line, e.g. "-Dlog4j.logger.com.whatever.MyClass=DEBUG". I can't find any similar facility in Logback. According to the FAQ, all it seems to allow you to do is set the level for the root logger by using variable substitution. Is there something I'm missing or does Logback just not support this? Thanks.

Log4J 允许您从命令行传递您希望应用程序中特定记录器登录的级别,例如“-Dlog4j.logger.com.whatever.MyClass=DEBUG”。我在 Logback 中找不到任何类似的工具。根据常见问题解答,它似乎只允许您使用变量替换来设置根记录器的级别。有什么我遗漏的或者 Logback 不支持这个吗?谢谢。

回答by kan

Yes, seems there is no such feature. As I understand, it is partly because that logback configuration is more complex so quite difficult to achieve reasonable configuration flexibility by flat string properties. Partly because, imho, it encourages bad practice - placing too many system properties - leads to bloated run-scripts or command lines, more difficult to manage than separate logging configuration files.

是的,好像没有这个功能。据我了解,部分原因是 logback 配置更复杂,因此很难通过扁平字符串属性实现合理的配置灵活性。部分原因是,恕我直言,它鼓励不好的做法 - 放置太多系统属性 - 导致膨胀的运行脚本或命令行,比单独的日志配置文件更难以管理。

However, I could suggest several options:

但是,我可以建议几种选择:

  • use ${sys.prop.var.name}substitutions in your logback.xml config file
  • copy logback.xml locally, modify it with desired logger levels and specify -Dlogback.configurationFile=/path/to/customised/logback.xml. Keep in mind that "Logback-classic can scan for changes in its configuration file and automatically reconfigure itself when the configuration file changes". So, you even don't need to relaunch your process to change logging levels.
  • DIY: Add a code in your application which would read system properties and apply the properties to the logging levels during start up.
  • ${sys.prop.var.name}在 logback.xml 配置文件中使用替换
  • 在本地复制 logback.xml,使用所需的记录器级别修改它并指定-Dlogback.configurationFile=/path/to/customised/logback.xml. 请记住,“Logback-classic 可以扫描其配置文件中的更改,并在配置文件更改时自动重新配置自己”。因此,您甚至不需要重新启动流程来更改日志记录级别。
  • DIY:在您的应用程序中添加一个代码,该代码将在启动期间读取系统属性并将这些属性应用于日志记录级别。

回答by Dag

As stated in the FAQ:

正如常见问题解答中所述:

Logback does not allow logging to be disabled from the command line. However, if the configuration file allows it, you can set the level of loggers on the command line via a Java system property.

Logback 不允许从命令行禁用日志记录。但是,如果配置文件允许,您可以通过 Java 系统属性在命令行上设置记录器的级别。

So as @kan mentioned previously you have to use other options.

因此,正如@kan 之前提到的,您必须使用其他选项。

回答by Beno?t

I know this is an old question, but here is my solution code to initialize Logback Logger levels from SysProps, if anyone needs it. Note that it retrieves the Logback Logger using Slf4j's LoggerFactory. It uses a Java 8 lambda but could easily be translated to Java 7 or less.

我知道这是一个老问题,但这是我的解决方案代码,用于从 SysProps 初始化 Logback Logger 级别(如果有人需要的话)。请注意,它使用 Slf4j 的 LoggerFactory 检索 Logback Logger。它使用 Java 8 lambda,但可以轻松转换为 Java 7 或更低版本。

You just have to add SysPropLogbackConfigurator.applyOnce()at the start of your mainmethod. If called multiple time, the static initializer will prevent re-scanning the properties.

您只需要SysPropLogbackConfigurator.applyOnce()main方法的开头添加。如果多次调用,静态初始化程序将阻止重新扫描属性。

package com.yourpackage;

import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;

/**
 * Looks into System.properties for props -DLOG.loggerName=LEVEL to set Logback levels at startup
 * If LEVEL is empty (setting -DLOG.loggerName without level), it erases a previously set level and will inherit from parent logger
 */
public class SysPropLogbackConfigurator {

    public static final String PROP_PREFIX = "LOG.";

    public static void apply() {
        System.getProperties().stringPropertyNames().stream().filter(name -> name.startsWith(PROP_PREFIX)).forEach(SysPropLogbackConfigurator::applyProp);
    }

    public static void applyOnce() {
        OnceInitializer.emptyMethodToForceInit();//force static init. applySysPropsToLogback will be called only once
    }

    private static void applyProp(final String name) {
        final String loggerName = name.substring(PROP_PREFIX.length());
        final String levelStr = System.getProperty(name, "");
        final Level level = Level.toLevel(levelStr, null);
        ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(loggerName)).setLevel(level);
    }

    private static class OnceInitializer {
        static {
            apply();
        }

        static void emptyMethodToForceInit() {
        };
    }
}