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!
Your blog looks nice on mobile phone