Migration from log4j to slf4j framework with Logback implementation

 

Objective:

To demonstrate the steps to migrate the existing application from log4j to slf4j framework with Logback implementation. Before demonstration, there are several advantages to use logback instead of log4j.

Few of them are as below:

1. Faster implementation-Logback internals have been re-written to perform about ten times faster on certain critical execution paths. Not only are logback components faster, they have a smaller memory footprint as well.
2. XML based configuration
3. Automatic reloading for configuration without server/app restart.
4. FileNamePattern Property , any format can be assigned to archived file.
e.g. filename.1.log, filename.log.1,filename.22122013.log,filename.log.201212013 etc.
5. Automatic file compression of archive files
RollingFileAppender can automatically compress archived log files during rollover. Compression always occurs asynchronously so that even for large log files, your application is not blocked for the duration of the compression.
6. SiftingAppender (used o log based on separate events)
SiftingAppender is an amazingly versatile appender. It can be used to separate (or sift) logging according to any given runtime attribute. For example, SiftingAppender can separate logging events according to user sessions, so that the logs generated by each user go into distinct log files, one log file per user.

To know more about this, please click here.


Prerequisites:

Before proceeding with this migration task, we need to fill below prerequisite for this.

1. A working application with existing log4j logging (any other as commons logging or Java Util Logging)
2. Only below jars are required to implement logback with slf4j framework.

 Required Jars  Maven dependency
 slf4j-api  <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
logback-classic.jar  <dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
</dependency>
 logback-core.jar  <dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.13</version>
</dependency>

3. Some bridge dependencies are also required only incase of any third party component/API(tomcat, websphere or other server logging, SOA logging, velocity etc) is using log4j/commons/java Util logging feature.

Logging slf4j Bridge Jar Maven dependency
log4j  log4j-over-slf4j.jar  <dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.5</version>
</dependency>
 commons-logging  jcl-over-slf4j.jar  <dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.5</version>
</dependency>
Java Util  jul-to-slf4j.jar  <dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.5</version>
</dependency>

 


 

Follow below steps to migrate from log4j to slf4j framework completely for maven based project:


Step-1 Dependency tree check

Run the maven dependency tree for existing project using below command.

command prompt>mvn dependency:tree > tree.txt 

Step-2 Remove/exclude log4j dependency

Remove/exclude log4j dependency from all the pom.xml which are loading log4j.jar. This step will make sure that there is no log4j dependency in existing project.

Step-3 Add bridge dependency (optional)

Add bridge dependency only incase of any third party component is really required else skip step 3. e.g. SOA logging requires some log4j feature therefore need to add log4j-over-slf4j.jar.

Step-4 Logback and slf4j dependency

Add the logback and slf4j dependency with latest version in parent and web project’s pom.xml. To be more consistent, set the version properties for all dependency.

Apply the slf4j.version to dependency.

 

Step-5 Migration app

Now, we need to migrate the code from log4j to slf4j with logback implementation. To do this, there is tool provided by slf4j. You may click here to download. Apply all the migration whatever we have in our code as log4j, common, or java util logging.
Migration jar to launch this app: slf4j-migrator-1.7.5.jar

 

Migration app limitations

There are certain limitations of the logback migration tool, which are mentioned below:

This tool changes only existing import statement and Loggerfactory reference only for other logging also(e.g. commons and Java util) 

 Log4j Existing  Logback Expected Changed
 package some.package;
import org.apache.log4j.Logger;
public MyClass {
Logger logger = Logger.getLogger(MyClass.class);
public void someMethod() {
logger.info(“Hello world”);
}
}
 package some.package;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public MyClass {
Logger logger = LoggerFactory.getLogger(MyClass.class);
public void someMethod() {
logger.info(“Hello world”);
}
}

1 – It won’t make any changes in existing debug statement to incorporate new logback implementation. Manual Intervention is required to do. This will reduce the performance overhead for logging.

 Existing  Expected Changed
 logger.debug(“TransactionId: ” + transactionId);  logger.debug(“TransactionId: {} “, transactionId);

2 – For MDC based changes are also required manual changes. NDC is not supported by slf4j.

3 – There is no support for PropertyConfigurator in slf4j.There is no equivalent to this.

4 – It won’t remove your existing isDebugEnabled check, if require then manually edit them.

5 – There is no FATAL level support in logback but Marker can be used to handle this if required.

For more limitation, please visit this page.


Step-6 RegEx for debug statements

To ease of these manual interventions to remove isDebugEnabled and modify debug statements to parameterized debug statements, I have written some regular expression to replace them with appropriate format for logback.

Please find regEx to change in debug statements below.

Sequence to execute these RegEx would be as below else this won’t work:

  • Debug statement with one/more variable
  • Debug statement with two variable
  • Debug statement with three variable

 

 Debug statement with one/more variable  Debug statement with two variable  Debug statement with three variable
 Sample
Debug
Statement
 logger.debug(“TransactionId: ” +
transactionId);
 logger.debug(“clientId” + clientId + “TransactionId: {}”,
transactionId);
logger.debug(“A” + A + “B {} C {}”, B,C);
 RegEx to
find
 ([a-z|A-Z|_]*)(\.debug)(\(\”)(.*)(\”\s\+){1}(.*)(;$)  ([a-z|A-Z|_]*)(\.debug)(\(\”)(.*)(\”)(\s\+)(.*)(\s\+)(\s+)(\”)(.*)(\,(.*);$)  ([a-z|A-Z|_]*)(\.debug)(\(\”)(.*)(\”)(\s\+)(.*)(
 RegEx to
Replace
 $1$2$3$4\{\}\”\,$6$7  $1$2$3$4 \{\} $11\,$7$12  $1$2$3$4 \{\} $11$12$7\,$13

Please find regEx to remove isDebugEnabled and replace one parameter with debug and error method with logback’s standard below.

 IsDebugEnabled Removal  debug() with one parameter
changed
 error() with one parameter
changed
Sample
Statement
 if (logger.isDebugEnabled()) {
logger.debug(“A :{} “, A);
logger.debug(“B :{}”, B);
}
 logger.debug(e);  logger.error(e);
 RegEx to find  (if\s*\([a-z|A-Z|_]*\.isdebugEnabled\(\)\)\s*\{)((\r\n.*)+)([\r|\n|\s]+\})  ([a-z|A-Z|_]*)(\.debug\()([a-z]+)(\);)  ([a-z|A-Z|_]*)(\.error\()([a-z]+)(\);)
 RegEx to
Replace
 $2  $1$2\”{}\”, $3$4  $1$2\”{}\”, $3$4

 

Step-7 Configuration file

To enable the logback logging, we need to create a logback.xml which is configuration file as log4j.properties/ log4j.xml. There is one online utility where you can transform the existing log4j.properties to logback.xml.

To transform the log4j.properties, please click here

To transform log4j.xml to logback.xml, please follow below table with steps

Line Type Log4j.xml logback.xml Changes
xml
declaration
<?xml version=”1.0″ encoding=”UTF-8″?> <?xml version=”1.0″ encoding=”UTF-8″?> No change
DTD type <!DOCTYPE log4j:configuration PUBLIC “-//APACHE//DTD LOG4J 1.2//EN” “https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd”> NO DTD mentioned remove the
DTD
Configuration <log4j:configuration debug=”false” xmlns:log4j=’https://jakarta.apache.org/log4j/’> <configuration> Remove prefix
and xml
namespaces
(e.g. log4j and
xmlns)
appender <appender name=”FILE” class=”org.apache.log4j.rolling.RollingFileAppender”>
<rollingPolicy class=”org.apache.log4j.rolling.TimeBasedRollingPolicy”>
<param name=”FileNamePattern” value=”#FILE_NAME#”/></rollingPolicy>
<layout class=”org.apache.log4j.PatternLayout”>
<param name=”ConversionPattern” value=”%d [%t] %-5p %c- %m%n”/>
</layout>
</appender>
<appender name=”FILE” class=”ch.qos.logback.core.rolling.RollingFileAppender”><rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”>
<param name=”FileNamePattern”value=”#FILE_NAME#”/></rollingPolicy>
<encoder>
<pattern>[%d{“dd MMM yyyy
HH:mm:ss,SSS”}]-[%t]-%n%m%n</pattern>
</encoder>
</appender>
1. change
appender
class
2. change
pattern
layout
3. introduce
logback
encoder
pattern
logger <category name=”#PACKAGE_PATH#”>
<priority value=”#LOG_LEVEL#”/><appender-ref ref=”#APPENDER#”/></category>
<logger name=”#PACKAGE_PATH#” additivity=”fal
se”
level=”#LOG_LEVEL#”>
<appender-ref ref=”#APPENDER#” />
</logger>
1. change
category
by logger
2. add
additivity
attribute
3. add level
attribute

Step-8 Clean up log4j

After generate the logback.xml, we need to remove the log4j.properties from the configuration.

Step-9 Message format

Change the Pattern layout based on logback guideline and project requirement. We can also incorporate MDC variable into this as sessionId or others.
%d %X{sessionId} %-5level [%logger{32}]: %msg%n

Step-10 Auto refresh configuration (optional)

To enable automatic reloading configuration, require to add below attribute to configuration.

This feature enables the server to scan the file in every 10 minutes to detect the changes and reload them. Having this feature, there is no need to restart the server.

To see the log for detect changes in the file, add debug=”true” attribute in the configuration and restart the server.

 

Step-11 Additional Appender (optional)

To enable automatic archive file compression with RollingAppender, do the following:

Note: <maxIndex> can be upto 20 because logback use OPERATING SYSTEM(OS) native API to rename the file which will cause the performance issue. FIXED_WINDOW_SIZE is already set as 20 inside the logback.

 

To address the maxSize problem, apply below rolling policy.

Step-12 Apply the changes

After completing above steps, need to build and deploy the application into server and test the desired logging file.

Step-13 Log level matrix

Fundamental of logback logger to log specific level information with the conjunction of others.

 level of  effective level q
 request p  TRACE DEBUG  INFO WARN  ERROR  OFF
 TRACE YES NO NO NO NO NO
 DEBUG  YES  YES  NO  NO  NO  NO
 INFO  YES  YES  YES  NO  NO  NO
 WARN  YES  YES  YES  YES  NO  NO
 ERROR  YES  YES  YES  YES  YES  NO

 

 

share or like this post
Share

Leave a Reply

Your email address will not be published. Required fields are marked *

Share