Liquibase/log4j integration

Has anyone dealt with integrating Liquibase into an application that uses log4j instead of java.util.logging? I’m trying to work Liquibase into the startup of a tomcat application that is using log4j to handle it’s logging and I was wondering what my options are to make sure information is logged consistently in the application.  Thanks for any help you can offer.

Look at slf4j.

Ok, so I’ve got Liquibase log messages running through log4j now by including jul-to-slf4j-1.5.6.jar, slf4j-to-log4j12-1.5.6.jar, slf4j-api-1.5.6.jar and log4j-1.2.14.jar in the classpath and adding the line

    LogFactory.getLogger().addHandler(new SLF4JBridgeHandler());

where LogFactory is the liquibase.log.LogFactory class.

The only issue left is that now issues are getting printed to the console twice using different formats.

2009-06-01 15:23:42,581 INFO  [liquibase] : Lock Database Jun 1, 2009 3:23:42 PM liquibase.database.template.JdbcTemplate comment INFO: Lock Database 2009-06-01 15:23:42,586 INFO  [liquibase] : Successfully acquired change log lock Jun 1, 2009 3:23:42 PM liquibase.lock.LockHandler acquireLock INFO: Successfully acquired change log lock

Does anyone with experience with slf4j know why this might be happening?

Figured it out:

    LogFactory.getLogger.setUseParentHandlers(false);

How can I integrate log4j with liquibase 2.0? There is no more addHandler method avaible in Logger interface.

With 2.0, you would need to create a logger extension.  You create a class that extends liquibase.logging.core.AbstractLogger in the liquibase.logging.ext package.  In that class, you override the public int getPriority() method to return a value larger than 1 and any other methods you need to override as well, such as debug/severe/etc. to make the call to log4j. 

I did commit a change to 2.0 trunk for 2.0.1 which makes the print() method protected so overriding is easier.

I had planned to make a log4j extension at liquibase.org/extensions but have not gotten to it yet.

Nathan

I did what Nathan suggest some time ago. I had the problem that Liquibase just couldn’t find my custom implementation. It worked when it was contained in the liquibase.jar but not when it was in my own liquibase-log4j.jar. I had to create a manifest to make it work

Manifest-Version: 1.0
Liquibase-Package: liquibase.logging

I am using a custom classloader so that might have been the problem or not. But if your implementation is not found you should try to add the manifest.

But why doesn’t Liquibase already ship with some additional logging implementations?

liquibase.jar contains the Liquibase and just a simple System.out logger. And then there are optional logger implementations:

  • liquibase-jul.jar
  • liquibase-log4j.jar
  • liquibase-slf4j.jar

Problem solved :wink:

It should have picked up your package in liquibase.logging since it is in the main liquibase MANIFEST.MF.  May be classloader related, may have been fixed since then.

The plan is definitely to have multiple log implementation jars that can be dropped in available on the extension portal.  I just haven’t gotten to them yet.  If you get to one before me, feel free to add it to liquibase.org/extensions

Nathan

From Fixing liquibase logging with SLF4J and Log4J: you can also simply include Matt’s jar, liquibase-slf4j, that does this for you. Then a log4j example goes as follows:


    Make sure you include liquibase-slf4j, or else slf4j won't pick up your log4j config.

Make sure you include liquibase-slf4j, or else slf4j won’t pick up your log4j config.