I've been the lead on several large projects now which have used log4j.
On each project there have been between 8 and 15 developers. The current
project has over 1200 Java classes. (I don't have stats for the previous
but they were equivalent in size.) The guidelines I give new developers
state that the declaration for a Logger should be:

    private static final Logger _log =
Logger.getLogger(currentClass.class);

This seems to have worked just fine. You'll notice that because of the
private declaration there is no concern about subclasses sharing a
Logger instance and so preventing discrimination of which class is doing
the logging. Likewise, keeping it static means it can be used from
either a class or instance context. And declaring it final prevents it
from being reassigned elsewhere in the code.

As far as preventing "sloppy" Logger naming, I don't see how there is
much you can do about that but code review. You can't keep someone from
coding to a public API; you have to actively discourage it and then
reinforce by feedback. Maybe I've just been fortunate, but I've only had
a couple instances where something like that was being done. After I
took time to explain to the developer the recommended Logger naming
scheme and the benefits thereof, we fixed the code and it never happened
with that developer again.

In this case, communication, simplicity, and courage seem to have
worked.
:-)

Best regards,
Jim Cakalic

-----Original Message-----
From: Scott Doherty [mailto:sdoherty@;kc.rr.com]
Sent: Wednesday, October 23, 2002 12:58 AM
To: [EMAIL PROTECTED]
Subject: Log4J design question: this.getClass() in super class


Design question about using Log4J in an application's framework. 

 

I wish to leverage Log4j in applications being built at my company. I've
been reading quite a bit and watching this list for awhile now. I would
like your input into architecture and design using Log4j.

 

Logger log = Logger.getLog(myClass.class);

Logger log = Logger.getLog(this.getClass());

 

I'm debating the above choice for logger naming. It is sometimes common
that applications built in my company inherit from an Abstract class for
that application. 

 

For example, if I am writing a Banking Application for my company, an
abstract class called BankingSkeleton might be used. Most of the objects
in this application would inherit from BankingSkeleton. BankingSkeleton
would provide behavior common to all objects in this application.

Public abstract class BankingSkeleton extends Object

{

}

Public abstract class Account extends BankingSkeleton

{

}

public class CheckingAccount extends Account

{

}

 

In the reading material about Log4j, it appears that the standard
approach to provide hierarchical based logging in each of these classes
would be to create a static attribute in each class using the class name
as the category's name. 

 

package com.company.banking;

 

abstract class BankingSkeleton extends Object

{

}

class Account extends BankingSkeleton

{

static Logger log = Logger.getLog(Account.class);

}

class CheckingAccount extends Account

{

static Logger log = Logger.getLog(CheckingAccount.class);

}

 

If I were to log a message from a method in each of these classes, it
would look something like this if displaying the logger in the appender
using %c in the PatternLayout:

631   [main] DEBUG com.company.banking.Account  - A message

1071 [main] DEBUG com.company.banking.CheckingAccount  - A message

 

This is great with the exception of a few things. Many of our projects
are completed by a team of developers with varying experience. Each
developer needs to remember to place the log attribute in their class
instead of inheriting log from its super class. Each developer needs to
properly provide the logger name to honor the hierarchy of the logger
naming, for example, "CheckingAccount.class" instead of "Account.class"
when getting the log. When writing this email, I myself copied the log
attribute from the Account class to the CheckingAccount class and at
first, simply forgot to update the logger name in the Logger.getLog
method. If a developer of a class simply doesn't write any logging and
never creates the log attribute for that class, I can foresee production
support developers who need to get something logged to troubleshoot a
problem might sloppily add code inside a method that obtains a logger
something like the following:

 

class sloppyAccount extends BankingSkeleton

{

            public void aSloppyMethod()

            {

                        Logger.getLog("IDunno").debug("A message");

            }

}

 

Notice that the logger, IDunno,  is no longer in the hierarchy and
becomes less manageable via the Log4j configuration properties. 

1452 [main] DEBUG IDunno  - A message

 

I would like the BankingSkeleton to provide the log attribute to all of
its sub-classes, eliminating the need for each class developer to
concern themselves with getting the correct logger.

 

package com.company.banking;

 

abstract class BankingSkeleton extends Object

{

static Logger log = Logger.getLog(BankingSkeleton.class);

}

class Account extends BankingSkeleton

{

}

class CheckingAccount extends Account

{

}

 

Problem above is that all logging is from the BankingSkeleton logger
which eliminates the logger hierarchy. Modifying to "this.getClass()" in
order to obtain the class name from the object's instance re-instates
the logging name hierarchy and enforces desired logger hierarchy.

 

package com.company.banking;

 

abstract class BankingSkeleton extends Object

{

static Logger log = Logger.getLog(this.getClass());

}

class Account extends BankingSkeleton

{

}

class CheckingAccount extends Account

{

}

 

However, since its static, the last object instantiated changes the
logger for all instances of BankingSkeleton, including all subclasses,
so its now necessary to also make log non-static.

package com.company.banking;

 

abstract class BankingSkeleton extends Object

{

Logger log = Logger.getLog(this.getClass());

}

class Account extends BankingSkeleton

{

}

class CheckingAccount extends Account

{

}

 

Everything is fine, except now I must have an instance of the class to
log. This means I cannot log from a static method to the log as I could
previously. Since log is no longer static, I also have an instance of
log for every instance of every class resulting in additional object
creation and cleanup whereas in the beginning I only had one logger for
each class..or am I wrong about that? Do I actually have a reference to
the same logger for each class since Logger.getLogger(this.getClass())
would return the same object reference for every instance of the same
class? Anything else wrong with this approach? 

 

To solve the lack of logging from my static methods, I contemplated the
following:

 

abstract class BankingSkeleton extends Object

{

Logger log = Logger.getLog(this.getClass());

static Logger staticLog = Logger.getLog(BankingSkeleton.class);

}

 

Now when a developer needs to log from a static method from one of the
sub-classes, they call staticLog instead.

 

Your thoughts and experience for integrating Log4j into application's
framework would be greatly appreciated.

 

 



<font size="1">Confidentiality Warning:  This e-mail contains information intended 
only for the use of the individual or entity named above.  If the reader of this 
e-mail is not the intended recipient or the employee or agent responsible for 
delivering it to the intended recipient, any dissemination, publication or copying of 
this e-mail is strictly prohibited. The sender does not accept any responsibility for 
any loss, disruption or damage to your data or computer system that may occur while 
using data contained in, or transmitted with, this e-mail.   If you have received this 
e-mail in error, please immediately notify us by return e-mail.  Thank you.


--
To unsubscribe, e-mail:   <mailto:log4j-user-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:log4j-user-help@;jakarta.apache.org>

Reply via email to