logging-log4j-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Charles Hache <cha...@tsco.ca>
Subject Re: Filter log based on package when using getLogger(String)
Date Wed, 18 Jul 2012 22:04:33 GMT
Thanks a lot for the tips guys!

tl;dr - skip to the end for my final, simple solution.

I'm a bit hesitant to adding expression filters to do this filtering.  
The root of the issue is that I want to set the package log level using 
the regular, standard way (so that anyone can do it/understand it from 
the properties file), but I want my loggers to output a bit of extra 
info whenever they print a line, so I know what instance is doing what.

The MDC/NDC stuff looks very interesting, but I'm looking for per logger 
granularity, not per thread.  When a thread traverses an object graph 
and does work in each object, I want the object to tell me which 
instance it is when it prints it's log lines, regardless if the worker 
is Thread-4 or Thread-34 etc.

I had found that this is sort of a tall order as the architecture 
doesn't really do this sort of thing (according to my primitive 
knowledge of it), but I made it pretty close (with some blocking 
caveats) with a custom logger.

I ended up finding out about custom loggers and log factories from the 
<Install Zip>/examples/subclass folder.  I threw together a new logger 
('DescriptiveLogger') and a factory for it. The DescriptiveLogger has a 
description field and overrides all the default logging to prepend the 
message with this description.

The system works out fine until I want to create two loggers with the 
same name/package with a different description.  When I try 
DescriptiveLogger.getLogger(existingClassAkaPackage, newDescription), it 
will change the original/old logger and update it with the new 
description, but I want a whole new instance.

This is due to the Hierarchy implementation - it stores all the loggers 
in a hashtable that is keyed by the logger name (which is the same for 
all my loggers, but I'd like a separate instance for each one so they 
can each have their own description).

So after pouring over the source, I've finally found the trivial ideal 
solution.  Beforehand I was using getLogger("ImportantDevice: This 
instance has ID 23"), which would give me the information I wanted in 
the log, but wouldn't allow me to easily user per-package log levels 
through the properties file.  The alternative log creation, namely 
getLogger(ImportantDevice.class) would give me the log level control I 
wanted, but wouldn't give me the instance information I crave.

The solution is to use getLogger(ImportantDevice.class.getName()+": This 
instance has ID 23").  Now the logger name is prefixed with the package, 
which allows log4j to apply package log level rules to it, and the 
logger name is also suffixed with the extra information I was looking 
for.  It took more time then I was hoping to figure this out (and I 
didn't get to employ anything cool), but I expect that at least one 
other person on here may be able to find it useful.


On 7/18/2012 10:55 AM, Scott Deboy wrote:
> Correction: expression would use the LOGGER instead of MSG, since you're
> filtering on that.
> On Wed, Jul 18, 2012 at 10:54 AM, Scott Deboy<scott.deboy@gmail.com>  wrote:
>> You can use filters, including the ExpressionFilter, to build pretty much
>> arbitrary expressions and filter appenders using that, but it requires you
>> to use a log4j.xml configuration file.
>> Something like this (requires you to have the 'extras' companion in your
>> classpath):
>>                  <filter class="org.apache.log4j.filter.ExpressionFilter">
>>                                  <param name="Expression" value="MSG ~=
>> #3"/>
>>                                  <param name="AcceptOnMatch"
>> value="false"/>
>>                          </filter>
>> Scott
>> On Wed, Jul 18, 2012 at 10:26 AM, Charles Hache<chache@tsco.ca>  wrote:
>>> Hello folks,
>>> Most of my loggers are constructed with the Logger.getLogger(String)
>>> function, so that I can have loggers like "Device(#3, Some Description)"
>>> instead of "ca.something.package.Device" with the goal of being able to
>>> more easily identify which instances are writing what log lines.
>>> I've found that when I do this I can't use properties to filter the log
>>> level, such as
>>> log4j.logger.ca.something.**package=INFO
>>> I figure this is because if I use getLogger(Device.class) it gets the
>>> package of the logger from the class I give it and it all works from there.
>>> So this all makes sense, but brings up two questions:
>>> Can I still declare my loggers with a String name (getLogger(String)) and
>>> somehow still use package-style log level selection in the properties file?
>>> If not, do you guys have any tips on how to differentiate between
>>> instances when they're logging?  The obvious solution would be to prepend
>>> any log message I want to write with a description of the instance, but
>>> that seems like a lot of extra work.
>>> I think really what I'm looking for is something like getLogger(Class
>>> theClass, String theName), but maybe there is an already-implemented way to
>>> do this.
>>> Any tips?
>>> Regards,
>>> Charles
>>> ------------------------------**------------------------------**---------
>>> To unsubscribe, e-mail:log4j-user-unsubscribe@**logging.apache.org<log4j-user-unsubscribe@logging.apache.org>
>>> For additional commands, e-mail:log4j-user-help@logging.**apache.org<log4j-user-help@logging.apache.org>

Charles Hache

Manager, Software Systems

Technical Solutions Company Ltd.
101 Titanium Way, Unit 105
Whitehorse, Yukon Y1A 0E7

Tel 867-668-6588, Ext. 204
Cell 867-336-1484
Fax 866-528-6410

Technical Solutions Company Ltd.
Automation - Telemetry - Electronics - Communications

To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org

View raw message