[logback-user] Separating the logging-output of libraries in tomcat/shared

Ceki Gülcü ceki at qos.ch
Tue Mar 2 15:42:23 CET 2010


I think the short answer is yes. The nested appenders will have the
same configuration differentiated by the value returned by the
discriminator. You could add properties to the logger context and
since logger context properties are seen as variables, you could in
principle use the value of the property to filter events. Here is an
example using a ThresholdFilter and the variable myLevel with a
default substitution value (see [1]).

  <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
     <discriminator
       class="ch.qos.logback.classic.sift.JNDIBasedContextDiscriminator">
       <Key>context</Key>
       <DefaultValue>unknown</DefaultValue>
     </discriminator>
     <sift>
       <appender name="FILE-${context}" class="ch.qos.logback.core.FileAppender">
         <File>${context}.log</File>
         <Append>true</Append>
         <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
           <level>${myLevel:-DEBUG}</level>
         </filter>
         <layout>
           <pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</pattern>
         </layout>
       </appender>
     </sift>
   </appender>

You could set the myLevel property at the start of each
application. Here is the sample code for web-app A:


    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
    lc.putProperty("myLevel", some level value as appropriate for web-app A);

For web-app B, the code is similar:

    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
    lc.putProperty("myLevel", some level value as appropriate for web-app B);

You need to make sure that the "myLevel" property is set before the
logger context is configured which means that you need to override
default logback configuration by invoking joran directly. Search for
"Invoking JoranConfigurator directly" in [2]. The code then becomes:

    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    JoranConfigurator configurator = new JoranConfigurator();
    configurator.setContext(lc);
    // the context was probably already configured by default configuration
    // rules
    lc.reset();
    lc.putProperty("myLevel", some level value as appropriate for the web-app);
    configurator.doConfigure(args[0]);

HTH,

[1] http://logback.qos.ch/manual/configuration.html#defaultValuesForVariables
[2] http://logback.qos.ch/manual/configuration.html


On 02/03/2010 1:52 PM, Achim Wiedemann wrote:
> Hi Ceki,
>
> I just implemented your suggestion and it works like a charm. :)
> So it seems like there's a workaround for LBLCLASSIC-166 with your new
> discriminator-class now. Great work and thanks a lot!
>
> By the way: Is there any possibility to have different logging-levels
> for the nested appenders of a SiftingAppender?
>
>
> greetz,
> achim
>
>
>
>
> Ceki Gülcü schrieb:
>> You are right. ContextBasedDiscriminator will not help you because the
>> context name is retreived from the LoggingEvent which ultimately gets
>> its value from the calling logger. If the calling logger is attached
>> to the wrong context, ContextBasedDiscriminator will give you the
>> wrong context name. Sorry for misleading you.
>>
>> However, I've written a new discriminator which should work assuming
>> you have installed ContextJNDISelector as explained in
>>
>> http://logback.qos.ch/manual/loggingSeparation.html
>>
>> JNDIBasedContextDiscriminator can be found at
>>
>>
>> http://github.com/ceki/logback/blob/90e50c/logback-classic/src/main/java/ch/qos/logback/classic/sift/JNDIBasedContextDiscriminator.java
>>
>>
>> or the same in tiny-speak
>>
>> http://tinyurl.com/yb6pdj2
>>
>> Getting values from JNDIBasedContextDiscriminator, SiftingAppender
>> will get the correct context name and things should work much better.
>> Give it a try.
>>
>>
>>
>> On 01/03/2010 9:38 AM, Achim Wiedemann wrote:
>>> Hey Ceki,
>>>
>>> thanks for your fast reply. I tested your tip with the SiftingAppender,
>>> but couldn't see how this gets me further compared to the
>>> logging-separation described in Ch8 of the manual (separation via
>>> JNDIContextSelector). The problem is still the same: The context of the
>>> logger, once initialized, remains the same in shared libraries. Since
>>> SiftingAppender has to sieve based on some criteria (in my case the
>>> context), it also can't solve this issue.
>>>
>>> So I see, as you already stated, it's not possible to get this scenario
>>> to work. However, thanks for your time and all your work.
>>>
>>>
>>> greetz,
>>> achim
>>>
>>>
>>> Ceki Gulcu schrieb:
>>>>
>>>> Hello Achim,
>>>>
>>>> Thank you for your message.
>>>>
>>>>
>>>> The only way to solve this issue transparently and perfectly would be
>>>> to introduce another level of indirection inside loggers so that each
>>>> logger-shell somehow delegate work to an inner logger attached to the
>>>> appropriate context. This is quite a difficult problem technically and
>>>> would generate significant computational overhead. I don't see the
>>>> problem fixed via such indirection any time soon. Read, as a logback
>>>> user, don't expect this problem to be solved without a little work on
>>>> your side.
>>>>
>>>> As far as I can see, you have two options:
>>>>
>>>> 1) move shared classes whose loggers you care about to the web-app
>>>> (unshare them)
>>>>
>>>> If 1) is not an option, there is:
>>>>
>>>> 2) Use a single shared logback.xml file with separation done by
>>>> SiftingAppender [1] using the context as separation criteria [2]. In
>>>> conjunction with prudent mode of FileAppender, you will be able to
>>>> separate logging by context.
>>>>
>>>> Let me know if the above does not make sense.
>>>>
>>>>
>>>> [1] http://logback.qos.ch/manual/appenders.html#SiftingAppender
>>>> [2]
>>>> http://logback.qos.ch/xref/ch/qos/logback/classic/sift/ContextBasedDiscriminator.html
>>>>
>>>>
>>>>
>>>> On 26.02.2010 08:21, Achim Wiedemann wrote:
>>>>> Hey everybody,
>>>>>
>>>>> just wanted to port our application from commons-logging / log4j to
>>>>> slf4j / logback. Unfortunately I stumbled upon some problems when
>>>>> separating the logging-output from different webapps (using the
>>>>> JNDIContextSelector). As long as you only use logging from classes
>>>>> inside the webapp, everything works fine. But as soon as you've got
>>>>> classes in tomcat/shared which use logging, you run into trouble: All
>>>>> logging output of the shared classes (e.g. Spring) are directed to the
>>>>> logger-context of the webapp which first loads the (shared) class.
>>>>>
>>>>> Example: Let's say you've got webbapp [A], webbapp [B], and Spring in
>>>>> tomcat/shared. Now both webapps use Spring. If webapp [B] first
>>>>> accesses
>>>>> any classes of Spring, all output of Spring will be directed to the
>>>>> log-file of [B], no matter from which webapp Spring is used. This is
>>>>> because static Logger references are used in Spring (which is
>>>>> commonplace) and are initialized with the context of webapp [B].
>>>>>
>>>>> The issue is already described very well in the logback JIRA:
>>>>> http://jira.qos.ch/browse/LBCLASSIC-166
>>>>>
>>>>> I wondered if anyone can make a suggestion how to deal with this. Any
>>>>> advice, tricks or magic is welcome. ;)
>>>>>
>>>>>
>>>>> Thanks a lot,
>>>>> Achim
>>>> _______________________________________________
>>>> Logback-user mailing list
>>>> Logback-user at qos.ch
>>>> http://qos.ch/mailman/listinfo/logback-user
>>> _______________________________________________
>>> Logback-user mailing list
>>> Logback-user at qos.ch
>>> http://qos.ch/mailman/listinfo/logback-user
>>
>> _______________________________________________
>> Logback-user mailing list
>> Logback-user at qos.ch
>> http://qos.ch/mailman/listinfo/logback-user
>
> _______________________________________________
> Logback-user mailing list
> Logback-user at qos.ch
> http://qos.ch/mailman/listinfo/logback-user



More information about the Logback-user mailing list