如何在命令行上设置log4j级别?


77

我想向正在处理的类中添加一些log.debug语句,并且希望在运行测试时在输出中看到它。我想在命令行上覆盖log4j属性,如下所示:

-Dlog4j.logger.com.mypackage.Thingie=DEBUG

我经常做这种事情。我只对在命令行中传递它的方式感兴趣。我知道如何使用配置文件进行操作,但这不适合我的工作流程。

Answers:


15

log4j不直接支持此功能。

由于您不需要配置文件,因此您很可能使用编程配置。我建议您考虑扫描所有系统属性,并根据此内容显式编程所需的内容。


49

作为jvm参数的一部分,可以设置-Dlog4j.configuration=file:"<FILE_PATH>"。其中FILE_PATH是log4j.properties文件的路径。

请注意,从log4j2开始,要使用的新系统变量是log4j.configurationFile您放入文件的实际路径(即不带file:前缀),它将根据配置文件的扩展名自动加载工厂:

-Dlog4j.configurationFile=/path/to/log4jconfig.{ext}

3
实际上是在CLASSPATH上搜索FILE_PATH,包括在jar文件中。
罗宾·格林

12
如果它是磁盘上的文件,则需要在路径前面放置“ file:”。换句话说... -Dlog4j.configuration =文件:<FILE_PATH> stackoverflow.com/questions/778933/...
crowmagnumb

2
这如广告所示;但是我试图覆盖jar中的属性文件的设置,而后者似乎在之后设置。有什么建议吗?
约翰·莱曼

34

这些答案实际上使我无法尝试最简单的方法!只需log4j.configuration像这样指定一个附加器(例如“控制台”)的阈值即可:

log4j.appender.console.threshold=${my.logging.threshold}

然后,在命令行上包含system属性-Dlog4j.info -Dmy.logging.threshold=INFO。我假定可以通过这种方式对任何其他属性进行参数化,但这是在全球范围内提高或降低日志记录级别的最简单方法。


我很确定这是对原始问题最简单的解决方案!
Droj

@Droj也许是这样,但是OP希望用代码来完成所有这些工作。查村是儿子痛风。
AbuNassar

就我而言,我也想从命令行进行设置,但是我已经有了一个配置。我只是不想编辑该文件以获取不同的日志记录。我没有把它读为“全部代码”,但也许是……
Droj

1
一点点的改进:YAMLLoggers:\n Logger:\n name: stuff \n level: ${sys:my.log.level:-INFO}
ICH

我喜欢上面的YAML,但是IIRC Spring不会在YAML上进行变量插值。
阿布纳萨尔

17

使用Log4j2,可以通过将以下实用程序方法添加到您的代码中来实现。

private static void setLogLevel() {
  if (Boolean.getBoolean("log4j.debug")) {
    Configurator.setLevel(System.getProperty("log4j.logger"), Level.DEBUG);
  }
}

您需要这些进口

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;

现在,setLogLevel在main()或任何合适的地方调用方法,并传递命令行参数-Dlog4j.logger=com.mypackage.Thingie-Dlog4j.debug=true


2
既然软件包已更新,这应该是公认的答案。感谢您提供最新的答案-对于长期存在的问题,我深表感谢。你救了我很多挫败感。
Daniel B. Chapman

6

根据ThorbjørnRavn Andersens的建议,我编写了一些使此工作有效的代码

在main方法的早期添加以下内容,现在可以从comand行设置日志级别。这已经在我的一个项目中进行了测试,但是我是log4j的新手,可能会犯一些错误。如果是这样,请纠正我。

    Logger.getRootLogger().setLevel(Level.WARN);
    HashMap<String,Level> logLevels=new HashMap<String,Level>();
    logLevels.put("ALL",Level.ALL);
    logLevels.put("TRACE",Level.TRACE);
    logLevels.put("DEBUG",Level.DEBUG);
    logLevels.put("INFO",Level.INFO);
    logLevels.put("WARN",Level.WARN);
    logLevels.put("ERROR",Level.ERROR);
    logLevels.put("FATAL",Level.FATAL);
    logLevels.put("OFF",Level.OFF);
    for(String name:System.getProperties().stringPropertyNames()){
        String logger="log4j.logger.";
        if(name.startsWith(logger)){
            String loggerName=name.substring(logger.length());
            String loggerValue=System.getProperty(name);
            if(logLevels.containsKey(loggerValue))
                Logger.getLogger(loggerName).setLevel(logLevels.get(loggerValue));
            else
                Logger.getRootLogger().warn("unknown log4j logg level on comand line: "+loggerValue);
        }
    }

4

在我漂亮的标准设置中,当以VM Option(在Java上类之前的命令行,或在IDE中的VM Option)中传递时,我一直看到以下效果很好:

-Droot.log.level=TRACE

2

基于@lijat,这是一个简化的实现。在基于Spring的应用程序中,我只是将其作为bean加载。

public static void configureLog4jFromSystemProperties()
{
  final String LOGGER_PREFIX = "log4j.logger.";

  for(String propertyName : System.getProperties().stringPropertyNames())
  {
    if (propertyName.startsWith(LOGGER_PREFIX)) {
      String loggerName = propertyName.substring(LOGGER_PREFIX.length());
      String levelName = System.getProperty(propertyName, "");
      Level level = Level.toLevel(levelName); // defaults to DEBUG
      if (!"".equals(levelName) && !levelName.toUpperCase().equals(level.toString())) {
        logger.error("Skipping unrecognized log4j log level " + levelName + ": -D" + propertyName + "=" + levelName);
        continue;
      }
      logger.info("Setting " + loggerName + " => " + level.toString());
      Logger.getLogger(loggerName).setLevel(level);
    }
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.