Sometimes you don’t want to ship a log4j.properties file — you want to spin up logging in code. Useful inside unit tests, one-off debug runs, or anywhere you want to flip log levels at runtime. Here’s a self-contained setupLog4j() that wipes any existing config, installs a console appender with a pattern, sets the root level to DEBUG, and binds a logger for your class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import org.apache.log4j.BasicConfigurator; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; private static void setupLog4j() { System.out.println("setupLog4j"); BasicConfigurator.resetConfiguration(); // Start clean. Logger.getRootLogger().removeAllAppenders(); // Create appender ConsoleAppender console = new ConsoleAppender(); // Configure the appender String PATTERN = "%d --[ %p ] %l: %m%n"; console.setLayout(new PatternLayout(PATTERN)); console.activateOptions(); console.setName("stdout"); Logger.getRootLogger().setLevel(Level.DEBUG); BasicConfigurator.configure(console); LOG = Logger.getLogger(MinerTest.class); } |
Replace MinerTest.class with your own class — it’s just the logger name (Log4j conventionally uses the fully-qualified class name so output stays organised by package).
A few useful additions.
This is Log4j 1.x — and Log4j 1.x is end-of-life. The package above is org.apache.log4j. Log4j 1.x reached EOL in August 2015 and has unpatched CVEs against it. If you’re starting something new, use Log4j 2 (org.apache.logging.log4j) or SLF4J with Logback. Keep this snippet around as a recipe for legacy projects, but don’t pick Log4j 1.x for anything fresh.
Set the level for one package, not the whole app. Logger.getRootLogger().setLevel(Level.DEBUG) turns DEBUG on globally — that floods everything, including third-party libraries. Usually you only want DEBUG for your own code:
1 2 | Logger.getLogger("com.acme.miner").setLevel(Level.DEBUG); Logger.getLogger("org.springframework").setLevel(Level.WARN); // tame the framework |
Same idea in Log4j 2. The API is different — there’s no BasicConfigurator; instead you talk to the LoggerContext / Configurator:
1 2 3 4 5 6 7 8 | import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; // Set the level for one package at runtime: Configurator.setLevel("com.acme.miner", Level.DEBUG); // Or for the root logger: Configurator.setRootLevel(Level.DEBUG); |
For the full “build a config from scratch” equivalent, see Log4j 2’s ConfigurationBuilder — the API is more verbose but lets you compose appenders, layouts, and loggers programmatically.
Using SLF4J / Logback? If your codebase logs via org.slf4j.Logger with Logback under the hood (very common), you flip levels through Logback’s own classes — SLF4J itself has no level-setting API:
1 2 3 4 5 6 | import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import org.slf4j.LoggerFactory; Logger logger = (Logger) LoggerFactory.getLogger("com.acme.miner"); logger.setLevel(Level.DEBUG); |
The cast from org.slf4j.Logger to ch.qos.logback.classic.Logger is the giveaway — SLF4J is just a facade; the level lives on the implementation. 🪵