Redirecting all stdout and stderr to Logger in Java

This would seem obvious, but it wasn’t to me, so I thought I’d write about it to help out anyone else attempting to accomplish the same. It’s pretty straight forward actually.

Let’s say you have a java.util.logging.Logger object that you’ve initialized, and you want to redirect all stderr (exceptions, System.err.print()’s) and stdout (System.out.print()) to it. You’ll want to use System.setErr and System.setOut to a custom java.io.PrintStream object which writes to your Logger object.

Let’s first define a class to do this for us, and then I’ll explain how it works:

class CustomOutputStream extends OutputStream 
{
	Logger logger;
	Level level;
	StringBuilder stringBuilder;
	
	public CustomOutputStream(Logger logger, Level level)
	{
		this.logger = logger;
		this.level = level;
		stringBuilder = new StringBuilder();
	}
	
	@Override
	public final void write(int i) throws IOException 
	{
		char c = (char) i;
		if(c == '\r' || c == '\n')
		{
			if(stringBuilder.length()>0)
			{
				logger.log(level,stringBuilder.toString());
				stringBuilder = new StringBuilder();
			}
		}
		else
			stringBuilder.append(c);
	}
}

The way this works is by extending OutputStream and overriding the write() method. But write() only takes one character at a time, so essentially you want to buffer each character into a String Builder, to build up the whole line, until you encounter a \r or \n (carriage return, new line), and then submit it to the logger.

To attach CustomOutputStream to your logger:

Logger logger = Logger.getLogger(...);
//...
System.setErr(
		new PrintStream(
			new CustomOutputStream(logger,Level.SEVERE) //Or whatever logger level you want
			)
		);  
System.setOut(
		new PrintStream(
				new CustomOutputStream(logger,Level.FINE) //Or whatever logger level you
			)
		);

Note: if you’ve configured your logger to always include the class/method with the log message, a side effect of this is that the output will not include your original method that wrote the log message to stderr or stdout , but instead your.package.CustomOutputStream.write().

Happy logging!

One thought on “Redirecting all stdout and stderr to Logger in Java”

Leave a Reply

Your email address will not be published. Required fields are marked *