Matt RaibleMatt Raible is a Java Champion and Developer Advocate at Okta. developer.okta.com

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

log.debug vs. logger.debug - which do you prefer?

This is probably a bit of a religious debate, but it can't hurt to ask. Do you prefer to use log.debug() or logger.debug() in your Java classes? A fair amount of open source projects use Commons Logging and many of them seem to use logger. Personally, I prefer log (esp. b/c it's shorter), but I'm willing to change based on what the community (particularly AppFuse users) prefer.

Here's another tip I learned today. I typically declare a log variable for each class, such as this one in BaseAction.java:

    protected static Log log = LogFactory.getLog(BaseAction.class);

A better design can be found in Spring's DaoSupport classes. They have a logger variable that all its subclasses can use - eliminating the need to initialize a log variable in each class.

    protected final Log logger = LogFactory.getLog(getClass());

Obviously this is cleaner than AppFuse's current design - so I'll be changing it for 1.6. Any reasons why I shouldn't?

Posted in Java at Aug 16 2004, 09:47:58 PM MDT 21 Comments
Comments:

between log and logger, i choose log, im also currently using protected final Log logger = LogFactory.getLog(getClass()); aswell but i remember reading somewhere that using getClass() for your logger (at least when you use log4j) doesnt also using one or two of the formatters, forgot which ones

Posted by Francisco Hernandez on August 16, 2004 at 10:31 PM MDT #

I use logger and I also use your first example, although now that you described your 2nd example I will use that in the future!

Posted by Pat on August 17, 2004 at 01:30 AM MDT #

I also prefer log over logger.

Posted by Mathias Bogaert on August 17, 2004 at 01:33 AM MDT #

I use log over logger, and the only case I know of where I don't use the second version, is when you have need for logging in static methods and such. I often use protected static final Log log;, but that's mostly out of old habit.

Posted by Pål Brattberg on August 17, 2004 at 02:27 AM MDT #

I prefer log over logger. I also use the second approach where subclasses can use the log from a base class.

Posted by Lars Fischer on August 17, 2004 at 03:39 AM MDT #

I use mLog (all fields are prefixed with m). I used second approch, but now I'm using first approch - Sometimes I'm logging in static methods and in such cases second approch doesn't work.

Posted by lasas on August 17, 2004 at 04:12 AM MDT #

I prefer private _log, not static. The _log instance is injected into my service implementation, and is based on the HiveMind service id, not the class name. In this way, I can easily enable debugging for a specific service, even when multiple instances use the same class. It works well. In fact, I have all the related utility objecs that construct the service use the same log instance ... so when I enable debugging for the foo.bar.Baz service, I get output about it being constructed and initialized, as well as output about method invocations and return values.

Posted by Howard M. Lewis Ship on August 17, 2004 at 04:56 AM MDT #

I use log and prefer to use the first approach. Unless I'm going mad, that's a new Log instance per "owning" class <strong>instance</strong>.

I'm not sure I'd want a new Log instance for each of the objects I instantiate. I'm sure it's lightweight enough, but still another object per object ... <em>nah!</em>

Of course, having said all that, it would depend on the circumstance. I would be tempted to use it in my BaseAction (as they're pseudo-Singletons), but not as a general rule.

Posted by Carl on August 17, 2004 at 04:58 AM MDT #

Carl, if you have classes
  • A
  • B extends A
  • C extends A
where A provides a <code>protected static Logger log = Logger.getLog(A.class);</code> that's shared, then what you'll see in the logs is
2004-08-17 11:11 [mypackage.A] doing X
2004-08-17 11:11 [mypackage.A] doing Y
2004-08-17 11:11 [mypackage.A] doing Z
instead of
2004-08-17 11:11 [mypackage.A] doing X
2004-08-17 11:11 [mypackage.B] doing Y
2004-08-17 11:11 [mypackage.C] doing Z
right? So I'd go for the latter approach even though it'd cost me a few more objects, it's much more clearer. Or do the logging libraries take the class name from somewhere else?

Posted by Santa Claus on August 17, 2004 at 05:23 AM MDT #

I like to use logger as I log info inside struts actions and struts has already a 'log' variable to be deprecated and sometimes it confuses me when I'm coding if I already create a log instance for the class or is the struts variable I'm using. I usually use the first approach.

Posted by Johann Reyes on August 17, 2004 at 05:55 AM MDT #

[Trackback] Thanks to Matt Raible's post on "log.debug vs. logger.debug" I learned another trick in OO Design. It is possible to eliminate the need to initialize a log variable in each class when you insert a statement in the superclass. Before...

Posted by Karsten Voges (Weblog) on August 17, 2004 at 06:44 AM MDT #

You left out an option: C. I use AOP for logging you insensitive clod!

Posted by Keller on August 17, 2004 at 07:14 AM MDT #

Let's say I go with option B. I have class Foo and I have class Bar that subclasses Foo. The Logger is declared in Foo. I instantiate a Bar object. When this executes, all log statements will be logged as "Bar", even the log statements that are contained in the Foo class. To me, this is confusing. I want to look at my log file and know *exactly* what class is logging the message. So, I would vote for A. We use the idiom: <code> private static final Logger LOGGER = Logger.getLogger(Foo.class); </code> A little long, put it's an Eclipse template so I never have to type it :-)

Posted by Ryan Breidenbach on August 17, 2004 at 07:33 AM MDT #

Santa Claus,

My apologies, I didn't take enough notice of the code for option A.

Instead of <code>protected static Log ...</code>, I use <code>private static Log ...</code> (thereby preventing subclasses using the Log instance, and exhibiting the behaviour you describe).

So, I'd go for my version of option A! (but feel okay about option B for things like <code>Action</code>s

Posted by Carl on August 17, 2004 at 07:39 AM MDT #

Keller -- AOP = All Old People? An Other Purpose? Agile Object Project?? ;-)

Santa &amp; All, sometimes you want to do both. The simple reason is sometimes you want to know (via the log) when the base class is performing an operation that is completely independent of the subclasses. If the implementation is in the subclass, you want to know exactly which one and not have all of them tagged with the name of the base class.

I don't know about the earlier comment about log4j not supporting a couple of filters in once case, but that would be good to know. I don't actually use log4j for my logging, but I'd be curious to know why some of the filters wouldn't work.

Posted by gerryg on August 17, 2004 at 09:33 AM MDT #

Well... I was used to use the first approach. But seemed to be a good design to put the static log (in time, I used "log" instead of "logger") in the superclass. I use Log4j and I can confirm that some filters really don't work with the second approach. Since I don't had the time yet do do my homework and test or search wich one works and wich don't, all i get in the console is (Unknown Source)[?:?].

log4j.properties:

log4j.rootCategory=INFO, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%p [%F:%L] - %m%n

Posted by Alexandre Jacques on August 17, 2004 at 12:17 PM MDT #

I like to make the logger transient, too.

Posted by Seth Ladd on August 17, 2004 at 12:20 PM MDT #

I prefer <code>private static final Logger log = Log.getLog(a.class);</code> or <code>private static final Logger _log = Log.getLog(a.class);</code>

Posted by 67.20.182.8 on August 17, 2004 at 08:06 PM MDT #

Option C!

Posted by Atoy on August 17, 2004 at 10:09 PM MDT #

correct me if Im wrong, what if you do
Class A {
  private static class L {
    public static Log log = LogFactory.getLog(A.class);
  }
  void doStuff(){
    try { ... } catch (Exception e){ L.log.error("...");
  }
}
whats new here? a Log instance is only created if you log.

Posted by Jano on August 21, 2004 at 05:24 PM MDT #

Hi, I vote for import org.apache.log4j.Logger; private static final Logger logger = Logger.getLogger(ClassA.class); - don't like protected because I want to delete every possibility to have a ClassB logging as ClassA, - logger is just a taste - static ... to make sure to have only an instance of the logger ClassA

Posted by 212.188.183.94 on August 14, 2008 at 09:44 AM MDT #

Post a Comment:
  • HTML Syntax: Allowed