tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mark Eggers <>
Subject Re: Logging - including host name in log file?
Date Sat, 03 Dec 2011 04:12:50 GMT
> From: Jerry Malcolm <>
>To: Tomcat Users List <> 
>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.
>On Fri, Dec 2, 2011 at 2:04 PM, Christopher Schultz <
>> wrote:
>> 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:
>> >
>> > = FINE
>> > =
>> > ${catalina.base}/logs
>> > = Host1App1.
>> Yes, although the format of the property base doesn't need to be that
>> complex. You could do this:
>> Host1App1.level=FINE
>> 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
>> >
>> >
>> =
>> You could instead do:
>> org.apache.catalina.core.ContainerBase.[Catalina].[host1].[/webapp1].handlers=Host1App1
>> > and I put all of this in /conf/
>> 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:

The resource documentation is: Entries

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

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


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

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:


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"));
} catch (NamingException ex) {
ex.printStackTrace(); // ugly

// default host if things are horribly broken
if (jndiValue.length() == 0) {

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

// set the new name and activate

// log in new place"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 . . . .


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message