Thursday, February 3, 2011

Logging per application in ServiceMix 4

A common requirement is to have an individual log file for each application that is running under a container.
In ServiceMix by default the log messages go to a shared log file (servicemix.log). It is possible to split the log files by bundle using the Sift appender, but if multiple applications share the same bundle you have a shared log file again. Also, the log messages for a single application get spread among all of the bundles used by the application, which makes it difficult to track down issues.
The Sift appender uses a key in order to separate the log messages into different log files. The available keys are bundle.id, bundle.name and bundle.version. In order to make the appender work at the application level, you need to define you own key by using the following call when you first start the application's main bundle:
    MDC.put("app.name", "myapp");
Please note that MDC is currently only supported by log4j and slf4j.
You need to use the above call in all of your applications in order to define the "app.name" key consistently.
In order to take advantage of the new key you need to make the following changes in
<SMX HOME>/etc/org.ops4j.pax.logging.cfg:
  • log4j.rootLogger=DEBUG, sift, osgi:VmLogAppender
  • log4j.appender.sift.key=app.name
  • log4j.appender.sift.appender.file=${karaf.data}/log/$\\{app.name\\}.log
After restarting ServiceMix and redeploying the applications you should see the log messages separated into separate log files based on the application name.

Limitation with asynchronous flows
MDC uses internally an InheritableThreadLocal context to manage key/value pairs. This implies that when a flow is moved among different threads (for instance, with asynchronous flows), MDC attributes are not propagated by default. ServiceMix and Camel propagate those attributes that they know about, but not our project-specific MDC attributes. This is an area where we will likely see improvements in ServiceMix in the near future.