>________________________________
> From: Jerry Malcolm <2ndgenfi...@gmail.com>
>To: Tomcat Users List <users@tomcat.apache.org> 
>Sent: Friday, December 2, 2011 6:45 PM
>Subject: Re: Logging - including host name in log file?
> 
>Thanks for all of your help.  I decided it was going to be difficult to
>maintain/update the static properties file for all of the different
>host/apps.  So I decided to pursue dynamic configuration at runtime (with
>success).  Each time I need a logger, I simply instantiate a tomcat
>FileHandler and build the file name from the catalina base, the server
>name, and the context.  This seems fairly straightforward, and again, it is
>working.  But if there is something in this implementation that's going to
>bite me, please let me know now.
>
>I've got it all working now, except for one specific situation... I have
>some servlets that run at startup.  I have googled and looked everywhere i
>can think of.... but I cannot figure out how to find the host name while
>inside a servlet init method.  In other situations, I pull the server name
>from the request object.  But when a servlet is running at startup, there
>is no request object.  I have a ServletConfig and can get the
>ServletContext.  But I can't find the host name in those.  A context runs
>in a host.  It seems to me that the context would report the host it is in,
>independent of whether a request is in progress of not.
>
>This is not a show-stopper on the overall logging transition for me.  But I
>would sure love to find a way to know the host that this context is running
>under without requiring a request object.
>
>Am I missing something obvious?
>
>Thanks again.
>
>Jerry
>
>On Fri, Dec 2, 2011 at 2:04 PM, Christopher Schultz <
>ch...@christopherschultz.net> wrote:
>
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Jerry,
>>
>> On 12/2/11 12:46 PM, Jerry Malcolm wrote:
>> > Ok, I'm digging into this.  Slowly but surely.... Just to
>> > confirm...
>> >
>> > So if I have, say 2 hosts, each with 3 web apps, and I want a
>> > different log file for each web app on each host, I need to define
>> > 6 of the following:
>> >
>> > 10host1webapp1.org.apache.juli.FileHandler.level = FINE
>> > 10host1webapp1.org.apache.juli.FileHandler.directory =
>> > ${catalina.base}/logs
>> > 10host1webapp1.org.apache.juli.FileHandler.prefix = Host1App1.
>>
>> Yes, although the format of the property base doesn't need to be that
>> complex. You could do this:
>>
>> Host1App1.level=FINE
>> Host1App1.directory=...
>> Host1App1.prefix=Host1App1.
>>
>> Tomcat has those odd property names so they will be unlikely to
>> conflict with anything you might want to define yourself.
>>
>> The magic happens here, when you actually configure Tomcat's logger(s):
>>
>> >
>> > And then define 6 of the following:
>> >
>> >
>> org.apache.catalina.core.ContainerBase.[Catalina].[host1].[/webapp1].level
>> >
>> >
>> = INFO
>> >
>> org.apache.catalina.core.ContainerBase.[Catalina].[host1].[/webapp1].handlers
>> >
>> >
>> = 10host1webapp1.org.apache.juli.FileHandler
>>
>> You could instead do:
>>
>>
>> org.apache.catalina.core.ContainerBase.[Catalina].[host1].[/webapp1].handlers=Host1App1
>>
>> > and I put all of this in /conf/logging.properties
>>
>> Yes: this will tell Tomcat that, when your webapp uses
>> ServletContext.log(...) that the output should go to those loggers
>> listed in the "handlers" property for that particular webapp.
>>
>> > All of this is required in order to get separate log files per
>> > webapp per host, right?
>>
>> - From ServletContext.log(..), yes.
>>
>> Again, if your webapp is logging in some other way, then Tomcat's
>> configuration does not apply at all. It's fairly common for webapps to
>> use their own logging mechanism rather than logging to the servlet
>> container, so I wouldn't be surprised if you have more work to do.
>>
>> - -chris


Here's something that I came up with for application-level logging. This is 
based on Apache commons-logging and log4j.

Please note that I'm a systems person, and only write Java code when I need to 
figure out how things are working (or not working).

I start out with a ServletContextListener, and two pieces of configuration.

In each Tomcat virtual host ($CATALINA_BASE/conf/[hostname]), I create a 
context.xml.default file. In it, I place a simple resource to retrieve via JNDI.

The context.xml.default file is documented:

http://tomcat.apache.org/tomcat-6.0-doc/config/context.html


The resource documentation is:

http://tomcat.apache.org/tomcat-6.0-doc/config/context.html#Environment Entries


So for example, a context.xml.default file can look like:

<?xml version="1.0" encoding="UTF-8"?>

<Context>
  <WatchedResource>WEB-INF/web.xml</WatchedResource>

  <Environment name="hostname" value="avirtualhost" type="java.lang.String"/>
</Context>

Now, in my application, I set up a base file name in log4j (log4j.xml) for my 
file appender. I use the Tomcat-defined variables, so the file name ends up 
looking like:

${catalina.base}/logs/applog.log

Finally, in the ServletContextListener, I do something like the following:
private Log log = LogFactory.getLog(this.getClass());


public void contextInitialized(ServletContextEvent sce) {
StringBuilder jndiValue = new StringBuilder();
StringBuilder nfname = new StringBuilder(128);

// get current log file name - assume that we're working with a
// FileAppender - maybe should check?
                // Hard coding names for now - not really a good idea
Logger wplog = Logger.getLogger("wplog");
FileAppender fa = (FileAppender) wplog.getAppender("FA");
String ofname = fa.getFile();

// get JNDI name - using a resource in context.xml.default
// see the Tomcat documentation for resources
try {
Context ictx = new InitialContext();
Context envctx = (Context) ictx.lookup("java:comp/env");
jndiValue.append((String) envctx.lookup("hostname"));
jndiValue.append("-");
jndiValue.trimToSize();
} catch (NamingException ex) {
ex.printStackTrace(); // ugly
}

// default host if things are horribly broken
if (jndiValue.length() == 0) {
jndiValue.append("foohost-");
jndiValue.trimToSize();
}

// insert the JNDI value plus a - before the file name portion of ofname
nfname.append(ofname);
                // should probably determine system separator here
int lastSep = nfname.lastIndexOf("/");
nfname.insert(lastSep + 1, jndiValue.toString());

// set the new name and activate
fa.setFile(nfname.toString());
fa.activateOptions();

// log in new place
log.info("Logging initialized and reset to new file name");
}

Obviously you can decouple names (a good thing) by using <context-param> 
elements in web.xml, go through all of the loggers and appenders (checking if 
the appenders are actually FileAppenders by using instanceof), and in general 
making this more production-worthy.

This ends up creating a zero-length file with the default name, and then all 
other logging goes to the new file.

The end result is that you can have multiple copies of the same web application 
hosted on different virtual hosts inside one CATALINA_BASE (or CATALINA_HOME) 
all writing to different log files, and all without modifying your source code.

Hope this isn't too ugly.

just my two cents . . . .

/mde/

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to