Search code examples
apache-karafapache-servicemix

Different log level for different Karaf Bundles


In Karaf 3.0.5 running under Servicemix 6.1.0 my org.ops4j.pax.logging.cfg looks like below:-

# Root logger
log4j.rootLogger=DEBUG, async, osgi:*
log4j.throwableRenderer=org.apache.log4j.OsgiThrowableRenderer

# To avoid flooding the log when using DEBUG level on an ssh connection and doing log:tail
log4j.logger.org.apache.sshd.server.channel.ChannelSession = INFO

# CONSOLE appender not used by default
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %X | %m%n

# File appender
log4j.appender.out=org.apache.log4j.RollingFileAppender
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %X | %m%n
log4j.appender.out.file=/tmp/servicemix.log
log4j.appender.out.append=true
log4j.appender.out.maxFileSize=1024MB
log4j.appender.out.maxBackupIndex=10

# Sift appender
log4j.appender.sift=org.apache.log4j.sift.MDCSiftingAppender
log4j.appender.sift.key=bundle.name
log4j.appender.sift.default=servicemix
log4j.appender.sift.appender=org.apache.log4j.FileAppender
log4j.appender.sift.appender.layout=org.apache.log4j.PatternLayout
log4j.appender.sift.appender.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X | %m%n
log4j.appender.sift.appender.file=/tmp/$\\{bundle.name\\}.log
log4j.appender.sift.appender.append=true

# Async appender
log4j.appender.async=org.apache.log4j.AsyncAppender
log4j.appender.async.appenders=out

Now this logger config is dumping Karaf's debug log as well whereas my intention is to DEBUG only a specific bundle.

Can some one let me know if it is possible to set different log levels for different bundles? What I am trying to ask is let's say I have two bundles bundle1 and bundle2. I want bundle1 log level to be DEBUG and bundle2 log level to ERROR. Is this possible to do so?


Solution

  • As discussed in karaf mailing-list since I was using different logger for different bundle. So just setting the log level (as shown below) for bundle level logger in org.ops4j.pax.logging.cfg solved it for me.

    log4j.logger.com.j1.bundle1 = DEBUG
    

    One more solution was suggested in the above mentioned thread. I did not try it but just quoting it below:-

    You can do this by using MDC combined with filters (I implemented that in Pax logging a few years back).

    E g if you use this root logger:

    log4j.rootLogger=INFO, stdout, info, error, bundle, context, osgi:*

    And you define the "bundle" log as follows:

    log4j.appender.bundle=org.apache.log4j.sift.MDCSiftingAppender log4j.appender.bundle.key=bundle.name log4j.appender.bundle.default=karaf log4j.appender.bundle.appender=org.apache.log4j.RollingFileAppender log4j.appender.bundle.appender.MaxFileSize=1MB log4j.appender.bundle.appender.MaxBackupIndex=2 log4j.appender.bundle.appender.layout=org.apache.log4j.PatternLayout log4j.appender.bundle.appender.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n log4j.appender.bundle.appender.file=${logdir}/bundles/$\{bundle.name\}.log log4j.appender.bundle.appender.append=true log4j.appender.bundle.threshold=INFO

    You will end up with a separate log file per bundle (named with the bundle's name). I use a custom variable (${logdir}) to specify where to create the log file but you can do as you wish. In this case these log files will be at INFO level.

    Sometimes I want TRACE logging on a specific bundle. I can then do as follows:

    log4j.rootLogger=TRACE, stdout, info, error, bundle, context, osgi:*, bundle_trace

    log4j.appender.bundle_trace=org.apache.log4j.sift.MDCSiftingAppender log4j.appender.bundle_trace.key=bundle.name log4j.appender.bundle_trace.default=karaf log4j.appender.bundle_trace.appender=org.apache.log4j.RollingFileAppender log4j.appender.bundle_trace.appender.MaxFileSize=10MB log4j.appender.bundle_trace.appender.MaxBackupIndex=2 log4j.appender.bundle_trace.appender.layout=org.apache.log4j.PatternLayout log4j.appender.bundle_trace.appender.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n log4j.appender.bundle_trace.appender.file=${logdir}/bundles/trace/$\{bundle.name\}.log log4j.appender.bundle_trace.appender.append=true log4j.appender.bundle_trace.threshold=TRACE log4j.appender.bundle_trace.filter.a=org.apache.log4j.filter.MDCMatchFilter log4j.appender.bundle_trace.filter.a.exactMatch=false log4j.appender.bundle_trace.filter.a.keyToMatch=bundle.name log4j.appender.bundle_trace.filter.a.valueToMatch=org.apache.aries.blueprint.core log4j.appender.bundle_trace.filter.z=org.apache.log4j.varia.DenyAllFilter

    In the above example I create a separate TRACE log for the bundle with the name "org.apache.aries.blueprint.core".

    It is also possible to configure custom logging for a particular camel context which we do in our integration platform based on Karaf and Camel. Also one thing to note DenyAllFilter should be the last filer in the above config.