Package de.mnl.osgi.lf4osgi

A bundle that provides a logging facade for the standard OSGI Logger.

GitHub issues Maven Central

Installation

The bundle is deployed as any other OSGi bundle

Facade functionality

The OSGi Log Service has improved a lot with Version 1.4. Still, it is not as easy to use as the popular logging frameworks, mainly because it lacks a static factory for loggers. In order to get a logger, you first have to obtain a LoggerFactory as service. Even with Declarative Services (or some other dependency managing framework), this makes the usage more cumbersome than you'd like it to be. And you still have to handle the problem that all loggers obtained become invalid should the LoggingFactory service in use be replaced.

Yet another point is how to log when no LoggingFactory service is available. This may be the case during startup.

This "facade" for OSGi logging overcomes those problems. The tiny overhead to pay is an extra method invocation because the Logger implementation provided as facade has to delegate to the logger supplied by the LoggingFactory service (or a stand-in, see below). However, this should be neglectable under all circumstances, especially if you use closures for logging.

As long as there is no LoggingFactory service available (yet), logging events are recorded in a buffer which is flushed to the service as soon as it becomes available. The "thread info", which is added automatically by the implementation of the logger service, cannot be recorded. The recorded event data therefore includes the name of the thread that caused the log event. When flushing the recorded events, the name of the flushing thread is temporarily set to the recorded thread name with "[recorded]" appended.

Of course, while there is no LoggingFactory service available, the desired logging level cannot be determined. Therefore all events with level LogLevel.DEBUG and up are recorded. This default threshold can be changed using system settings or bundle properties (see below).

Additional log methods

The loggers returned by the LoggerFactory actually implement a subinterface of the OSGi Logger interface. This augmented LF4OSGi Logger interface provides additional log methods with the first parameter being the Supplier for the message, which is only evaluated if the log level is met.

This additional functionality is the reason why the LoggerFactory does not supply FormatterLoggers. Using a supplier for the message is a much more flexible design. If you want to use printf-style formatting, simply log like this:

 logger.warn(() -> String.format("Value is %d.", 42));
 
With the "message supplier pattern" you can just as easily use a MessageFormat or simply concatenate strings to generate your log message. As long as the log level is below the threshold, nothing is evaluated and no performance is lost.

Bundle properties

The following bundle properties are used to configure the described behavior.
Bundle parameters
PropertyDescriptionDefault
de.mnl.osgi.lf4osgi.bufferThreshold The minimum LogLevel of messages that are to be buffered. LogLevel.DEBUG
de.mnl.osgi.lf4osgi.bufferSize The size of the buffer. If the buffer is full, the oldest event is discarded. 100
Bundle parameters can only be evaluated when the bundle has been started. This may be too late if another bundle that uses LF4OSGi is started before this bundle. These values can therefore also be set as system properties. If values are supplied both as system properties and as bunde parameters, the bundle parameters take precedence when the LF4OSGi provider bundle is started.