2011-08-19 56 views
49

我想爲我正在處理的類添加一些log.debug語句,並且希望在運行測試時在輸出中看到該語句。我想重寫命令行上的log4j屬性,如下所示:如何在命令行上設置log4j級別?

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

我經常這樣做。我特別只對通過命令行傳遞這個方法感興趣。我知道如何用配置文件來做到這一點,這不適合我的工作流程。

回答

12

log4j不直接支持這個。

由於您不需要配置文件,因此很可能使用編程配置。我建議你看看掃描所有的系統屬性,並根據此明確地編程你想要的。

41

作爲jvm參數的一部分,您可以設置-Dlog4j.configuration=file:"<FILE_PATH>"。 FILE_PATH是您的log4j.properties文件的路徑。

請注意,爲log4j2,新的系統變量使用的是log4j.configurationFile,你把實際的文件路徑(即沒有0​​前綴),並根據配置的擴展它會自動加載工廠文件:

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

FILE_PATH實際上是在CLASSPATH上搜索的,其中包括jar文件。 –

+12

如果它是磁盤上的文件,則需要將「file:」放在路徑的前面。 換句話說...... -Dlog4j。配置=文件: http://stackoverflow.com/questions/778933/log4j-configuration-via-jvm-arguments – crowmagnumb

+0

這與廣告一樣工作;但是我想重寫jar中的一個屬性文件的設置,並且後者似乎會被設置。有什麼建議? –

6

基於托爾比約恩Ravn的安徒生建議我寫了一些代碼,使這項工作

添加在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); 
     } 
    } 
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); 
    } 
    } 
} 
20

這些答案實際上阻礙了我嘗試最簡單的事情!只需在您的log4j.configuration指定一個appender閾值(比方說,「控制檯」),像這樣:

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

然後,在命令行上,包括系統屬性-Dlog4j.info -Dmy.logging.threshold=INFO。我假設任何其他屬性都可以通過這種方式進行參數化,但這是提高或降低全球日誌記錄級別的最簡單方法。

+0

我很確定這是對原始問題最簡單的解決方案! – Droj

+0

@Droj也許如此,但OP想要在代碼中完成這一切。 Chacun兒子痛風。 –

+0

就我而言,我想從命令行設置它,但我已經有了一個配置。我只是不想編輯文件來獲得不同的日誌記錄。我沒有把它看作「全部用代碼」,但也許是這樣...... – Droj

7

使用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()或徘徊無論合適,並通過命令行PARAMS -Dlog4j.logger=com.mypackage.Thingie-Dlog4j.debug=true

+1

這應該是現在包被更新的公認的答案。感謝您提供最新的答案 - 對於長期存在的問題,我深表感謝。你救了我很多挫折。 –