Published on JAVA exPress
        (http://www.javaexpress.pl)
      Sooner or later every Java programmer realizes that using System.out.print     is neither effective nor efficient way of checking the current state of an     application or the value of a variable. Of course, it is true that standard     output is simple and apparently fast. But what if we want to have our traces     written to a file instead of the console? Then, we would have to manually     replace all the commands with the code. That is great, but what if need to     change it again and use the console? Whoa.. it would require a lot of avoidable     work. Can it be made simplier? Well, the answer for this question is really     simple: Log4j! It is an     multi-platform library written in Java by Ceki Gülcü and its     beginnigs date back to the last century (no fear! I mean the '90s :) The     library provides a way of logging in Java applications. Currently, it is     supported by Apache foundation and a part of the Jakarta     project. There are currently three versions available: 1.2 which is supposed     to be the stable one, 1.3 whose development was abbandoned for some reasons     and 2.0 which is, let's say, experimental version.
The first and obvious thing is the tracing of the application flow. We can write current values of variables or objects and various messages about errors or inform about business events that took place while application is running.
Well, it all depends on our imagination. To start with the real basics, there are three types of objects:
Loggers,
Appenders,
Layouts.
Loggers are provided with methods that create logs and set the proper priorities. The places where the logs can be sent are configured using Appenders. The form of the output messages is defined by Layout objects.
There are three types of Loggers:
NOPLogger,
RootCategory,
RootLogger.
The most important one is RootLogger and I will use it in the     following examples. The other two one can be omitted - RootCategory     is considered as obsolete and NOPLogger stands for "No-operation logger".
As it regards log levels, the following levels can be distinguished:
FATAL: Severe errors that cause premature termination of an application;
ERROR: Execution errors;
WARN: The usage of obsolete components or unexpected conditions that do not crash of the application;
INFO: Level used to trace program execution;
DEBUG: More detailed information about program execution and stated, used for diagnostic purposes;
TRACE: The most detailed log level;
ALL / OFF: All levels / turn off logging.
When we choose a certain log level we should keep in mind that all log messages with lower level will not be printed. For instance, if we set log level to DEBUG (the default one), then all logs with TRACE level will never be visible.
In comparison to Loggers, there are numerous types of Appenders.     Moreover everyone can create their own using AppenderSkeleton class.     Here are the most interesting Appenders:
ConsoleAppender simply prints logs messages to the console. By      default it works as System.out. , but it can also function as     System.Err.
WriterAppender prints logs to a file using Writer     class or OutputStream.
JDBCAppender allows to store log messages in a database.
LF5Appender stores log messages in a Swing-based console.
SMTPAppender sends an e-mail when a specific logging event occurs.
DailyRollingFileAppender is an extension of FileAppender     class. Its underlying file is rolled over at a user chosen frequency. Besides     that, it allows to divide messages into years, months, days, etc.
Assuming that you have chosen Appender that suits your needs, it is time to configure what should be printed into logs. It is done by Layouts:
HTMLLayout produces HTML tables.
PatternLayout defines a pattern of a message.
SimpleLayout causes logs to be written in a form: level - message.
XMLLayout sets XML as target format.
DateLayout simplifies time adjustments that is put in logs.
According to my experience and other users’ opinions PatternLayout and     HTMLLayout are the most popular Layouts.
If we decide to use PatternLayout, then we can define what a     message should look like. How to do that? We define a kind of template in     which we use following elements:
%% - single % character
%c - event category
%C - the name of a class that triggered an event
%d - the date when it happened
%m - message
%n - line separator
%p - event level
%r - number of miliseconds since the application was started
%t - name of a thread that sent the message
%x - diagnostic context that is bound to a thread
%M - method name
%L - line number where an event occured
%F - file name where log message was printed
%l - location that sent log message
It is advised not to overuse the last four elements, since they slow down an application.
The last thing to describe is configuration. It can be done in three different ways:
by using BasicConfigurator object,
by using .properties file,
by using XML configuration file.
BasicConfigurator should be used only if we want configure logs     creation. It is the simplest way. It causes creation of PatternLayout     object whose ConversionPattern property has the following value:
%-4r [%t] %-5p %c %x - %m%n
BasicConfigurator class has only three methods:     configure(), configure(Appender) and     resetConfiguration().
Configuration applied by .properties file is similiar to the configuration that uses XML file, however the syntax is different. This is the sample code that is invoked from static method main:
    BasicConfigurator.configure();
    Logger logger = Logger.getRootLogger();
    logger.debug("Hello world");
The result is:
    2 [main] DEBUG root  - Hello world
This log message is quite easy to understand, because we are using the default pattern I have already mentioned a few lines earlier.
It is easy to define our own pattern, for example:
    Layout lay1 = new PatternLayout("[%p] %c - %m - Data wpisu: %d %n");
    Appender app1 = new ConsoleAppender(lay1);
    BasicConfigurator.configure(app1);
    Logger logger = Logger.getRootLogger();
    logger.debug("Hello world");
The result you would get is:
    [DEBUG] root - Hello world - Data wpisu: 2009-11-24 15:20:29,049
Why does it look like? Again, it's very simple: we declare a pattern and an     appender whose purpose is to print logs to the console. Next, the appender is     passed as a parameter to the configure() function and that is all.
OK, what to do if we need to change logging level?
There is no problem with this - we should add the following line:
    logger.setLevel(Level.TRACE);
Or we want to redirect logging messages to a file?
Then the line with appender construction (Appender app1 = new ConsoleAppender(lay1);)     should be, for instance, replaced with this code:
    Appender app1 = null;
    try {
            app1 = new FileAppender(lay1,"C:/log_express.txt");
    } catch(IOException ex) {
    }
As I have mentioned earlier configuration may also be applied in .properties or XML file. They both work according to the same principle: we put a file called log4j.properties or log4j.xml in a custom package (If you choose the default package, the system will automatically find the configuration file).
The sample content of .properties file:
    log4j.appender.C=org.apache.log4j.ConsoleAppender
    log4j.appender.C.layout=org.apache.log4j.PatternLayout
    log4j.appender.C.layout.ConversionPattern=[%p] %c - %m - Data wpisu: %d %n
    log4j.rootLogger=DEBUG, C
The sample content of XML file:
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
      <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out"/>
        <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="[%p] %c - %m - Data wpisu: %d %n"/>
        </layout>
      </appender>
      <root>
        <priority value ="debug" />
        <appender-ref ref="console" />
      </root>
    </log4j:configuration>
In both cases configuration is the same. The difference is only in a way it is expressed. You decide which should be used.
It is worth to mention that if we do not apply Log4j configuration, there would be a warning and the logs will not be displayed.
It can be done in a following way:
download .zip archive: http://apache.privatejetscharter.net/logging/log4j/1.2.15/apache-log4j-1.2.15.zip,
extract log4j-1.2.15.jar file,
create a new library using tabs Tools -> Library,
add the library to your project,
use appropriate imports, e.g. import org.apache.log4j.*;.
I have heard opinions saying that "But there is something called Java Logging API which supported by SUN Microsystems"
It's true. Nevertheless, it does not mean that something is better just because it is considered as a standard. Java Logging API was introduced later than Log4j and is partially based on it. Although there are not many differences between these two libraries, there is a popular belief amongst Java developers that everything possible with Java Logging API is also possible with Log4j. And even more... I have put the advantages and disadvantages in the table below:
| 
             Log4j  | 
            
             Java Logging API  | 
        
| 
             + Supported by Apache Longer on the market Used by a great number of programmers - Rarely updated  | 
            
             + Supported by SUN It does not require any extra libraries - Supported by relatively small number of developers  | 
        
Besides the obvious advantages, the common drawback is the fact if the logs are very big, you may have problems with spotting the most relevant information. This phenomenon has even its name - it is called scrolling-blindness.
The potential offered by Log4j is huge. It is simple is usage     and what is important - it is open source. It was optimalized in order to     achieve the best performance. Also, it solves related to multi-threading.     Intelligent usage of log messages considerably contributes to software     development. In the next issue I am going to publish a few more sample     pieces of code that show how effectively and impressively use Log4j     in various types of applications. Please remember: no more System.out.print :)
Source: http://www.javaexpress.pl/article/show/Effective_logging_with_Log4J