Saturday, October 11, 2008

Logging in OSGI Enterprise Applications, Part 3

Part 3 explains how to catch all log events logged by OSGI Bundles using  OSGI Log Services. 

In part 2 you've seen that catching log entries from "classic" Log - Frameworks was very easy:
  • ✓ Choose the right bundles
  • ✓ Create a config - file 
-thats all :-)
Remark: java.util.logging needs also this one-liner: SLF4JBridgeHandler.install();

Running an OSGI Enterprise Application you'll also find bundles logging their log - entries using OSGI Services:
  • org.osgi.service.log.LogService 
  • org.osgi.service.log.LogReaderService 

You have also to watch for Services extending the "normal" OSGI Log Services: Eclipse Riena per ex. uses from Equinox Incubator:
  • org.eclipse.equinox.log.ExtendedLogService 
  • org.eclipse.equinox.log.ExtendedLogReaderService

You can read Log entries using the LogReaderService. You only have to register your LogListener
The LogListener gets all LogEntry (ExtendedLogEntry), then you can log them using SLF4J-API to your LOGBack Implementation. 

You have to use the same config file (logback.xml or logback-test.xml) as described in part 2 (logging the entries from „classic“ Log - frameworks). Details about configuration will follow in another Blog of this series.

Short overview:

We already have following bundles used as bridges between „classic“ Log-Frameworks and SLF4J / LOGBack:

  • slf4j.api
  • log4j.over.slf4j
  • jcl.over.slf4j

There are also the bundles of the SLF4J - implementation LOGBack:

  • logback.core
  • logback.classic

You'll find more details in part 2 of this Blog series.

Bundle osgi.over.slf4j (a bridge between OSGI Service and LOG4J)

We need a bundle as bridge between OSGI Log Services and SLF4J / LOGBack. Please create a Plug-In project using PDE:

  • my.namespace.osgi.over.slf4j

Your MANIFEST.MF should look like:

This osgi.over.slf4j - bundle has its own org.slf4j.Logger:
We'll use this Logger to log events from this bundle itself and also to log all catched LogEntry from other bundles.

To track LogReader Services we can use a ServiceTracker:

We create our LogServiceTracker with this filter to get only services from type LogReaderService or ExtendedLogReaderService:

(|(objectClass=org.osgi.service.log.LogReaderService) (objectClass=org.eclipse.equinox.log.ExtendedLogReaderService))

A LogListener for „normal“ OSGI LogServices:
LogEntry will be logged using the Logger of our osgi.over.slf4j - bundle.

A LogListener for „extended“ Equinox OSGI LogServices:
ExtendedLogEntry already contains an own Logger
We'll use an org.slf4j.Logger with same name - but to distinguish we use a prefix („X.“). Details will follow in another Blog.

Then we delegate LogEntry and ExtendedLogEntry to the org.slf4j.Logger:
We have to map the OSGI LogService Levels. We can get the origin message and (optional) exception from LogEntry and delegate to our Logger.

Different from Log4J or Commons-Logging is using a Marker. Markers are part of the SLF4J API, but at the moment only the LOGBack - implementation uses them. We are using Marker to print the bundle-name and perhaps also the service-name. Then we know which bundle / service originally creates the LogEntry or ExtendedLogEntry
Remark: More about Marker you'll find in one of the next Blogs of this series.

Logging BundleEvent and FrameworkEvent 

Its a good idea also to log org.osgi.framework.BundleEvent and org.osgi.framework.FrameworkEvent

To do this we need these Listener:
Dependent from the Event - Type we create the message and level.
Remark: More about SLF4J - Marker in one of the follow-ups.


Now we are ready to catch and log all events from „classic“ Log-Frameworks, OSGI LogServices, BundleEvents or FrameworkEvents using SLF4J / LOGBack:

This was the third part of my blog series "Logging in OSGI Enterprise Applications":

Perhaps some of my older blogs about Logging und OSGI are also interesting:

the blog in german.

No comments: