The JavaDocs for java.util.logging.Level
state:
The levels in descending order are:
SEVERE
(highest value)WARNING
INFO
CONFIG
FINE
FINER
FINEST
(lowest value)
Source
import java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
logger.setLevel(Level.FINER);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
Output
Logging level is: FINER
Jun 11, 2011 9:39:23 PM LoggingLevelsBlunder main
INFO: 0 0
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 1 1
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 2 4
Press any key to continue . . .
Problem statement
My example sets the Level
to FINER
, so I was expecting to see 2 messages for each loop. Instead I see a single message for each loop (the Level.FINE
messages are missing).
Question
What needs changing in order to see the FINE
(, FINER
or FINEST
) output?
Update (solution)
Thanks to Vineet Reynolds' answer, this version works according to my expectation. It displays 3xINFO
messages, & 3xFINE
messages.
import java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
// LOG this level to the log
logger.setLevel(Level.FINER);
ConsoleHandler handler = new ConsoleHandler();
// PUBLISH this level
handler.setLevel(Level.FINER);
logger.addHandler(handler);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
Tried other variants, this can be proper
The Why
java.util.logging has a root logger that defaults to
Level.INFO
, and a ConsoleHandler attached to it that also defaults toLevel.INFO
.FINE
is lower thanINFO
, so fine messages are not displayed by default.Solution 1
Create a logger for your whole application, e.g. from your package name or use
Logger.getGlobal()
, and hook your own ConsoleLogger to it. Then either ask root logger to shut up (to avoid duplicate output of higher level messages), or ask your logger to not forward logs to root.Solution 2
Alternatively, you may lower the root logger's bar.
You can set them by code:
Or with logging configuration file, if you are using it:
By lowering the global level, you may start seeing messages from core libraries, such as from some Swing or JavaFX components. In this case you may set a Filter on the root logger to filter out messages not from your program.
why is my java logging not working
provides a jar file that will help you work out why your logging in not working as expected. It gives you a complete dump of what loggers and handlers have been installed and what levels are set and at which level in the logging hierarchy.
WHY
As mentioned by @Sheepy, the reason why it doesn't work is that
java.util.logging.Logger
has a root logger that defaults toLevel.INFO
, and theConsoleHandler
attached to that root logger also defaults toLevel.INFO
. Therefore, in order to see theFINE
(,FINER
orFINEST
) output, you need to set the default value of the root logger and itsConsoleHandler
toLevel.FINE
as follows:The problem of your Update (solution)
As mentioned by @mins, you will have the messages printed twice on the console for
INFO
and above: first by the anonymous logger, then by its parent, the root logger which also has aConsoleHandler
set toINFO
by default. To disable the root logger, you need to add this line of code:logger.setUseParentHandlers(false);
There are other ways to prevent logs from being processed by default Console handler of the root logger mentioned by @Sheepy, e.g.:
But
Logger.getLogger("").setLevel( Level.OFF );
won't work because it only blocks the message passed directly to the root logger, not the message comes from a child logger. To illustrate how theLogger Hierarchy
works, I draw the following diagram:public void setLevel(Level newLevel)
set the log level specifying which message levels will be logged by this logger. Message levels lower than this value will be discarded. The level value Level.OFF can be used to turn off logging. If the new level is null, it means that this node should inherit its level from its nearest ancestor with a specific (non-null) level value.Loggers only log the message, i.e. they create the log records (or logging requests). They do not publish the messages to the destinations, which is taken care of by the Handlers. Setting the level of a logger, only causes it to create log records matching that level or higher.
You might be using a
ConsoleHandler
(I couldn't infer where your output is System.err or a file, but I would assume that it is the former), which defaults to publishing log records of the levelLevel.INFO
. You will have to configure this handler, to publish log records of levelLevel.FINER
and higher, for the desired outcome.I would recommend reading the Java Logging Overview guide, in order to understand the underlying design. The guide covers the difference between the concept of a Logger and a Handler.
Editing the handler level
1. Using the Configuration file
The java.util.logging properties file (by default, this is the
logging.properties
file inJRE_HOME/lib
) can be modified to change the default level of the ConsoleHandler:2. Creating handlers at runtime
This is not recommended, for it would result in overriding the global configuration. Using this throughout your code base will result in a possibly unmanageable logger configuration.
This solution appears better to me, regarding maintainability and design for change:
Create the logging property file embedding it in the resource project folder, to be included in the jar file:
Load the property file from code: