[slf4j-dev] MDC Type functionality

Gardiner, Paul PGardiner at syntellect.com
Tue Mar 27 21:07:07 CEST 2007



-----Original Message-----
From: dev-bounces at slf4j.org [mailto:dev-bounces at slf4j.org] On Behalf Of
John E. Conlon
Sent: Tuesday, March 27, 2007 2:39 PM
To: slf4j developers list
Subject: Re: [slf4j-dev] MDC Type functionality

Paul,

Gardiner, Paul wrote:
> John,
>
> What you have in the repo looks like an implementation of an OSGi log
> service that uses SLF4j to do the logging.  What I have is a bit
> different.  I'll explain in a bit more detail.
>
> The OSGi log service I am using is the Equinox extended log service.
> The SLF4J implementation I did (the "log user") is a separate bundle
> that uses the OSGi log service; it doesn't provide any services
itself.
> Instead, it writes out log entries to the OSGi log service.  I use the
> slf4j.api bundle, and then export org.slf4j.impl, and my logger
package
> from my bundle, which the slf4j.api bundle then imports.  
>   


So your 'log user' might also be called in our slf4j naming conventions 
a: slf4j-osgi.
Bundle wiring (with the symbol --> meaning uses some package or service 
from another bundle) so far looks like:
[PAG] By "-->", I was just intending to show the flow of the logged
message, not a dependency.

originatingBundle(s) --> slf4j-api --> your 'log user'(aka slf4j-osgi) 

Right?
[PAG] Yes, assuming that the "slf4j-osgi" is not the one in the repo,
because that one is an OSGi log service, not a user of the log service.
My slf4j implementation is a user of the service.

> Then I have a completely separate bundle (the "log reader user") that
> registers a listener with the OSGi log service.  Every time a log
entry
> is made by the log user, the log reader user's filter method gets
called
> (isLoggable), and if it returns true, its logged method gets called,
> which is where the logs get written out to their final destination.  
Paul, I have a rough idea of what your doing but I maybe hossed up 
somewhere -  if from the following you see that I am still confused 
please send me a list of the package imports and exports from each of 
your bundles and also note which services are used by each of the
bundles.
[PAG] Would it be easier to send the whole workspace?  It's not too big.

> The
> logged method receives an ExtendedLogEntry object as its argument,
which
> in addition to the stuff inherited from LogEntry, contains the logger
> name, thread id, a sequence number, and a context object, which can be
> any object defined by the log user.  Currently, I have the bundle and
> FQCN included in this object.  Note that the bundle is the bundle that
> made the original log entry, not the log user bundle.  My log reader
> bundle is using log4j to log out the messages.  
>
> So all together, there are three components - log user bundle (slf4j),
> the OSGi extended log service (in Equinox incubator), and the log
reader
> user (currently I'm using log4j).  When making a log entry, the path
the
> log message takes is ->originating bundle->log user->OSGi logger->log
> reader user.
>   
1. originatingBundle(s) --> 2. slf4j-api bundle--> 3. your 'log 
user'(aka slf4j-osgi) bundle --> 4. OSGi logger(LogService) bundle--> 5.

'log reader user' bundle--> 6. log4j
[PAG] Yes, that looks right on.

I think I got it so far.  So how are you using the log4j(6)?  Or in 
other words how does your 'log reader user' bundle (5) use the log4j (6)

packages, does it import them from a log4j bundle or are they privately 
packaged by you into your 'log reader user' (5) bundle?
[PAG] In the case of log4j, it has a Require-Bundle entry in the
manifest.  Because the "slf4j-osgi" bundle and the logback bundle both
use slf4j, I had to place the logback and slf4j jars inside the logback
reader bundle, otherwise I would go into an endless loop.

> The advantage to this approach is that it is reasonably efficient,
> allows users to use LoggerFactory.getLogger(getClass())...  and still
> get bundle and other context information without having to use a
service
> reference or bundle as an argument, it allows for different listener
> types, and it doesn't break existing OSGi log users/log reader users.
>   
Native LogService client bundles would then be wired like:
3*. LogService client bundles -->4. OSGi logger(LogService) bundle--> 5.

'log reader user' bundle--> 6. log4j

Top end sounds good - both Equinox LogService clients (3*) and slf4j 
clients (1)  are supported. 
> So to answer your question about which implementation, the answer is
> it's an OSGi log user implementation.  
 OSGi logging (like many other OSGi services) can be split up (or 
combined) in many different ways.  So from slf4j perspective it's impl 
is your OSGi 'log user'(3) .  From the perspective of the actual 
outputing of log messages to the world the 'logging impl' would be 
log4j(6).  Sorry for mixing up terms in previous email.
> I implemented it using a
> LocationAwareLogger, but nothing is being done with the marker data at
> the moment, because I can't use logback as the log reader user.  
So your 'log user' (3) is implemented with a LocationAwareLogger which 
means you have the information you want at (3) and you want to 
(obliviously) get it to (6).

the path again...
3. 'log user'(aka slf4j-osgi) bundle --> 4. OSGi logger(LogService) 
bundle--> 5. 'log reader user' bundle--> 6. log4j

So if  you want your logging messages from originatingBundles that use 
slf4j apis to use this path
1. originatingBundle(s) --> 2. slf4j-api bundle--> 3. your 'log 
user'(aka slf4j-osgi) bundle --> 4. OSGi logger(LogService) bundle

and you want to retain context information then you would have to map 
the Marker information you have at 'log user' (3) to something that the 
LogService (4) can use passing that through to (5).  You would then have

to pull out this information again at (5) and pass it to a logger(6) for

output.   Sounds messy.
[PAG] Yes.  I had to serialize the marker to a byte array and
deserialize it on the other side.  Yes, kind of messy.

Why not implement the slf4j at  the 'log reader user' bundle (5)? 
[PAG] A couple of reasons.  First, the way it's implemented now, all a
programmer has to do is import the slf4j-api bundle, and then use it.
They don't have to worry about context, because its all taken care of.
Second, the OSGi api without the extensions has no way of getting
context through to the reader where no service reference is used.  The
objective here is to provide a better logging api while still using the
OSGi log service, and provide implementation options on the reader side.
>  The
> reason for this is that I already have a binding to OSGi, so if I then
> bind to logback, I have a classloader issue.  This should be ok if I
> completely segregate the bundles, but unfortunately I can't do that,
> because the Marker object comes from the log user bundle, which is
> different than the Marker object from the log reader user bundle.
>   
The Marker interface and the BasicMarker are exported from the slf4j-api

bundle.
> Having said that, I'm not really asking for ideas on this, unless you
> have ideas off the top of your head.  I really haven't looked into
this
> very much.  I tried implementing logback, it got lots of class loader
> errors, so I put log4j back.  
Your use case is rather generic so I expect this will come up again in 
the future so trying to get a handle on it now is a good thing.  
(Actually had it on my todo list to address this.) ;-)

Did you make a logback bundle?
[PAG] Yes.  It seems to be working very well, and the markers work fine
also.

Alternative suggestion -
An OSGi bundle implementation of a logback based slf4j binding that I 
will call here  'slf4j&osgireader-logback'  that also listens to the 
OSGi logService (5*).  That replaces the 'log reader user' bundle (5)  
the  log user (3) as well.

slf4j clients now do:
1. originatingBundle(s) --> 2. slf4j-api bundle--> 5*. 
slf4j&osgireader-logback bundle

and LogService clients now do:

3*. LogService client bundles -->4. OSGi logger(LogService) bundle--> 
5*.slf4j&osgireader-logback bundle

WDYT?
John

> Also, since both the log user and log
> reader user use SLF4J (since logback uses it), I end up getting an
> endless loop.  Once I have looked a bit deeper, I'll pose some
> questions, but for now, I just don't understand what's going on
enough.
> I'm pretty sure the class loader issues are solvable though.
>
> As far as MDC goes, I think I'll just drop it.  I likely can get the
job
> done with Markers, but I'll have to learn a bit more about how they
> work.  I understand how to use them, but need to learn how to use them
> properly and appropriately.
>
> Thanks,
> Paul
>
> -----Original Message-----
> From: dev-bounces at slf4j.org [mailto:dev-bounces at slf4j.org] On Behalf
Of
> John E. Conlon
> Sent: Monday, March 26, 2007 5:26 PM
> To: slf4j developers list
> Subject: Re: [slf4j-dev] MDC Type functionality
>
> Gardiner, Paul wrote:
>   
>> The extended log service in equinox is similar to the standard one,
>>     
> but
>   
>> it adds a few extra methods for supporting named loggers, isLoggable,
>> and logging context objects.  Here's the basic idea:
>> https://www.eclipse.org/bugs/show_bug.cgi?id=147824.  It's just an
>> incubator project right now, but I have a pressing need at the
moment.
>>   
>>     
>
> Interesting thread... I think our devs and users may find it most 
> interesting as slf4j is mentioned several times: :-)
>
> For example:
>
>   
>> Message payload for the LogService consistes primarily of String
based
>>     
> messages
>   
>> and when relevant a Throwable. In some situations a generic
>>     
> String-based
>   
>> logging API is insufficient and in these cases it's desirable to pass
>>     
> additonal
>   
>> information with the understanding that it may be ignored. SLF4J uses
>>     
> it's
>   
>> Marker API in this fashion to allow strong coupling between logger
and
>> recipient without impacting the generic log API.
>>     
>
> ...
>
>   
>> For this to work there are a couple of problems that need thought:
>> 1) we need a binding of the various logging API to the log service
>>  - we should consider looking at SLF4J as its defined a few useful
>>     
> static
>   
>> bindings already for JCL and log4j.
>>     
>
> ...
>
>   
>> I'm step by step migrating to SLF4J, because I really enjoy the
>>     
> simplicity and
>   
>> effectiveness of the API. Problem is: I NEED to know which OSGi
Plugin
>>     
> is
>   
>> logging.  This is a serious problem, as all implementations only
>>     
> provide a
>   
>> thread based context.
>>     
> Note: The osgi-over-slf4j binding in the repo already provides this
> information as BundleSymbolicName and Version.
>
>
>
>
>
>   
>> I'm new to SLF4J, but I have looked around at markers, and found
there
>> isn't a lot of info on how they are used.  
>>     
> Logger logger = LoggerFactory.getLogger("testMarker");
> Marker blue = MarkerFactory.getMarker("BLUE");
> logger.debug(blue, "hello");
> logger.info(blue, "hello");
> logger.warn(blue, "hello");
> logger.error(blue, "hello");
>
> Take a look at the test cases in slf4j.
>   
>> It looks like a single piece
>> of data, but with a hierarchy.  
>>     
> Yes.
>   
>> How would it work in this case?  Would I
>> (or the end user) create a marker named "session_id", and then create
>>     
> a
>   
>> child with the actual session id as the name?  
>>
>>   
>>     
> Well from what I gather about the Equinox extension is that there is a

> context associated with logging messages.
> In your use case the user or client application is an Equinox Log 
> Service client, not a slf4j api user right? That would mean YOU would 
> have to create the Marker from the context in the log messages in your

> 'equinox-over-slf4j'.
>
> Now the critical question is which Logging API implementation are you 
> planning to have your 'equinox-over-slf4j' bind with? If you use
Markers
>
> you will have to use an implementation that uses them too and that
would
>
> be either one that you implement or the Logback implementation. Check 
> the logback project for more details on how it handles marker 
> hierarchies. http://logback.qos.ch/
>
> cheers,
> John
>
>   
>> -----Original Message-----
>> From: dev-bounces at slf4j.org [mailto:dev-bounces at slf4j.org] On Behalf
>>     
> Of
>   
>> John E. Conlon
>> Sent: Monday, March 26, 2007 12:55 PM
>> To: slf4j developers list
>> Subject: Re: [slf4j-dev] MDC Type functionality
>>
>> Hello Paul,
>>
>> Have you considered using the
>>
>>
>>     org.slf4j.Marker
>>
>> to move this data to the readers? See the FAQ 
>> http://www.slf4j.org/faq.html#marker_interface
>>
>> BTW - You may have noticed in our slf4j source repository we have 
>> implemented a simple osgi log service for slf4j?
>> http://svn.slf4j.org/viewvc/slf4j/trunk/osgi-over-slf4j/
>>
>> I have not worked with the Equinox log service but plan to do so
soon.
>>     
>
>   
>> Paul would you be so kind to please provide a link to the
>>     
> documentation 
>   
>> that can describe the Equinox extensions? Is this log service the
same
>>     
>
>   
>> used by Eclipse as well?
>>
>> thanks,
>> John
>>
>>
>> Gardiner, Paul wrote:
>>   
>>     
>>> I have written an SLF4J binding to the Equinox extended log service,

>>> which is an extension of the OSGi logging service, that includes 
>>> contextual information, and passes "isLoggable" statements through
to
>>>       
>
>   
>>> log listeners (readers). The problem I have is supporting extra data

>>> that is not part of the log message. SLF4J does not include MDC or
>>>       
> NDC
>   
>>>     
>>>       
>>   
>>     
>>> functionality, so I am not sure of the best way to pass through this

>>> kind of data. A typical use case is session id, which is passed as 
>>> MDC. When the log entry is made, the session id is included in the 
>>> file appender, but omitted from an appender that sends pages. One 
>>> solution is to read all MDC data and pass it through to the OSGi log

>>> service, and then recreate it in the log reader. However, I was 
>>> wondering if there was a more elegant/less expensive solution.
>>>
>>> Thanks,
>>>
>>> Paul
>>>
>>>
>>>     
>>>       
>
------------------------------------------------------------------------
>   
>>   
>>     
>>> _______________________________________________
>>> dev mailing list
>>> dev at slf4j.org
>>> http://www.slf4j.org/mailman/listinfo/dev
>>>     
>>>       
>> _______________________________________________
>> dev mailing list
>> dev at slf4j.org
>> http://www.slf4j.org/mailman/listinfo/dev
>> _______________________________________________
>> dev mailing list
>> dev at slf4j.org
>> http://www.slf4j.org/mailman/listinfo/dev
>>
>>
>>   
>>     
>
> _______________________________________________
> dev mailing list
> dev at slf4j.org
> http://www.slf4j.org/mailman/listinfo/dev
> _______________________________________________
> dev mailing list
> dev at slf4j.org
> http://www.slf4j.org/mailman/listinfo/dev
>
>
>   

_______________________________________________
dev mailing list
dev at slf4j.org
http://www.slf4j.org/mailman/listinfo/dev



More information about the slf4j-dev mailing list