[osgi logging] part 2 – LogServices vs classic Logger

This is part 2 of my blogseries about ‘Logging in OSGI Enterprise Applications‘ – you’ll find all parts here.

OSGI Log Services vs ‘classic’ Logging

There are some important differences you should be aware of before taking your decision:

  • How do you log ? There are not so much differences at a first look:
    • OSGI Log Services: logService.log(LogService.LOG_INFO, “Hello “+user.getName()+” is logging!”)
    • Equinox Extended Log Services: logger.log(LogService.LOG_INFO, “Hello “+user.getName()+” is logging!”)
    • Apache Commons Logging: logger.info(“Hello “+user.getName()+” is logging!”)
    • SLF4J / Logback: logger.info(“Hello {} is logging!”, user.getName())
  • When will a message be logged ?
    • Using OSGI Log Services all messages are always logged, which meant the OSGI Log Services will provide your Log Entries to all Log Reader Services, where you then decide what to do with this message.
    • Using ‘classic’ Logging the Log Implementation decides from your configuration if a message from this logger at a specific level should be logged or not. If not, then nothing happens and if using a modern implementation like SLF4J / Logback then there’s no String  concatenation done to construct the log message. Logback understands parameterized Log messages, tests first if the message should be logged and then constructs the message. Other Implementations always do the String concatenation – thats the reason why you found constructs like if logger.isDebugEnabled() then… where’s no need to use it with SLF4J/Logback (read more here about parameterized log messages)
  • What will be logged ?
    • Using OSGI Log Services you’re best integrated into OSGI world and have access to BundleContext and ServiceReferences.
    • Extended OSGI Log Services also give you the Loggername (normaly the Classname from where you logged)
    • ‘classic’ Logging has no infomations about Bundles or ServiceReferences, but knows things like MDC (Mapped Diagnostic Context – a Thread-local Map to add Sessiondata or so)
    • SLF4J/Logback has also Marker Support. Markers are a tree of Strings – I use Markers to store the Bundle from where the Log message comes.
Here’s a short comparision about the content of a LogEntry:
was-wird-geloggt

How to decide what to use ?

Its not always easy to decide, whats your best choice – perhaps some questions can help:

  • You’re developing an OSGI Application without many ‘other’ frameworks / tools integrated?
  • You have your own Logging – Backend (perhaps sending all  Log Entries to a RDBMS Log Server) ?

→ OSGI LogService + OSGI LogReaderService seems to be a good choice

  • You’re developing an OSGI Application without many ‘other’ frameworks / tools integrated?
  • You like the flexibility of different Appenders from ‘classic’ Logging Frameworks (RDBMS, SMTP, Files, …) ?

→ OSGI LogService + OSGI LogReaderService  …or… → ‘classic’ Logging

  • You already integrate other Bundles using ‘classic’ Logging ?
  • Or you expect to use those bundles in the future ?
  • You need flexibility of Appenders ?

→ ‘classic’ Logging is perhaps your way to go

How to get all under the same umbrella ?

Here’s an example how it could look like:
logging framework-flow
An interesting part is the LogListener – in my blog series from 2008 I used a ServiceTracker, now I’m using DeclarativeServices (DS).

you’ll find the overview of this blog series here. stay tuned… part3 follows…

4 responses

  1. Jörn Huxhorn (Lilith Developer see part 8) told me about another difference between Log4J and Logback:
    Log4J supports NDC (http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/NDC.html), where Logback didn’t.

    Lilith provides an NDC impl (http://lilith.huxhorn.de/projects/de.huxhorn.lilith.logback.classic/apidocs/de/huxhorn/lilith/logback/classic/NDC.html) and if using Appenders from Lilith (like ClassicMultiplexSocketAppender I described in this blog series) you can also use NDC with Logback.

    I haven’t used NDC (Nested Diagnostic Context) yet – it fits well in Sessions of Web-applications – if the Thread-based NDC makes sense in an Enterprise OSGI application with remote RCP clients I don’t know, but I’ll have it in mind. thx to Jörn Huxhorn mentioning NDC

    ekke

  2. Hi Ekke,

    Thanks for your great blog series about logging, I finally found the time to try this all out.
    I have just one question on how you use the logback markers for the bundle names: Do you define such a marker in your bundle and then create one logger (each referencing this marker) per class in the bundle? Or did you find a way to use one “central” bundle logger and use this across your bundle? Maybe you can post an example how your logging code looks like.

    Cheers, Kai.

    • Kai,
      in each bundle I have something like this – in the Activator or another class

      // The Bundle Marker: a Marker where the name is the osgi bundle symbolic name
      // and an attached IS_BUNDLE – Marker to guarantee that the Log Framework knows its a BundleMarker
      public static final Marker bundleMarker = createBundleMarker();
      private static final Marker createBundleMarker() {
      Marker bundleMarker = MarkerFactory.getMarker(ID);
      bundleMarker.add(MarkerFactory.getMarker(LoggingConstants.IS_BUNDLE_MARKER));
      return bundleMarker;
      }

      and I’m logging:

      logger.debug(Activator.bundleMarker, “my log msg”);

      ekke

Leave a comment