92

I want to add some log.debug statements to a class I'm working on, and I'd like to see that in output when running the test. I'd like to override the log4j properties on the command line, with something like this:

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

I do this kind of thing frequently. I am specifically only interested in a way to pass this on the command line. I know how to do it with a config file, and that doesn't suit my workflow.

1
  • -Dorg.apache.logging.log4j.level=DEBUG Commented Feb 8, 2024 at 2:22

8 Answers 8

64

As part of your jvm arguments you can set -Dlog4j.configuration=file:"<FILE_PATH>". Where FILE_PATH is the path of your log4j.properties file.

Please note that as of log4j2, the new system variable to use is log4j.configurationFile and you put in the actual path to the file (i.e. without the file: prefix) and it will automatically load the factory based on the extension of the configuration file:

-Dlog4j.configurationFile=/path/to/log4jconfig.{ext} 
Sign up to request clarification or add additional context in comments.

3 Comments

FILE_PATH is actually searched on the CLASSPATH, including inside jar files.
You need to put "file:" in front of the path if it is a file on disk. In other words... -Dlog4j.configuration=file:<file_path> stackoverflow.com/questions/778933/…
This works as advertised; however I am trying to override a setting of a properties file in the jar, and the latter appears to get set after. Any advice?
43

These answers actually dissuaded me from trying the simplest possible thing! Simply specify a threshold for an appender (say, "console") in your log4j.configuration like so:

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

Then, on the command line, include the system property -Dlog4j.info -Dmy.logging.threshold=INFO. I assume that any other property can be parameterized in this way, but this is the easiest way to raise or lower the logging level globally.

9 Comments

I'm pretty sure this is the simplest solution to the original question!
@Droj Maybe so, but OP wanted to do this all in code. Chacun a son gout.
In my case, I wanted to set it from the command line too, but I already had a config. I just didn't want to have to edit the file to get different logging. I didn't read it as "all in code", but maybe so...
Just a minor improvement: yaml Loggers:\n Logger:\n name: stuff \n level: ${sys:my.log.level:-INFO}
I like the above YAML, but IIRC Spring won't do variable interpolation on YAML.
|
23

With Log4j2, this can be achieved using the following utility method added to your code.

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

You need these imports

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

Now invoke the setLogLevel method in your main() or whereever appropriate and pass command line params -Dlog4j.logger=com.mypackage.Thingie and -Dlog4j.debug=true.

1 Comment

This should be the accepted answer now that the packages is updated. Thank you for an updated answer--I deeply appreciate updated answers when it comes to long-standing questions. You saved me quite a bit of frustration.
18

log4j does not support this directly.

As you do not want a configuration file, you most likely use programmatic configuration. I would suggest that you look into scanning all the system properties, and explicitly program what you want based on this.

Comments

6

Based on Thorbjørn Ravn Andersens suggestion I wrote some code that makes this work

Add the following early in the main method and it is now possible to set the log level from the comand line. This have been tested in a project of mine but I'm new to log4j and might have made some mistake. If so please correct me.

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

Comments

5

In my pretty standard setup I've been seeing the following work well when passed in as VM Option (commandline before class in Java, or VM Option in an IDE):

-Droot.log.level=TRACE 

Comments

2

Based on @lijat, here is a simplified implementation. In my spring-based application I simply load this as a 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); } } } 

Comments

0

Try including the following JVM argument:

-Dorg.apache.logging.log4j.level=INFO

Source:
https://medium.com/@kasunbg/change-log4j2-default-logging-level-to-info-b25db8723eb9

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.