How to Disable the Default Console Handler, While Using the Java Logging API

How can I disable the default console handler, while using the java logging API?

The default console handler is attached to the root logger, which is a parent of all other loggers including yours. So I see two ways to solve your problem:

If this is only affects this particular class of yours, the simplest solution would be to disable passing the logs up to the parent logger:

logger.setUseParentHandlers(false);

If you want to change this behaviour for your whole app, you could remove the default console handler from the root logger altogether before adding your own handlers:

Logger globalLogger = Logger.getLogger("global");
Handler[] handlers = globalLogger.getHandlers();
for(Handler handler : handlers) {
globalLogger.removeHandler(handler);
}

Note: if you want to use the same log handlers in other classes too, the best way is to move the log configuration into a config file in the long run.

java logging API, disable logging to standard output

The question arises if you don't know the default configuration of java util logging.
Architectural fact:
0)Every logger whatever its name is has the root logger as parent.
Default facts:
1) the logger property useParentHandlers is true by default
2) the root logger has a ConsoleHandler by default

So. A new logger, by default sends its log records also to his parent(point 1) that is the root logger(point 0) wich, by default, logs them to console(point 2).

Remove console logging is easy as:

Logger l0 = Logger.getLogger("");
l0.removeHandler(l0.getHandlers()[0]);

Why does my java logging go to console as well as file

Add code to com.jthink.songkong.logging.StandardLogging to print the logger tree at the end of your configuration. This will help you troubleshoot what is happening. Since you are using a configuration class you can even make your own system property to toggle printing the logger tree if you need to in the future.

If your console output looks like the format of the CmdLineFormatter you created then code is either using that logger or a child logger that is printing to the parent handlers. Assuming you control the format of the CmdLineFormatter you can include the logger name in the output to locate the logger in question.

If the output looks like the SimpleFormatter then more likely it is the console handler that is attached to the root logger. Simply remove that handler from the root logger in your configuration class.

A more complete solution is to invoke LogManager.reset at the start of your StandardLogging class constructor. This would clear out the configuration that the JRE set prior to invoking your changes. An alternative is to set the java.util.logging.config.file to point to a null device from the command line in addition to setting your java.util.logging.config.class.

Turn off java.util.logging for a specific package programmatically

There is a way to do this programatically, but it's not intuitive. Changing to SLF4J or Log4J may be better if you end up needing control at a a finer level or over multiple classes

The issue is that Loggers are cached using WeakReferences. From the time you call Logger.setLevel() until the Logger is actually used, it may be GC'ed. So, the Logger that logs isn't the Logger you set the level on! This is especially true in frameworks where there is a lot of GC at startup.

The solution is to programatically set the configuration, not the actual Loggers.

String logConfig = ".level=" + java.util.logging.Level.INFO + '\n';
logConfig += "handlers=java.util.logging.ConsoleHandler\n";
// ensure ConsoleHandler does not filter
logConfig += "java.util.logging.ConsoleHandler" + ".level=" + java.util.logging.Level.FINEST + '\n';

//set your custom levels
logConfig += "org.apache.cxf" + ".level=" + java.util.logging.Level.WARNING + "\n";

try {
java.util.logging.LogManager.getLogManager().readConfiguration(new java.io.ByteArrayInputStream(logConfig.getBytes("UTF-8")));
// no need to close ByteArrayInputStream -- it is a no-op
}
catch (IOException ioe) {
System.err.println("cannot fully configure logging");
ioe.printStackTrace();
}

Note there are a few issues with this approach:

  1. You are overwriting the built-in configuration, so you have to set the root handler. If you set -Djava.util.logging.config.file, it will also be overwritten.
  2. Total hack - might not be maintainable or understandable later.
  3. Your config string has to be valid. Note all lines have to end with \n.
  4. Has to be called very early, preferably the first line in main(). If this is not possible, you may also need to iterate all the existing Loggers and update their config using setLevel() too.


Related Topics



Leave a reply



Submit