In this example we shall talk about the
RollingFileAppender, one of the most basic appenders of Log4j.
Log4j a thread-safe and flexible logging library for Java, licensed under the Apache Software Foundation.
The
log4j architecture has three basic components, the
logger, the
appender and the
layout. The
logger is used to log the messages, the
appender publishes the messages to different outputs and
layout is used to format the log messages. All these components are configured in the
log4j.xml file, which is placed in the application
classpath.
A basic appender that is frequently used in log4j is the
RollingFileAppender. It is an
OutputStreamAppender
that writes log messages to files, following a configured triggering
policy about when a rollover should occur, and also following a
configured rollover strategy about how to rollover the file.
Below, we will configure the
RollingFileAppender to log files to a file, making use of its basic configuration parameters and using
Log4j 2
Create the log4j2.xml file
The
log4j2.xml file is placed under the
resources folder of the project. This is where all logging components are configured. The
rootLogger is set here, binded to a logging level and to the appender. The
rootlogger is the logger configured in the
log4j2.xml file, unless there is a custom logger implementation to be used in the application.
The logging levels are (from smaller to greater) :
ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF. When a logging level is set, only messages belonging to this level or greater levels are printed.
Here, we use the
RollingFileAppender to log messages to a file. The basic
RollingFileAppender parameters to configure are described below:
- append : when this field is set to
true, the appender will append new logs to the file, when false ti will clear previous logs and write from the beginning.
- immediateFlush : When set to
true, every log record is immediately flushed to disk, if false, batch flushing is performed, thus improving the logger performance.
- bufferedIO : If set to
true, a buffer is used to write data and when the buffer is full the data is flushed.
- bufferSize : This is the buffer size that will lead to data flush when reached.
- filter : Here, we can define one or more filters to check if the records should be logged or not.
- fileName : The name of the file that the appender writes to. If the file does not exist, it is created.
- filePattern : This is where the pattern of the file is configured.
- layout : This is the layout used to format the log event.
- name : Here the appender name is set.
- policy : The
TriggeringPolicy to perform a rollover. The TriggeringPolicy may be composite, that combines multiple triggering policies and returns true if any of the configured policies return true.
It may be on startup, that causes a rollover if the log file is older
than the current JVM’s start time or it may be size based and time
based, that cause a rollover according to size and time setting
accordingly. The time based triggering policy uses two extra parameters,
interval and modulate, to set how often the rollover will occur and wether it will occur on the interval boundary.
- strategy : The
RolloverStrategy that determines the name and location of the archived file. The default strategy may use the date/time pattern and the filePattern attributes specified on the RollingFileAppender. So, the date/time is replaced by current time in rollover, and if the filePattern has integer counter, the counter is incremented in rollover.
- ignoreExceptions : When set to
true, internal exceptions will be logged and then ignored. When set to false, exceptions will be propagated to the caller, instead, or can also be propagated to a FailoverAppender.
Below, we have focused on configuring the parameters that are related to rollover, so we have set the
strategy and
policy of the
appender, as also the
layout of log events and the
fileName of files. We are using a
SizeBasedTriggeringPolicy, with size set to 1 KB, so we expect the file to rollover when it reaches this size. We are also using a
DefaultRolloverStrategy,
with max number of files equal to 4, so we expect that the files in our
logs folder will reach the max number of 4, and then the oldest ones
will be removed as new ones will be created.
The
layout used for the log events is:
%d{dd/MMM/yyyy HH:mm:ss,SSS} : the date pattern
%c{1} : print the class name
%m : print the message
%n to leave an empty line
The
filePattern is set to
${log-path}/myexample-%d{yyyy-MM-dd}-%i.log, where the
${log-path} is set as a property in the file and sets the initial path of the logs folder, and
%i is the counter that will be automatically incremented in rollover.
log4j2.xml
01 | <?xml version="1.0" encoding="UTF-8"?> |
02 | <Configuration status="DEBUG"> |
04 | <Property name="log-path">C:/logs/</Property> |
07 | <RollingFile name="RollingFile" fileName="${log-path}/myexample.log" |
08 | filePattern="${log-path}/myexample-%d{yyyy-MM-dd}-%i.log" > |
10 | <pattern>%d{dd/MMM/yyyy HH:mm:ss,SSS}- %c{1}: %m%n</pattern> |
13 | <SizeBasedTriggeringPolicy size="1 KB" /> |
15 | <DefaultRolloverStrategy max="4"/> |
19 | <Logger name="root" level="debug" additivity="false"> |
20 | <appender-ref ref="RollingFile" level="debug"/> |
22 | <Root level="debug" additivity="false"> |
23 | <AppenderRef ref="RollingFile"/> |
Create an Example class
Example.java class gets the
rootLogger to log messages to the console. The
logger is stated as a
static field, initialized by the
getLogger(String name) API method of
org.apache.logging.log4j.LogManager.
Example.java class has a
main method, where the user is asked to type a number. The
logger logs messages of different levels, using
info(Object message),
warn(Object message),
debug(Object message),
error( Object message) and
fatal(Object message) API methods.
Example.java:
01 | package com.javacodegeeks.snippets.enterprise.log4jexample; |
03 | import java.io.BufferedReader; |
04 | import java.io.IOException; |
05 | import java.io.InputStreamReader; |
07 | import org.apache.logging.log4j.LogManager; |
08 | import org.apache.logging.log4j.Logger; |
13 | static Logger log = LogManager.getLogger(Example.class.getName()); |
15 | public static void main(String[] args) throws IOException { |
16 | System.out.println("===> Please enter a number:\n===>"); |
17 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); |
18 | int number = Integer.valueOf(br.readLine()); |
19 | log.info("Info : number is " + number); |
20 | log.warn("Warning : number is " + number); |
21 | log.debug("Debug : number is " + number); |
22 | log.error("Error : number is " + number); |
23 | log.fatal("Fatal : number is " + number); |
26 | log.info("Info : You chose a number > 100 "); |
27 | log.warn("Warning : You chose a number > 100 "); |
28 | log.debug("Debug : You chose a number > 100 "); |
29 | log.error("Error : You chose a number > 100 "); |
30 | log.fatal("Fatal : You chose a number > 100 "); |
33 | log.info("Info : You chose a number < 100 "); |
34 | log.warn("Warning : You chose a number < 100 "); |
35 | log.debug("Debug : You chose a number < 100 "); |
36 | log.error("Error : You chose a number < 100 "); |
37 | log.fatal("Fatal : You chose a number < 100 "); |
39 | String numberStr = String.valueOf(number); |
40 | for(int i=0; i<=10; i ++) { |
41 | if(numberStr.contains(String.valueOf(i))) { |
42 | log.info("Info : Your number has the digit " + i); |
43 | log.warn("Warning : Your number has the digit " + i); |
44 | log.debug("Debug : Your number has the digit " + i); |
45 | log.error("Error : Your number has the digit " + i); |
46 | log.fatal("Fatal : Your number has the digit " + i); |
Run the application
Run the application more than once. Since the logging level is set to
DEBUG,
we expect that all logs will be produced and writen in the file. Since
the file size is set to just 1 KB, rollover will occur immediately. You
can change the logging level, and the policy and strategy params in the
configuration file to practice more.