If you dont you pay special attention (i.e. using own RepositorySelector, using 
MDC, etc.), then all the log4j stuff is really global in one and them same JVM.

You need a way how you can distinguish your different apps in the same JVM. 

If all apps running in the same thread, it will be difficult. Every log 
statement must be surrounded by a calls to set and remove MDC information. You 
could centralize this, but then you loose source code informations (line 
number). Further you have to write filters (attacht to a particular appender) 
which analyze this MDC informations in order to block it or to write it to the 
file. I not encourage this way.

Better way: all apps run within its own thread context. 
1. The MDC information is kept per thread basis, so you have to set it only 
once at the beginning of eacht thread running (i.e. storing the thread id). 
2. In your main class (the launcher), you supply the LogManager with your own 
written RepositorySelector. This can be done statically:

    private static Object guard = new Object();
    
    static
    {
        LogManager.setRepositorySelector( new MyRepositorySelector(), guard );
    }

Your repository selector is called everytime you call Logger.getLogger( .. ), 
via the LogManager. 
The following example maintains a two dimensional map of different 
Repositories, the axis are described by an integer and an application name, 
realized by using a hashtable which has in turn hashtables in each entry. Your 
solution can be only one dimensional, only using an integer as key.
Which Repository is returned depends on the context information stored within 
the MDC. 

public class MyRepositorySelector implements RepositorySelector
{
    /** ID of the default hierarchy */
    private static final String DEFAULT_REPOSITORY_ID = "MyDefaultRepository";
    /** the location of the repository */
    private static Hashtable myHt = new Hashtable();

    /**
     * @see org.apache.log4j.spi.RepositorySelector#getLoggerRepository()
     */
    public LoggerRepository getLoggerRepository()
    {
        Integer eventID = ( Integer ) MDC.get( PROP_NAME_EVENT_ID );
        String appName = ( String ) MDC.get( PROP_NAME_APP_NAME );
        
        Hierarchy h = null;
        
        if (    ( eventID == null )
             || ( appName == null ) ) 
        {
            // MDC values are not set. This means, this method was called from 
somewhere not in my system
            h = ( Hierarchy ) myHt.get( DEFAULT_REPOSITORY_ID );
            
            if ( h == null ) 
            {
                h = createAndLoadHierarchy();
                myHt.put( DEFAULT_REPOSITORY_ID, h );
            }
        } 
        else 
        {
            // we maintain one Hierarchy per eventID and appName:
            Hashtable ht = ( Hashtable ) myHt.get( eventID );
            
            if ( ht == null ) 
            {
                ht = new Hashtable();
                myHt.put( eventID, ht );
            }
            
            h = ( Hierarchy ) ht.get( appName );
            
            if ( h == null ) 
            {
                h = createAndLoadHierarchy();
                ht.put( appName, h );
            }
        }       
        
        return h;
    }

    /**
     * Creates a new Hierarchy and configurs it from the file log4j.xml
     * 
     * @return the newly created Hierarchy
     */
    private synchronized Hierarchy createAndLoadHierarchy()
    {
        Hierarchy h;
        
        h = new Hierarchy( new RootCategory( Level.DEBUG ) );
        
        URL url = Loader.getResource( "log4j.xml" );
        OptionConverter.selectAndConfigure( url, 
"org.apache.log4j.xml.DOMConfigurator", h );
        
        return h;
    }
    
} 
     
BTW: You can provide most of the configuration details by using a config file. 
This is then done in the above call selectAndConfigure(). The file NAME can be 
changed in code, somewhere at the beginning of run() of a sub thread:

{
    ...
    <set MDC informations>  // important to set this before any call to Logger 
in order to fetch the correct Repository
    Logger log = Logger.getRootLogger();
    Fileappender fa = (FileAppender) log.getAppender( "MyFileAppender").
    fa.setFile( "myFile" );
    fa.activateOptions();
    ...
}
     
Hope this is clear enough. Else feel free to ask again.

Heri


> -----Original Message-----
> From: Dave Gomboc [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, June 29, 2005 4:22 PM
> To: 'Log4J Users List'
> Cc: Bender Heri
> Subject: RE: new user question re: configuring log4j via code
> 
> 
> I call the LoggingConfiguration "class"/glorified-global near the
> start of the main() routine.
> 
> I use ProcessBuilder.start() to launch other classes that have their
> own main() (which in turn also call LoggingConfiguration).  I do not
> see any indication in the ProcessBuilder docs that another JVM is
> created.  I am using J2SE 1.5/5.0 (the new one with generics and
> enum support -- and ProcessBuilder, for that matter).
> 
> Your questions give me the idea that the configuration happens too
> late -- the static Loggers are already initialized.  I'll try making
> them member variables of the respective classes.  But would this be
> "fighting log4j", e.g., maybe I should instead be attempting to use
> the properties configuration feature?
> 
> Dave
> 
> 
> > -----Original Message-----
> > From: Bender Heri [mailto:[EMAIL PROTECTED] 
> > Sent: June 29, 2005 1:28 AM
> > To: Log4J Users List
> > Subject: RE: new user question re: configuring log4j via code
> > 
> > Where and how do you call your LoggingConfiguration class exactly?
> > 
> > The code "private static Logger log = 
> > Logger.getLogger(Foo.Bar.class);" is called at class loading, 
> > before any "real" code is executed. 
> > 
> > In one JVM there is only one LogManager which has per default 
> > only one logger repository. So you will add a new appender to 
> > the very same root logger each time you call
> LoggingConfiguration().  
> > 
> > I dont really understand your "several independent processes" 
> > meaning. One JVM starts annother JVM? Or just other main 
> > classes? And, if the latter, are they running in its own 
> > thread context? If you want more help you have to clarify this.
> > 
> > Heri
> > 
> > > -----Original Message-----
> > > From: Dave Gomboc [mailto:[EMAIL PROTECTED]
> > > Sent: Tuesday, June 28, 2005 7:46 PM
> > > To: [email protected]
> > > Subject: new user question re: configuring log4j via code
> > > 
> > > 
> > > I have code to launch several independent processes, which 
> > then set up 
> > > socket connections with each other.  I'd like to use log4j 
> > to acquire 
> > > execution trace information to assist me in finding bugs in 
> > that code.
> > > 
> > > I have a LoggingConfiguration() that I call at the start of each
> 
> > > independent process to set up logging.  Currently the filename
> is 
> > > fixed, but I actually want to use the process id number as 
> > the name of 
> > > the log file (I just haven't done that yet).
> > > 
> > > Currently it's hardwired, but the file c:\trace.log doesn't 
> > showed up.
> > > I assume I'm missing something simple?  Almost all of the 
> > examples I 
> > > have seen use a configuration file (log4j.properties) 
> > instead of code 
> > > setup, but I didn't want to do this because I wanted the 
> > name of the 
> > > logfile to include the process id.
> > > 
> > > Here's LoggingConfiguration:
> > > 
> > > [package statement]
> > > 
> > > import org.apache.log4j.FileAppender;
> > > import org.apache.log4j.PatternLayout; import 
> > org.apache.log4j.Logger;
> > > 
> > > 
> > > public class LoggingConfiguration {
> > > 
> > >     LoggingConfiguration() {
> > > 
> > >         // Dump lots for now; figure out what I don't need
> later.
> > >         PatternLayout layout = new PatternLayout("%d %x %t %p %l
> 
> > > %throwable: %m%n");
> > > 
> > >         FileAppender fileAppender = new FileAppender();
> > >         fileAppender.setFile("c:\\trace.log");
> > >         fileAppender.setAppend(true);
> > >         fileAppender.setImmediateFlush(true);
> > >         fileAppender.setLayout(layout);
> > >         fileAppender.activateOptions();
> > > 
> > >         Logger log = Logger.getRootLogger();
> > >         log.addAppender(fileAppender);
> > >     };
> > > 
> > > };
> > > 
> > > 
> > > And in other files, I do:
> > > 
> > > [package...]
> > > [imports...]
> > > 
> > > public class Foo.Bar {
> > > 
> > >     private static Logger log = Logger.getLogger(Foo.Bar.class);
> > > 
> > > [and for each routine I am interested in]
> > > 
> > >     public boolean someRoutine() {
> > > 
> > >         log.trace("Entered.");
> > > 
> > >         [boolean result = ....;]
> > > 
> > >         log.trace("Exited: result = |{}|.", result);
> > >     };
> > > 
> > > };
> > > 
> > > 
> > > 1) What am I missing to make the log file (files, once I 
> > start using 
> > > the process id for the name) show up?
> > > 2) Is there anything else an experienced user sees that I am
> doing 
> > > incorrectly?
> > > 
> > > Thanks,
> > > Dave
> > > 
> > > 
> > > 
> >
> --------------------------------------------------------------------
> -
> > > To unsubscribe, e-mail:
> [EMAIL PROTECTED]
> > > For additional commands, e-mail:
> [EMAIL PROTECTED]
> > > 
> > > 
> > 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to