How can we create a logger?
It seems that we do not create a logger using the configuration. It seems that the logger is automatically created in the code when we invoke:
static Logger logger = Logger.getLogger(ExperimentLog4J.class.getName());
and in the configuration file, we really just configure the logger rather than actually creating it.
Sample program to demonstrate how to use log4j:
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class ExperimentLog4J {
static Logger logger = Logger.getLogger(ExperimentLog4J.class.getName());
public static void main(String[] args) {
logger.info("Yo! This is log4j in action.");
}
}
javac -classpath c:\parsers\log4j\log4j-1.2.14.jar ExperimentLog4J.java
java -classpath ".;c:\parsers\log4j\log4j-1.2.14.jar" ExperimentLog4J
How can we log a message?
static Logger logger = Logger.getLogger(ExperimentLog4J.class.getName());
logger.info("Yo! This is log4j in action.");
The point is that log4j offer appropriate method for each log level. For example, to log a message with the level of INFO, we use logger.info("…"), and to log a message with the level of WARNING, we use logger.warn("…")
How can we obtain a reference to the root logger?
Invoking the class static Logger.getRootLogger method retrieves it.
Logger.getRootLogger
How can we obtain an instance of the logger "com.foo"?
Logger logger = Logger.getLogger("com.foo");
static Logger logger = Logger.getLogger(MyApp.class);
How can we programmatically assign log level to a logger?
logger.setLevel(Level.INFO);
// Normally you do not need to set the level of a logger programmatically.
// This is usually done in configuration files.
How can we log a message with the severity of WARNING?
logger.warn("Low fuel level.");
How can we log a message with the severity of DEBUG?
logger.debug("Starting search for nearest gas station.");
Can different part of your application use different loggers?
Yes. In fact, if we want to, we can get a logger for each package, and each class using the getLogger method mentioned elsewhere on this page. If we want to obtain the logger for the package, we just have to specify the name of the package. If we want to get the logger for the class, we specify the name of the class. If the logger that we want have not been created, Java will create it. This way, each class and each package can have their own logger. The logger for the class is consider as the child logger of the logger for the package.
In the below example, the main application (MyApp) use a logger named "MyApp", but the Bar class used a logger named "Bar". While each class or package can have a separate logger, using separate logger for each class / package maybe overkill.
import com.foo.Bar;
// Import log4j classes.
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
public class MyApp {
// Define a static logger variable so that it references the
// Logger instance named "MyApp".
static Logger logger = Logger.getLogger(MyApp.class);
public static void main(String[] args) {
// Set up a simple configuration that logs on the console.
BasicConfigurator.configure();
logger.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
logger.info("Exiting application.");
}
}
package com.foo;
import org.apache.log4j.Logger;
public class Bar {
static Logger logger = Logger.getLogger(Bar.class);
public void doIt() {
logger.debug("Did it again!");
}
}
MyApp begins by importing log4j related classes. It then defines a static logger variable with the name MyApp which happens to be the fully qualified name of the class. MyApp uses the Bar class defined in the package com.foo.
What does BasicConfigurator.configure() do?
I am not really sure on this, but it supposedly "Set up a simple configuration that logs on the console".
import com.foo.Bar;
// Import log4j classes.
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
public class MyApp {
// Define a static logger variable so that it references the
// Logger instance named "MyApp".
static Logger logger = Logger.getLogger(MyApp.class);
public static void main(String[] args) {
// Set up a simple configuration that logs on the console.
BasicConfigurator.configure();
logger.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
logger.info("Exiting application.");
}
}
So, perhaps, for whatever reason, you want to use log4j, but do not want to create the log4j.properties file, using BasicConfigurator.configure() would allow you to log to the console, suppress the warning message, and at some point later, if you want to get fancy, we can add the log4j.properties file. This method is hardwired to add to the root logger a ConsoleAppender. The output will be formatted using a PatternLayout set to the pattern "%-4r [%t] %-5p %c %x - %m%n".
What happens if we pass an argument to PropertyConfigurator.configure()?
It instructs PropertyConfigurator to parse a configuration file and set up logging accordingly.
import com.foo.Bar;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class MyApp {
static Logger logger = Logger.getLogger(MyApp.class.getName());
public static void main(String[] args) {
// BasicConfigurator replaced with PropertyConfigurator.
PropertyConfigurator.configure(args[0]);
logger.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
logger.info("Exiting application.");
}
}
Here is a sample configuration file that results in identical output as the previous BasicConfigurator based example.
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n