I\'m using the standard ConsoleHandler
from java.util.logging
and by default the console output is directed to the error stream (i.e. System.
Have a look at the docs and source for ConsoleHandler - I'm sure you could easily write a version which just uses System.err instead of System.out. (It's a shame that ConsoleHandler doesn't allow this to be configured, to be honest.)
Then it's just a case of configuring the logging system to use your new StdoutHandler (or whatever you call it) in the normal way.
I had a similar problem. I wanted to log INFO and below to System.out
, and WARNING and above to System.err
. Here is the solution I implemented:
public class DualConsoleHandler extends StreamHandler {
private final ConsoleHandler stderrHandler = new ConsoleHandler();
public DualConsoleHandler() {
super(System.out, new SimpleFormatter());
}
@Override
public void publish(LogRecord record) {
if (record.getLevel().intValue() <= Level.INFO.intValue()) {
super.publish(record);
super.flush();
} else {
stderrHandler.publish(record);
stderrHandler.flush();
}
}
}
Of course, you could make it more flexible by factoring out the hard-coded reference to Level.INFO
, for example. But this worked well for me to get some basic dual-stream logging. (BTW, the tips about not subclassing ConsoleHandler to avoid closing the System.err
were very useful.)
I figured out one way. First remove the default console handler:
setUseParentHandlers(false);
Then subclass ConsoleHandler and in the constructor:
setOutputStream(System.out);
If there is still someone out there looking for a solution to this problem. Here's what I came up with finally: I just subclassed StreamHandler and added an additional parameter MaxLevel, which is checked at the beginning of publish(). If the level of the logging event is larger than MaxLevel, publish won't be executed any further. Here are the details:
MaxlevelStreamHandler.java Main Class below.
package helper;
/**
* The only difference to the standard StreamHandler is
* that a MAXLEVEL can be defined (which then is not published)
*
* @author Kai Goergen
*/
import java.io.PrintStream;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
public class MaxlevelStreamHandler extends StreamHandler {
private Level maxlevel = Level.SEVERE; // by default, put out everything
/**
* The only method we really change to check whether the message
* is smaller than maxlevel.
* We also flush here to make sure that the message is shown immediately.
*/
@Override
public synchronized void publish(LogRecord record) {
if (record.getLevel().intValue() > this.maxlevel.intValue()) {
// do nothing if the level is above maxlevel
} else {
// if we arrived here, do what we always do
super.publish(record);
super.flush();
}
}
/**
* getter for maxlevel
* @return
*/
public Level getMaxlevel() {
return maxlevel;
}
/**
* Setter for maxlevel.
* If a logging event is larger than this level, it won't be displayed
* @param maxlevel
*/
public void setMaxlevel(Level maxlevel) {
this.maxlevel = maxlevel;
}
/** Constructor forwarding */
public MaxlevelStreamHandler(PrintStream out, Formatter formatter) {
super(out, formatter);
}
/** Constructor forwarding */
public MaxlevelStreamHandler() {
super();
}
}
Main Class
To now show some events in stdout and some in stderr, simply setup two StreamLoggers, one for critical events and one for all others, and disable the standard console logger:
// setup all logs that are smaller than WARNINGS to stdout
MaxlevelStreamHandler outSh = new MaxlevelStreamHandler(System.out, formatter);
outSh.setLevel(Level.ALL);
outSh.setMaxlevel(Level.INFO);
logger.addHandler(outSh);
// setup all warnings to stdout & warnings and higher to stderr
StreamHandler errSh = new StreamHandler(System.err, formatter);
errSh.setLevel(Level.WARNING);
logger.addHandler(errSh);
// remove default console logger
logger.setUseParentHandlers(false);
logger.info("info");
logger.warning("warning");
logger.severe("severe");
Hope this helps!
Update: I added super.flush() right after super.publish() to make sure that the message is shown immediately. Before, I had problems that the log-messages were always shown at the end. It's now part of the code above.
Simply extend StreamHandler & in the constructor call Super(System.out,). This will avoid closing System.err - Thanks
Step 1: Set parent handlers to false.
log.setUseParentHandlers(false);
Step 2: Add a handler that writes to System.out
log.addHandler(new StreamHandler(System.out, new SimpleFormatter()));
Thats it..
import java.io.IOException;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.logging.StreamHandler;
public class App {
static final Logger log = Logger.getLogger("com.sample.app.App");
static void processData() {
log.info("Started Processing Data");
log.info("Finished processing data");
}
public static void main(String args[]) throws IOException {
log.setUseParentHandlers(false);
log.addHandler(new StreamHandler(System.out, new SimpleFormatter()));
processData();
}
}