mardi 3 mai 2011

Log4j : Customize LoggingEvent for SMTPAppender


Recently I was confronted to the need of customizing the log4j message generation. When an exception occurs, the application should sent the email to the development team in the following format:

The error message should be enclosed by the corporation information represented by the header and footer. The problem is the application URL (marked by the red ellipse). This URL can be different depending on the environment where the application is running and throwing the exception. In the complex, industrial projects where exist many environments, this can be very helpful to determine which environment has a problem.

First of all, how set the footer and header? It’s quite simple, you have to use org.apache.log4j.EnhancedPatternLayout, in the parameter ConversionPattern, you put the header, footer and the message error with some additional information (date, class name which generated the exception, etc). The standard log4j distribution(log4j.jar file) does not contain the class EnhancedPatternLayout, you have to download the additional extras companion (here)

Pay particular attention to do not use org.apache.log4j.PatternLayout which contains some issues with synchronization (see the first paragraphe of the associated JavaDoc). PatternLayout class is still widely used and all exemples on Internet use it, but for make your code robust you don’t have to use it.

And what about the environment dependent URL ? How can I put the or in the log message? I found 2 solutions:
  1. Use ant or maven to replace a specific symbol in your log4j.xml ( when you are building the app. You can use filter resource maven plugin fot that. But is not the most elegant solution, because you will have a strong dependency with the build tool. For production system, it is not a choice.
  2. Use org.apache.log4j.EnhancedPatternLayout and %properties{key} mechanism
So first of all, you have to customize the SMTPAppender in order to put the specific information into the each message that will be sent. For that you have to subclass SMTPAppender and override the method append. Take a look on my test implementation:

The code is self documented. I put the URL to prod environment behind the key named "app".I hardcoded the value in order to make the explanation simpler. But in your production code you may get the correposnding value from properties file, from environment variable or from the database.

Next, the key “app” in the event property becomes available for Log4J runtime. You may see how I use it in my log4j.xml file (the 2nd screenshot).

The setProperty method is an extension point and the excellent example of a good designed API.

Updated : actually, there is a simpler method to inject the environment name into the log4j logging message - simply, change the ConversionPattern for each log4.propeperties file.

Aucun commentaire: