logging-log4j-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jacob Kjome" <h...@visi.com>
Subject Re: Specify Repository
Date Fri, 11 Apr 2008 22:11:22 GMT
On Fri, 11 Apr 2008 09:58:23 -0400
  "Robert Pepersack" <RPepersack@mdinsurance.state.md.us> wrote:
> Jake,
> 
> I've been thinking about your last reply.
> 
> I don't understand part of it.
> 
>>You'll have to come up with some way to determine how you configure each 
>>logger repository, though.  You could pre-initialize all the logger 
>>repositories based on the MDC value(s) you expect to select upon.
> 
> I understand this, but should I do it before or after the Spring container 
>starts?
> 

Before.  Basically, as soon as possible.

>>You could then run configure the repository either programmatically or via 
>>the 
>>appropriate *Configurator.doConfgure(url/stream/file/etc.., repository) 
>>methods.  In fact, you could do this all in a static initializer of the 
>>selector class.  That way, the selector is ready to go very shortly after it 
>>is loaded by the classloader.
> 
> But, I don't understand this.  I think I should use 
>PropertyConfigurator.doConfigure(URL, Repository), but I don't know what else 
>to do.  Why put all of this in a static initializer block in my selector?

Just as a way to get all the repositories configured as soon as possible.  Of 
course, you could also defer until the first log statement comes through, but 
if you already know all the values the various threads will be using for the 
MDC entry you are keying your repositories upon, then you might as well do it 
all up front.  Or don't, if you want to defer creation of repositories to the 
call to selector.getLoggerRepository().  If the value of the MDC entry you are 
keying on doesn't yet exist in your repository cache, then create the 
repository, configure it, store it in the cache, and return.

> How would the MDC factor into this?  Can you give more detail or an example?
> 

MDC doesn't really factor into this early initialization.  You are just using 
the values that, as I undertand, you know in advance to key your repositories 
in the cache.


One further thought.  There is a problem with this whole scheme (which you 
already alluded to in a previous response).  If you look at the Category class 
[1], where most of the Logger [2] functionality is stored, you will find that 
it keeps a reference to the repository instead of looking it up each time from 
LogManager [3].  This usually makes sense.  However, if the applicable 
selector criteria is not available at logger creation time, the logger will 
end up belonging to the default repository.  This is true in your case, 
because the MDC entries won't exist until the threads are kicked off, and your 
instances are created prior to the threads running.  So, if you store the 
logger as an instance variable in your Runnables at construction time, the 
instance will belong to the default repository, not the one you want it to 
ultimately be part of.

You have a couple options here.  The first is to not store the logger instance 
and call Logger.getLogger("somename") every time you want the logger.  The 
second is to use lazy-creation of the logger in the run() method and store the 
instance at that point.  In both cases, you'd want to make sure you called 
MDC.put(key, value) before calling Logger.getLogger() (probably first thing in 
the run() method)..

Assuming that the libraries you use are using instance loggers, you should be 
ok as long as they aren't singletons or otherwise being stored in some cache.

That gets me thinking that maybe Category/Logger shouldn't keep a reference to 
the repository as it does today?  If it always called 
LogManager.getLoggerRepository() when it was needed, then even statically 
defined loggers would always log to the correct logger repository.  Of course, 
there might be a significant performance cost as well as some details I 
haven't thought of that make this unfeasible?  But it seems like it would be 
possible to make repository selection less haphazard than it is today.


[1] 
http://svn.apache.org/viewvc/logging/log4j/trunk/src/main/java/org/apache/log4j/Category.java?view=log
[2] 
http://svn.apache.org/viewvc/logging/log4j/trunk/src/main/java/org/apache/log4j/Logger.java?view=log
[3] 
http://svn.apache.org/viewvc/logging/log4j/trunk/src/main/java/org/apache/log4j/LogManager.java?view=log

> Thanks,
> 
> Bob
> 
>>>> "Jacob Kjome" <hoju@visi.com> 04/10/2008 11:53 AM >>>
> On Thu, 10 Apr 2008 10:49:50 -0400
>  "Robert Pepersack" <RPepersack@mdinsurance.state.md.us> wrote:
>> I'm not confusing LogManager.setLoggerRepository(repository, guard) and 
>>LogManager.getLoggerRepository().  I understand everything in Chapter 8.
>> 
> 
> Then you understand why there's no point to LogManager.getLoggerRepository() 
> taking arguments and why it's not generally necessary to actually call this 
> from application code.
> 
>> I wouldn't be creating all that many repositories, just one for each of my 
>>jobs (this is analogous to one repository per web application).  I currently 
>>have six jobs, so would I have six instances of Hierarchy that get reused 
>>again and again?
>> 
> 
> If your threads are limted to a pool of 6, then you're correct; it wouldn't 
>be 
> that much overhead.  And, yes, you would cache each logger repository in a 
> collection within your selector, keyed by whatever MDC value you selecting 
> upon.
> 
> You'll have to come up with some way to determine how you configure each 
> logger repository, though.  You could pre-initialize all the logger 
> repositories based on the MDC value(s) you expect to select upon.   You 
>could 
> then run configure the repository either programmatically or via the 
> appropriate *Configurator.doConfgure(url/stream/file/etc.., repository) 
> methods.  In fact, you could do this all in a static initializer of the 
> selector class.  That way, the selector is ready to go very shortly after it 
> is loaded by the classloader.
> 
> 
> Jake
> 
>> Robert Pepersack
>> Senior Lead Developer
>> Maryland Insurance Administration
>> 410-468-2054
>> 
>>>>> Jacob Kjome <hoju@visi.com> 04/10/2008 10:34 AM >>>
>> Are you confusing LogManager.setLoggerRepository(repository, guard) with 
>> LogManager.getLoggerRepository()?  In whatever environment you are in, you 
>>just 
>> need to make sure that you set your custom repository selector first thing, 
>>before 
>> doing any logging.  A servlet context listener was only a suggestion of a 
>>possible 
>> way to do it if you were running in a servlet environment.
>> 
>> You could do this prior to loading the Spring application context.  I'm 
>>assuming 
>> that if you are using plain old JSE, and not JEE, that Spring 
>>applicationContext 
>> loading is not being done in some automatic way, but manually.
>> 
>> And I think I said the per/thread approach is heavyweight because it creates 
>>a 
>> *lot* of logger repositories and requires configuration to run on each of 
>>them as 
>> they are created.  That's much more heavyweight than the typical application 
>> server JNDI-based logger repositories, which would only be created once per 
>> application.
>> 
>>Finally, you don't have to call LogManager.getLoggerRepository().  Your 
>>selector 
>> implements this.  Log4j calls it internally when determining which logger 
>> repository to log to.  Your selector implements...
>> 
>> public LoggerRepository getLoggerRepository();
>> 
>> Again, see the ContextJNDISelector in the sandbox for an example...
>> http://svn.apache.org/repos/asf/logging/sandbox/log4j/log4j_sandbox/tags/LOG4J_SANDBOX_ALPHA3/src/java/org/apache/log4j/selector/ContextJNDISelector.java

>> 
>> Your code just does the following, as usual...
>> 
>> logger.debug("blah");
>> 
>> 
>> It's all magic/smoke and mirrors.  That's both the beauty and the bane of 
>>the 
>> repository selector solution.  It's works transparently, like magic, but 
>>it's 
>> sometimes hard to comprehend; and sometimes simply fails to work in certain 
>> situations.
>> 
>> 
>> Jake
>> 
>> Robert Pepersack wrote:
>>> James and Jake, thanks for your replies.
>>> 
>>> I want to specify a RepositorySelector, because I'm using the Spring IOC 
>>>container to manage my application.  The Spring IOC container is a J2SE 
>>>container, not J2EE.  So, there is no ServletContext for me to use to 
>>>determine which repository to select.  The book points out that 
>>>LogManager.getLoggerRepository() does not accept any arguments, and it says 
>>>that the RepositorySelector must track the context.  But, in a J2SE 
>>>environment, I don't know a way to do this - other than using the MDC, as 
>>>Heri suggests in the log4j archives.  Jake, you said that this approach is 
>>>heavy weight, but I don't understand why.  Here is the URL for Heri's 
>>>suggestion:
>>> 
>>> http://mail-archives.apache.org/mod_mbox/logging-log4j-user/200602.mbox/%3C3FE38194C8A3334A959B64B7D9A1E27B6E30E1@plejaden.seychelles.ergo%3E

>>> 
>>> But, here is an added twist.  In the Spring IOC containter, most objects are

>>>created by one thread as the container starts, and the objects' methods are 
>>>executed by another thread (i.e. Quartz jobs).  Since my loggers are created 
>>>as instance variables, the MDC approach breaks down.
>>> 
>>> Thanks,
>>> 
>>> Robert Pepersack
>>> Senior Lead Developer
>>> Maryland Insurance Administration
>>> 410-468-2054
>>> 
>>>>>> "Jacob Kjome" <hoju@visi.com> 04/09/2008 5:52 PM >>>
>>> Your repository selector selects the repository.  You set the repository 
>>> selector by calling LogManager.setRepositorySelector(selector, guard).  Note

>>> that the guard is provided so that if someone else comes along a tries to 
>>> reset it, they will get an IllegalArgumentException and be prevented from 
>>> overriding the initial setting.  This is because the selector is global to 
>>>the 
>>> Log4j instance.  Repository selector setting is meant to be done at 
>>> application startup.  When running inside an application server, it should, 
>>> ideally, be set by the server.  However, if you are the only app to use it, 
>>> you could have a servlet context listener do this upon application startup.
>>> 
>>> http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/LogManager.html#setRepositorySelector(org.apache.log4j.spi.RepositorySelector,%20java.lang.Object)
>>> 
>>> As you can see, this has nothing to do with logger statements.  Your code 
>>> doesn't have to change in order to use a repository selector.
>>> 
>>> Jake
>>> 
>>> On Wed, 09 Apr 2008 11:58:53 -0400
>>>   "Robert Pepersack" <RPepersack@mdinsurance.state.md.us> wrote:
>>>> I've checked the archives and didn't find an answer, but please forgive me

>>>> if this a duplicate post.
>>>>
>>>> I would like to be able to specify a repository for my logger to use.  For

>>>> example:  Logger logger = new Logger("my.class.name", "myRepositoryName");
>>>>
>>>> I read Chapter 8, "Extending log4j", and it said that subclassing Logger
is 
>>>> a bad idea.  I don't see a way to accomplish what I want by wrapping Logger.

>>>> So, I think, that the only way to do it would be to tweak a few of the log4j

>>>> classes (i.e. Logger, LogManager, RepositorySelector, and 
>>>> DefaultRepositorySelector).  Would anyone be interested in this, or am I

>>>> barking up the wrong tree?  I realize that this could open a can of worms

>>>> with a lot of repositories getting created, but, if we're carful, this could

>>>> be very useful.
>>>>
>>>> Thanks,
>>>>
>>>> Robert Pepersack
>>>> Senior Lead Developer
>>>> Maryland Insurance Administration
>>>> 410-468-2054
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
>>>> For additional commands, e-mail: log4j-user-help@logging.apache.org 
>>>>
>>>>
>>> 
>>> 
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
>>> For additional commands, e-mail: log4j-user-help@logging.apache.org 
>>> 
>>> 
>>> 
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
>>> For additional commands, e-mail: log4j-user-help@logging.apache.org 
>>> 
>>> 
>>> 
>>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
>>For additional commands, e-mail: log4j-user-help@logging.apache.org 
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
>>For additional commands, e-mail: log4j-user-help@logging.apache.org 
>> 
>> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
>For additional commands, e-mail: log4j-user-help@logging.apache.org 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
>For additional commands, e-mail: log4j-user-help@logging.apache.org
> 
> 


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


Mime
View raw message