Logging

Logging in Omneity will use the approach described in no gunner's blog, which is summarised here.

Logging calls will use the SLF4J facade.

A LogbackConnector bundle is provided. This contains a simple LogBackendActivator class that registers a LogListener (LogbackAdaptor) that passed logged events reported by any active logging services through to Logback.

To intercept the SLF4J calls, a JAR containing a StaticLogBinder is provided by the slf4j-osgi library project. This JAR is included in any bundle that needs access to logging (so pretty much all of them).

This is a general purpose approach, not specific to Omneity.

Build
The components can be rebuilt from source using Maven: ITSLM osgi logging.

Important: this is a forked version of no gunner's original code. The fork updates the code to version 1.6.6 of SLF4J. Updated OSGi core/compendium referenced. For these reasons the JAR filename is different, as are the maven groupId and artifactId, to avoid any future version collision. I would have pushed this back to the originating source, but given that it was so out of date I suspect there is little interest in maintaining it.

The com.itslm.slf4j-osgi-XXXX.jar is built using the slf4j-osgi subproject.

cd slf4j-osgi mvn clean install

The LogbackConnector is built using the LogbackConnector subproject.

Important: this is a forked version of no gunner's original code. The fork updates the code to version 1.0.6 of Logback. Updated OSGi core/compendium referenced. For these reasons the JAR filename is different, as are the maven groupId and artifactId, to avoid any future version collision. I would have pushed this back to the originating source, but given that it was so out of date I suspect there is little interest in maintaining it.

cd LogbackConnector mvn clean install

Installation
Put the in your OSGi framework's bundle directory (in Felix this is, unsurprisingly, the bundle directory).

You will also need the following bundles installed to your framework.

Use
Include slf4j-osgi-XXXX.jar and slf4j-1.6.6.jar in every bundle the needs access to logging.

In the start method of the bundle's Activator, include the following line.

Everywhere else in your code you access the Logger as your normally would using SLF4J.

import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... private static final Logger logger = LoggerFactory.getLogger(SomeClass.class); ... logger.debug("Oh no!"); logger.info("And so on...");

Warning
Actually, more of an 'in development' note.

The current arrangement requires that both slf4j-osgi-XXXX.jar and slf4j-1.6.6.jar in each bundle (as described in no gunner's blog). This is because of a classpath issue with how StaticLoggerBinder is resolved.

slf4j-1.6.6.jar is also required as a bundle in order to satisfy the wiring on the logback-classic bundle. This means that, if another bundle also relies on slf4j-1.6.6.jar it will resolve against it directly, bypassing the log service redirect and causing potential class loading issues (the underlying SLF4J logger may not be properly configured when the requesting bundle tries to create a Logger, causing a warning that the Logger will not work because a default null logger is supplied by SLF4J under these circumstance).

I'm not sure what the solution to that problem will be though. :( I guess it would mean bundling slf4j-1.6.6.jar with logback-classic, exporting logback-classic while keeping slf4j-1.6.6.jar Package-Private and creating slf4j-osgi-XXXX.jar as a bundle to provide the interception of all slf4j calls?