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:
- 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. - Total hack - might not be maintainable or understandable later.
- Your config string has to be valid. Note all lines have to end with
\n
. - 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 usingsetLevel()
too.
Related Topics
Stop Scheduled Timer When Shutdown Tomcat
"Not Allowed to Load Local Resource: File:///C:....Jpg" Java Ee Tomcat
@Onetomany List<> VS Set<> Difference
Copying Text to the Clipboard Using Java
How to Get Java Logging Output to Appear on a Single Line
Not Implementing All of the Methods of Interface. Is It Possible
Maven. Lambda Expressions Are Not Supported in -Source 1.5
How to Copy Data from File to Postgresql Using Jdbc
How to Loop Over a Class Attributes in Java
Remove Last Character of a Stringbuilder
How to Configure Httponly Cookies in Tomcat/Java Webapps
How to Determine If a Point Is Inside a 2D Convex Polygon
Java:Does Wait() Release Lock from Synchronized Block
How to Properly Do a Background Thread When Using Spring Data and Hibernate