org.apache.felix.logback-1.0.0
Copy releases to tags to have github pick up on them.

git-svn-id: https://svn.apache.org/repos/asf/felix/tags/org.apache.felix.logback-1.0.0@1874473 13f79535-47bb-0310-9956-ffa450edef68
tree: 2e71d3f986737026d90e8a1fec854ce6233885a3
  1. DEPENDENCIES
  2. LICENSE
  3. NOTICE
  4. README.md
  5. pom.xml
  6. src/
README.md

Apache Felix Logback

Apache Felix Logback is a small integration of the Logback backend with OSGi.

With OSGi R7 the Log Service Specification 1.4 (Log 1.4) brings a slew of new features designed to improve the developer experience with logging, the details of which can be read about here.

This project is intended to help bridge the last frontier of OSGi logging by leveraging many capabilities of Logback, the new Log 1.4 features to provide a unified backend where:

  1. all logging is configured in one place
  2. all log records are appended together (or at least all appenders are setup in one place)
  3. support as many logging APIs as possible

The LICENSE is of course Apache License Version 2.0.

Depedencies

First, to add Logback to an OSGi framework include the following dependencies

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.2.x</version>
</dependency>
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-core</artifactId>
	<version>1.2.x</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.x</version>
</dependency>

These provide the slf4j logging API over the Logback backend.

Basic Configuration

Configuring logback is most easily handled by setting the system property logback.configurationFile to point to a file on the file system.

This is an example using a bndrun file:

-runproperties: logback.configurationFile=file:${.}/logback.xml

where in bnd ${.} gives the path to the directory of the bndrun file.

Logback offers many features from it's configuration file, so make sure to look through the documentation.

Deployment Options

There are at least two possible deployment scenarios.

The Standard Approach

The standard approach is to install all bundles into the OSGi runtime.

pros:

  • this is the most understood and expected deployment scenario
  • bundles are managed through any OSGi management agent

cons:

  • due to the fact that logging APIs are most comonly static there is an inevitable race condition which is exacerbated by aspects such as:
    • the order in which the bundles are started
    • which bundle makes the first call the static API that most-likely has the side effect of binding an implementation
    • it's not possible to ensure that all log records are temporaly recieved when they are made which means that some form of queue* is required to temporarily store records until the log engine is ready or, as in the vast majority of cases, simply fail outright.

[^*]: (In the case of the OSGi Log Service this is handled by implementations that support Log 1.4, or perhaps earlier through proprietary means. Most logging frameworks simply do not support this type of feature.)

The RunPath Approach

The runpath approach is intended overcome the cons of the standard approach; to initialize the log engine and allow APIs to bind to implementations as early as possible in order to capture all records without resorting to a queues, being worried about binding issues, or having to be concerned with missed logs due to start ordering.

pros:

  • there's very little chance to miss any log records
  • there are no temporal issues for binding or bundle start order since the log engine is setup before most other application activities take place

cons:

  • bundles on the runpath are not installed into the framework and so they cannot be managed through regular means. On the other hand, logging is one of those infrastructural aspects that trancends the application and for which there are very few scenarios under which one would want to manage logging API or implementation bundles this way. Configuration? Sure!

Unified Backend

Of course adding Logback does not magically result in all logs being funnelled into the same appenders, particularly the OSGi logs. However, it is quite common to assemble an OSGi application from a variety of bundles which use a variety of logging APIs. Many of these can already be mapped onto Logback.

Many examples setting up the various logging APIs can be found in the integration tests of the project.

The following APIs are tested:

  • JBoss Logging 3.3.x
  • Commons Logging 1.2
  • JUL (Java Util Logging)
  • Log4j 1
  • Log4j 2
  • Slf4j

Mapping of OSGi Events

The OSGi Log specification describes events resulting in log records. Log 1.4 defines logger names mapping to these events.

EventLogger NameEvents types
Bundle eventEvents.BundleINSTALLED - BundleEvent INSTALLED
STARTED - BundleEvent STARTED
STOPPED - BundleEvent STOPPED
UPDATED - BundleEvent UPDATED
UNINSTALLED - BundleEvent UNINSTALLED
RESOLVED - BundleEvent RESOLVED
UNRESOLVED - BundleEvent UNRESOLVED
Service eventEvents.ServiceREGISTERED - ServiceEvent REGISTERED
MODIFIED - ServiceEvent MODIFIED
UNREGISTERING - ServiceEvent UNREGISTERING
Framework eventEvents.FrameworkSTARTED - FrameworkEvent STARTED
ERROR - FrameworkEvent ERROR
PACKAGES_REFRESHED - FrameworkEvent PACKAGES REFRESHED
STARTLEVEL_CHANGED - FrameworkEvent STARTLEVEL CHANGED
WARNING - FrameworkEvent WARNING
INFO - FrameworkEvent INFO
Legacy Log Service eventsLogServiceany log events originating from bundles that used the original LogService logging API

Note: In order to improve the granularity of the logging associated with these events, Apache Felix Logback makes it possible to refer to these mappings per bundle by appending a period (.) and segments of the Bundle-SymbolicName of the originating bundle(s) to the logger names. This greatly improves the configurability.

Consider the following logback.xml example:

<configuration>
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%.15thread] %-5level %logger{36}:%line - %msg%n</pattern>
		</encoder>
	</appender>

    <!-- log all bundle events -->
	<logger name="Events.Bundle" level="TRACE"/>

    <!-- WARN framework service events, because we can -->
	<logger name="Events.Service.org.eclipse.osgi" level="WARN"/>

    <!-- turn OFF legacy Log Service records from bundles with BSN `org.baz.*` -->
	<logger name="LogService.org.baz" level="OFF"/>

    <!-- DEBUG service events for bundles with BSN `org.fum.*` -->
    <logger name="Events.Service.org.fum" level="DEBUG"/>

    <!-- DEBUG custom project -->
	<logger name="org.my.foo" level="DEBUG"/>

	<root level="ERROR">
		<appender-ref ref="STDOUT" />
	</root>
</configuration>

Notes

  • Apache Felix Logback supports Logback's automatic reloading upon file modification
  • When using equinox framework you may want to disable it's internal appenders using the system property eclipse.log.enabled=false