I have the following issue: I want to use the java.util.logging.Logger
. No I found different resources 1,2,3, how one can modify the behavior of the logger.
Especially in the question of 2 a (in my opinion) good structure is given to initialize the loggers according to the class name. This also allows to modify verbosity on a package based level for debugging if needed.
After a bit of digging into the problem I found out, that the global logger and the "empty" logger (with name ""
) are not the same. See also the example below.
I just created a logger foo.Bar
, which is anchored at the empty logger instead of the logger called foo
.
Only if I first create the logger bar
, the logger bar.Baz
is anchored to it correctly.
This makes the approach in this question mainly useless as one cannot assume the parent loggers to be created before. One has to parse the class name and create loggers as needed, as far as I see.
Am I correct that I have to add some static {...}
code to initialize the loggers in a recursive way before the own logger can be initialized?
Does this have any negative effect if multiple classes call the Logger.getLogger(String)
method for the package loggers (resulting in multiple calls overall, e.g both bar.Baz
and bar.FooBaz
get the logger bar
)?
import java.util.Enumeration;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class TestLogger
{
public static void main(String[] args)
{
// Create the logger directly
Logger.getLogger("foo.Bar");
// Create the logger objects step-by-step
Logger.getLogger("bar");
Logger.getLogger("bar.Baz");
// Put the available loggers to output
Enumeration<String> e = LogManager.getLogManager().getLoggerNames();
while(e.hasMoreElements())
{
String s = e.nextElement();
Logger l = Logger.getLogger(s);
String p = (l.getParent() == null ? "none" : "'" + l.getParent().getName() + "'");
System.out.println("'" + s + "': " + p);
}
}
}
The output of the program is
'bar': ''
'global': ''
'foo.bar': ''
'bar.baz': 'bar'
'': none
java.utils.Logger
s can be tricky. Although I don't fully understand what the actual question is here, a (probably) important side note: Loggers can be garbage collected. When you writeLogger.getLogger("foo").setLevel(x)
in yourmain
method, and then obtain a logger withLogger.getLogger("foo")
somewhere else, it may be a different instance! The logger that you obtained in themain
may already have been garbage collected, and the secondgetLogger("foo")
call will then create a new instance. – Kellam