Upgrading log4j properties to log4j2

This article was written to help with upgrading a project built with log4j 1.x to using log4j 2.x, which I was asked to do.

My brief on this task was to upgrade from log4j to log4j2 with minimal changes to the code base.

Because of that brief I just used the same .properties file as was originally in the project (well a renamed file). And this what I learned in the process of making those changes.

Simple(ish) like-for-like change

Rename the default file

If you are using a default file like me, i.e. not setting log4j2.configurationFile, then you need to make sure the file name is log4j2.properties as this is the default name being looked for. See Default file load order below.

Change the properties

If you are like me and just want to see the answers, below is my original file, and the log4j2 translation of that file. However if you want to learn more, look further down.

My original file

# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootCategory=INFO, CONSOLE, RollingAppender

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d %5p %c - %m%n

# Set a Rolling File Appender to create a new file every day
log4j.appender.RollingAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.RollingAppender.File=C:/temp/logs/app.log
log4j.appender.RollingAppender.Threshold=DEBUG
log4j.appender.RollingAppender.encoding=UTF-8
log4j.appender.RollingAppender.DatePattern='.'yyyy-MM-dd
log4j.appender.RollingAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.RollingAppender.layout.ConversionPattern=%d %5p [%c] %m%n

New log4j2 file

# Extra logging related to initialization of Log4j
# Set to debug or trace if log4j initialization is failing
status = warn
# Name of the configuration
name = SampleLogConfig
# location for log files
property.basePath = c:/temp/logs

# Root logger level
rootLogger.level = info
# Root logger referring to console appender
rootLogger.appenderRef.stdout.ref = consoleLogger
# Root logger referring to file appender
rootLogger.appenderRef.dailyrolling.ref = fileLoggerDaily


# Set threshold level for internal components
logger.axis.name = org.apache.axis
logger.axis.level = error

# Console appender configuration
appender.console.type = Console
appender.console.name = consoleLogger
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %5p %c - %m%n

# RollingFileAppender name, pattern, path and rollover policy
appender.dailyrolling.type = RollingFile
appender.dailyrolling.name = fileLoggerDaily
appender.dailyrolling.fileName = ${basePath}/app.log
appender.dailyrolling.filePattern = ${basePath}/app_%d{yyyy-MM-dd}.log
appender.dailyrolling.layout.type = PatternLayout
appender.dailyrolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %5p %c - %m%n
appender.dailyrolling.policies.type = Policies
# Rotate log file each day
appender.dailyrolling.policies.time.type = TimeBasedTriggeringPolicy
# the interval duration in this case is one day
appender.dailyrolling.policies.time.interval = 1
appender.dailyrolling.policies.time.modulate = true
appender.dailyrolling.strategy.type = DefaultRolloverStrategy

Changing from old to new – What I found

The Namespace

First thing I noticed was that the root namespace, i.e. log4j was is longer valid (and yes I did try log4j2). So that needs to be removed.

Before we go to far, I think it is important (or just worthwhile) to understand the namespace that is being used.

As the documentation explains (see my comments below), the configuration is a tree structure and the .properties file is a flat representation of that. So think of every part of the namespace, up to the property name, as a node in the tree structure. For me this helps.

The second part of the new namespace (i.e. CONSOLE, RollingAppender) is just a unique name for the node and is no longer the name and doesn’t even need to match the name. But I guess it’s good practice to make them match though.

Having the namespace on the types (i.e. org.apache.log4j.ConsoleAppender) totally broke my code. But that could also have been because the types themselves have changed, i.e. ConsoleAppender is now just Console.

Properties

Log4j2 seems to be more specific, requiring the name property on the appender (as mentioned above).

A type property is also required on each node, i.e. appender, layout, policy, etc.

Threshold is now an object in it’s own right, rather than just a property. As in my original file.

Troubleshooting

Add the property status = debug (see line 3 in my new file) and run some test method (I just run my unit tests) and you will see all the debugging from log4j. I found this quite helpful.

If there is nothing in the console output (after adding the status property) then we can assume that it is just broken. My guess is remove the namespaces from the types. Else comment out everything but the name and type and build up from there.

Other Examples

A Rolling File Appender based on log file size

Here is another one I created when playing around that will rename the log file when it gets to a certain size.

# RollingFileAppender name, pattern, path and rollover policy
appender.sizerolling.type = RollingFile
appender.sizerolling.name = fileLoggerSize
appender.sizerolling.fileName = ${basePath}/app.log
appender.sizerolling.filePattern = ${basePath}/app_%i.log # %i increments with each new file
appender.sizerolling.layout.type = PatternLayout
appender.sizerolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %level [%t] [%l] - %msg%n
appender.sizerolling.policies.type = Policies
# Rotate log file when it reaches a certian size
appender.sizerolling.policies.size.type = SizeBasedTriggeringPolicy
appender.sizerolling.policies.size.size = 1MB

# Root logger referring to file appender
rootLogger.appenderRef.sizerolling.ref = fileLoggerSize

A Rolling File Appender based on day and log file size

If you want the rolling file daily, but to a maximum file size, then you mix both appenders together, like so…

# Set a Rolling File Appender to create a new file every day
appender.dailyrollingwithsize.type = RollingFile
appender.dailyrollingwithsize.name = fileLoggerDailyWithSize
appender.dailyrollingwithsize.fileName= ${basePath}/app.log
appender.dailyrollingwithsize.filePattern= ${basePath}/app_%d{yyyy-MM-dd}_%i.log # %i increments with each new file
appender.dailyrollingwithsize.layout.type = PatternLayout
appender.dailyrollingwithsize.layout.pattern = %d %5p [%c] %m%n
appender.dailyrollingwithsize.policies.type = Policies
# Rotate log file each day
appender.dailyrollingwithsize.policies.time.type = TimeBasedTriggeringPolicy
appender.dailyrollingwithsize.policies.time.interval = 1
appender.dailyrollingwithsize.policies.time.modulate = true
appender.dailyrollingwithsize.strategy.type = DefaultRolloverStrategy
# Add a size component to the appender
appender.dailyrollingwithsize.policies.size.type = SizeBasedTriggeringPolicy
appender.dailyrollingwithsize.policies.size.size = 1MB

# Root logger referring to file appender
rootLogger.appenderRef.dailyrollingwithsize.ref = fileLoggerDailyWithSize

Further Information from the log4j site

Default file load order

The .properties file is the first default configuration file to be looked for and loaded. By default I mean if the system property log4j2.configurationFile is not set.

As the documentation says, ‘If no system property is set the properties ConfigurationFactory will look for log4j2.properties in the classpath.’ (well it actually looks for test configurations first)

Properties File Structure

Every configuration implementation, such as XML, Yaml, Json, etc. has the primary task of converting the configuration text into the Node tree. It should be noted that while most of the supported document types are inherently tree structured, the Java properties syntax is not. Because of the need to convert the syntax into a Node tree the Java properties syntax used by Log4j required all properties follow a naming pattern that made the tree structure clear. As a consequence, the Java Properties format tends to be more verbose than using a different document type. See manual.

Appender interval property

This is a little confusing, but here goes.

The documentation says ‘How often a rollover should occur based on the most specific time unit in the date pattern. For example, with a date pattern with hours as the most specific item and and increment of 4 rollovers would occur every 4 hours. The default value is 1.’

So what that means is the duration of 1 interval is based on the date format you added in the filePattern (file name), and is like so…

  • app_%d{yyyy}_.log = 1 year
  • app_%d{yyyy-MM-dd}_.log = 1 day
  • app_%d{yyyy-MM-dd-HH}_.log = 1 hour
  • app_%d{yyyy-MM-dd-HH-mm-ss}_.log = 1 second

Leave a Reply

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