Logging specific class at FINE while the rest is at WARNING. Possible?

By default the project has its logger set this way (in the main class where everything is started from):



[java] Logger.getLogger("").setLevel(Level.WARNING); //NOI18N[/java]

as I don’t want to be constantly spammed by more or less irrelevant message while working on something in particular.



Right now though I’m working on sector saving and I’d like a FINE granularity for the LeafCache class.



Changing the above to this didn’t let me log anything from LeafCache.

[java] Logger.getLogger("").setLevel(Level.WARNING); //NOI18N

Logger.getLogger(LeafCache.class.getName()).setLevel(Level.ALL);

// nor using “LeafCache” instead of the FQN.

[/java]



After reading a couple of articles I thought I had found the solution by using this inside LeafCache class. (LOGGER is defined as “private final static … etc”):

[java] LOGGER.setUseParentHandlers(false);[/java]



But when I use the following debug lines…

[java]

LOGGER.setUseParentHandlers(false);

System.out.println("Logger at INFO is " + LOGGER.isLoggable(Level.INFO));

System.out.println("Logger at WARNING is " + LOGGER.isLoggable(Level.WARNING));

System.out.println("Logger at SEVERE is " + LOGGER.isLoggable(Level.SEVERE));

[/java]



I get this:

“Logger at INFO is false

Logger at WARNING is true

Logger at SEVERE is true”



So… Is there a way to get FINE logging in a specific class while everything else has a different granularity?



Thanks.

@madjack said:
So... Is there a way to get FINE logging in a specific class while everything else has a different granularity?


There definitely is. It's the entire point to having log levels. Unfortunately, I don't know why what you've tried didn't work. In a proper logging API like log4j then it would have worked without issue, exactly how you've done it. I find the built in JUL logging to be somewhat baffling in this regard as I've also chased my tail a few times trying to figure out why settings weren't properly applied. Every time I figure it out, I rapidly forget again.

I know my post seems pointless but I thought I'd at least offer the hope that there IS a way. You just have to figure out the proper incantations.

Odd question: how are you grabbing the logger from your leaf cache and is it a kept in a static variable or an instance variable?

The LeafCache logger is set like this (the normal way afaik):

[java]

private final static Logger LOGGER = Logger.getLogger(LeafCache.class.getName());

[/java]

then use the LOGGER in that class.

@madjack said:
The LeafCache logger is set like this (the normal way afaik):
[java]
private final static Logger LOGGER = Logger.getLogger(LeafCache.class.getName());
[/java]
then use the LOGGER in that class.


Yeah, I was grasping at straws.

I have gotten per-logger configuration working before... even loaded from a properties file. I do remember something weird about the order I had to do things.

I eventually wrote a simple bridge that dumps JUL logging into log4j and then never looked back. It even transfers the logging configuration so I can just configure it all in log4j. So I can't recall what I did specifically before.

Here you go:



[java]

public static void main(String[] args) {

Handler[] handlers = Logger.getLogger("").getHandlers();

for (Handler handler : handlers) {

handler.setLevel(Level.ALL);

}

Logger.getLogger("").setLevel(Level.WARNING);

Logger.getLogger(“nu”).setLevel(Level.ALL);

Logger.getLogger(“nu”).setUseParentHandlers(true);



// Just to check that it works

Logger.getLogger(“nu.zoom”).fine(“Fine logging on ‘nu.zoom’”);

[/java]



This works for me, I’m not sure that the “useParentHandlers” is needed but better safe than sorry :slight_smile: The “problem” is that the the console-handler, by default, in JUL-logging is set to filter out “fine”-levels.

1 Like

(Rant mode on)

Oh by the way, I know that everyone and his IDE says that loggers should declared static but I think that is bad practice. I use:

[java]private final Logger log = Logger.getLogger(getClass().getName());[/java]



I mean, really, how long time do people think it takes to also allocate a logger if you instantiate the same class several times, a logger that the logging framework almost always is pooling? OTOH I have in the wild fixed several cases of refactored or copy-paste-classes where the logger used the wrong class name which I consider far more annoying than a theoretical extra instance of a logger class. (Rant mode off)

@jmaasing said:
(Rant mode on)
Oh by the way, I know that everyone and his IDE says that loggers should declared static but I think that is bad practice. I use:
[java]private final Logger log = Logger.getLogger(getClass().getName());[/java]

I mean, really, how long time do people think it takes to also allocate a logger if you instantiate the same class several times, a logger that the logging framework almost always is pooling? OTOH I have in the wild fixed several cases of refactored or copy-paste-classes where the logger used the wrong class name which I consider far more annoying than a theoretical extra instance of a logger class. (Rant mode off)


I actually consider this is a bug in the JUL logging which could have easily provided a version of the method that automatically detected the class even from a static context. Though it is pretty trivial to write one.

static is better because logging should minimize footprint just so that it doesn't change the behavior of your program. e.g.: "I added logging and now the bug doesn't happen anymore." Per object instance look ups also makes a LOT of assumptions about usage. If you allocate that object 7000 times and throw it away, I really doubt you want to be looking up a Logger every time... especially since some large percentage of the time it may not even be used.

I think static is the proper idiom. No reason to blame the idiom for what amounts to a broken API.

We have way too many INFO logs in our engine atm, we should add an issue to gc about going through these and putting proper levels etc. Another big candidate for some logging cleanups is nifty cough@void256 :wink:

What i dislike about the current loggers is taht they are not slf4j compatible (there is a adapter, but it needs to cnvert everything from java.util.Logging to slf4j interfaces, even if all logging is disabled, so its suboptimal.)

Damn it Normen! You really should start to see the doctor with your coughing! Are you sure you don’t have a serious Bronchitis or something? It’s really scary, when people cough that loud, you know? :wink:



But, yes I heard you! :wink: And I agree - it’s now on the TODO list issue created on github. Thanks! :wink:

1 Like
@EmpirePhoenix said:
What i dislike about the current loggers is taht they are not slf4j compatible

well thats a slf4j problem, thats the standard java logging system
@EmpirePhoenix said:
What i dislike about the current loggers is taht they are not slf4j compatible (there is a adapter, but it needs to cnvert everything from java.util.Logging to slf4j interfaces, even if all logging is disabled, so its suboptimal.)


Hmmm... the adapter I wrote for log4j examines the log setup when initialized and sets all of the JUL log levels to be the same as the log4j ones. Perhaps the slf4j logger could do the same and then you avoid the issue.

The standard Java logging is the worst logging system I have ever used, hands down. It's like they took the worst features of every logging API out there and threw them together while changing the names to more ridiculous ones. Compared to most of the beauty of the JDK it is an abomination.

slf4j is great.



it’s especially great for libs since it lets the final application decide what kind of logging implementation the application wants to use. So the lib using slf4j can better integrate into existing infrastructure.



“In fact, each SLF4J binding is hardwired at compile time to use one and only one specific logging framework.” ← this is great as well and much better than the commons-logging classpath resolving hell.



I’m a big fan of slf4j. Really! :slight_smile:



.

.

.



I’m just not sure if it is really necessary for libs like jme (or Nifty). It adds yet another dependency while jdk14 is build-in. And in the end it’s really just logging and most of it is probably really unnecessary spam or never seen by anyone at all. So sticking with jdk14 and just use it better would be enough IMHO.



And in the end slfj4 wouldn’t solve madjacks logger configuration problem since the configuration of a specific slf4j impl is done using the specific configuration options of the impl. For instance when using slf4j with “slf4j-jdk14-.jar” you would still need to configure jdk14.



Just my two cents.

Totally agree, actually jme is the only project I ever saw that uses the default java one, all others use log4j or a slf4j compatible binding. But the idea with the loglevels might work.

@normen said:
We have way too many INFO logs in our engine atm, we should add an issue to gc about going through these and putting proper levels etc. Another big candidate for some logging cleanups is nifty *cough@void256* ;)


I agree with that, although Nifty's logging dwarfs jME's by a very long stretch. I consider Nifty's logging spam really. The worst (and I've said it before) is that Nifty will log severe errors instead of crashing. I know crashing with the right message after reflection and all that is going on behind the scene is not trivial, but it doesn't remove the fact that in this instance logging is pretty useless as it takes more time to find the actual problem in the log than to fix it. :/

Anyhow.

---

I read the comments about the other logging systems and I'm wondering, should I switch to one of those? Which one would be the best? I do intend to add logging options to magical classes ;).

@jmaasing
I'll give this a whirl.

Thanks guys.

@madjack i suggest first to take a look at slf4j since it is a general logging api wrapper (wich can use various different logging systmes without much overhead), and then on the implementation logback,since its the successor to log4j. Also logback implements the slf4j interface nativly with no adapter patterns, so it’s extremly efficient. Also it works with any slf4j client , so for exmaple glassfish will automatically pickup the loggers and tie them up to the internall logging system.



http://logback.qos.ch/

1 Like