Reputation: 4695
I'm trying to internally change the layout of a custom exception. To unit test this I'm looking to capture the console output. I've captured console output before but the method I used for that previously doesn't seem to have the expected result with log4j.
If I wanted to capture console output, I'd use:
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream printStream = new PrintStream(baos);
System.setOut(printStream);
System.out.println("Hello world!");
final String consoleOutput = baos.toString();
The value of consoleOutput would then be "Hello World!".
If I apply this to log4j using:
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream printStream = new PrintStream(baos);
System.setOut(printStream);
LOGGER.debug("Simple message");
final String consoleOutput = baos.toString();
consoleOutput is empty. Looking at the javadoc for ConsoleAppender I see:
The default target is System.out.
If I change my code to just include the line:
LOGGER.debug("Simple message");
I see the expected result in the console:
2013-06-02 19:49:46,818 DEBUG [com.parlance.LoggingTest] - Simple message
So I was assuming that this would work but have obviously missed something and have been left scratching my head!
UPDATE
I just tried something and if I change the creation of my logger class to be AFTER I call System.setOut, it appears to work:
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream printStream = new PrintStream(baos);
System.setOut(printStream);
final Logger logger = Logger.getLogger(LoggingTest.class);
logger.debug("Simple message");
final String consoleOutput = baos.toString();
This has the desired effect but isn't great if I want to Logger to be static. Any ideas why this happens and how to address the original question without declaring the logger this way?
Upvotes: 0
Views: 1848
Reputation: 61715
It seems the System.setOut
is being called after the initialisation of log4j. log4j initialises using the value of System.out
(it will keep a reference to it). You can get around it by calling System.setOut
before log4j as you've said.
For static loggers it gets harder; you can use the option
-Dlog4j.defaultInitOverride=true
This means that log4j doesn't get initialised automatically, but you'll still need to arrange that the System.setOut
gets called before the first logger.
For more information, see Short introduction to log4j (section Default Initialization Procedure)
Upvotes: 2