Log4j Hello World with Maven..

Logger hierarchy, sort of..

Directory Layout

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/maven-v4_0_0.xsd">
 
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>biz.tugay</groupId>
    <artifactId>log4pro</artifactId>
    <packaging>war</packaging>
 
    <version>1.0-SNAPSHOT</version>
 
    <name>log4pro</name>
    <url>http://www.tugay.biz</url>
 
    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
 
    <build>
        <finalName>log4pro</finalName>
    </build>
 
    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
</project>

log4j.properties
# suppress inspection "UnusedProperty" for whole file
 
# logger level configurations
log4j.rootLogger=WARN, console
log4j.logger.biz.tugay.log4pro.FooBar=INFO
 
# configuration for console outputs
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.conversionPattern=[%t] %-5p %c - %m%n

FooBar.java
package biz.tugay.log4pro;
 
import org.apache.log4j.Logger;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 12/8/2016
 * Time: 18:07 PM
 */
public class FooBar {
 
    final Logger logger = Logger.getLogger(FooBar.class);
 
    public FooBar() {
        logger.info("FooBar object created!");
    }
}

TestClass.java
package biz.tugay.log4pro;
 
import org.apache.log4j.Logger;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 12/8/2016
 * Time: 18:09 PM
 */
public class TestClass {
 
    final static Logger logger = Logger.getLogger(TestClass.class);
 
    public static void main(String[] args) {
        logger.warn("This will be printed!");
        logger.info("This will not be printed!");
        new FooBar();
    }
}

Here is the output..
[main] WARN  biz.tugay.log4pro.TestClass - This will be printed!
[main] INFO  biz.tugay.log4pro.FooBar - FooBar object created!

Summary of Notes from Log4j notes

Loggers are named entities. Logger names are case-sensitive.

The root logger resides at the top of the logger hierarchy. It is exceptional in two ways:
  • it always exists,
  • it cannot be retrieved by name.

Invoking the class static Logger.getRootLogger method retrieves it. All other loggers are instantiated and retrieved with the class static Logger.getLogger method.

Loggers may be assigned levels. The set of possible levels, that is:
  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL

If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level.

By definition, the printing method determines the level of a logging request. For example, if c is a logger instance, then the statement c.info("..") is a logging request of level INFO.

A logging request is said to be enabled if its level is higher than or equal to the level of its logger. Otherwise, the request is said to be disabled.

Calling the getLogger method with the same name will always return a reference to the exact same logger object.

Thus, it is possible to configure a logger and then to retrieve the same instance somewhere else in the code without passing around references.

Configuration of the log4j environment is typically done at application initialization. The preferred way is by reading a configuration file.

Log4j makes it easy to name loggers by software component. This can be accomplished by statically instantiating a logger in each class, with the logger name equal to the fully qualified name of the class. This is a useful and straightforward method of defining loggers. As the log output bears the name of the generating logger, this naming strategy makes it easy to identify the origin of a log message.

In log4j speak, an output destination is called an appender. More than one appender can be attached to a logger.

Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy. In other words, appenders are inherited additively from the logger hierarchy. For example, if a console appender is added to the root logger, then all enabled logging requests will at least print on the console. If in addition a file appender is added to a logger, say C, then enabled logging requests for C and C's children will print on a file and on the console.

More often than not, users wish to customize not only the output destination but also the output format. This is accomplished by associating a layout with an appender. The layout is responsible for formatting the logging request according to the user's wishes, whereas an appender takes care of sending the formatted output to its destination.

The PatternLayout, part of the standard log4j distribution, lets the user specify the output format according to conversion patterns similar to the C language printf function.
For example, the PatternLayout with the conversion pattern "%r [%t] %-5p %c - %m%n" will output something akin to:
176 [main] INFO  org.foo.Bar - Located nearest gas station.