tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bob Herrmann <...@jadn.com>
Subject Re: JDK 1.4 Logging
Date Mon, 22 Jul 2002 16:35:48 GMT

Humm...  How about this instead (not that I am lazy)?

$ cvs diff -u catalina/build.xml
Index: catalina/build.xml
===================================================================
RCS file: /home/cvspublic/jakarta-tomcat-4.0/catalina/build.xml,v
retrieving revision 1.124
diff -u -r1.124 build.xml
--- catalina/build.xml	29 Jun 2002 01:00:04 -0000	1.124
+++ catalina/build.xml	22 Jul 2002 16:31:07 -0000
@@ -801,6 +801,8 @@
        unless="jdk.1.3.present"/>
       <exclude name="org/apache/catalina/servlets/CGIServlet.java" 
        unless="jdk.1.3.present"/>
+      <exclude name="org/apache/catalina/logger/JdkLogger.java"
+       unless="jdk.1.4.present"/>
       <exclude name="org/apache/naming/NamingService.java"
        unless="compile.jmx"/>
       <exclude
name="org/apache/naming/factory/DbcpDataSourceFactory.java" 


On Mon, 2002-07-22 at 12:28, Patrick Luby wrote:
> Bob,
> 
> This is a useful piece of code. However, your patch can't go into Tomcat 
> as it will only compile with JDK 1.4. The standard builds of Tomcat that 
> are downloadable from the jakarta.apache.org are built using JDK 1.3 and 
> should be run without crashing Tomcat on JDK 1.2.
> 
> So, if you would like this in Tomcat (and I think it would be a nice 
> optional logger implementation), I think that you need to do the following:
> 
> 1. Remove all of the following import statements and replace them with
>     reflection calls so that the JDK 1.3 compiler can compile this class:
> 
>     import java.util.logging.Logger;
>     import java.util.logging.Level;
>     import java.util.logging.Formatter;
>     import java.util.logging.Handler;
>     import java.util.logging.LogRecord;
> 
> 2. Catch any ClassNotFound and MethodNotFound exceptions that will occur
>     when the code is run on JDK 1.2 or 1.3.
> 
> Patrick
> 
> 
> 
> 
> Bob Herrmann wrote:
> > Hi.  I am trying to get Tomcat to log to JDK1.4's logging.
> > 
> > I tried implementing a "o.a.c.logging.Logger" subclass that forwarded
> > calls to commons-logging Log.  This was unsatisfying because the
> > commons-logger unrolls the stack and logs the "class.method" of my
> > logger, not my logger's caller. 
> > 
> > I was tempted to change the commons-logger to allow for specifying
> > a class and method on all its methods, but that would be a large
> > change the commons-logger (involving changes and decisions about
> > how this new information should be pushed down and handled with
> > the other loggers it supports.)  There is also some issues mapping
> > tomcat verbosity levels, to common-logger log levels and then to JDK
> > Logger levels.
> > 
> > So I punted and implemented the code below.  It is a
> > "o.a.c.logging.Logger" which writes directly to JDK 1.4 Logging.
> > It allowed me to unroll the stack in a way that fits well with
> > tomcat (ignoring stack frames calling with method log() or method
> > internalLog() which are uninteresting.)  And allowed me to map
> > verbosity to JDK Levels.
> > 
> > Cheers,
> > -bob
> > 
> > 
> > 
> > 
> > ------------------------------------------------------------------------
> > 
> > /*
> >  * $Header: $
> >  * $Revision: $
> >  * $Date: $
> >  *
> >  * ====================================================================
> >  *
> >  * The Apache Software License, Version 1.1
> >  *
> >  * Copyright (c) 1999 The Apache Software Foundation.  All rights
> >  * reserved.
> >  *
> >  * Redistribution and use in source and binary forms, with or without
> >  * modification, are permitted provided that the following conditions
> >  * are met:
> >  *
> >  * 1. Redistributions of source code must retain the above copyright
> >  *    notice, this list of conditions and the following disclaimer.
> >  *
> >  * 2. Redistributions in binary form must reproduce the above copyright
> >  *    notice, this list of conditions and the following disclaimer in
> >  *    the documentation and/or other materials provided with the
> >  *    distribution.
> >  *
> >  * 3. The end-user documentation included with the redistribution, if
> >  *    any, must include the following acknowlegement:
> >  *       "This product includes software developed by the
> >  *        Apache Software Foundation (http://www.apache.org/)."
> >  *    Alternately, this acknowlegement may appear in the software itself,
> >  *    if and wherever such third-party acknowlegements normally appear.
> >  *
> >  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
> >  *    Foundation" must not be used to endorse or promote products derived
> >  *    from this software without prior written permission. For written
> >  *    permission, please contact apache@apache.org.
> >  *
> >  * 5. Products derived from this software may not be called "Apache"
> >  *    nor may "Apache" appear in their names without prior written
> >  *    permission of the Apache Group.
> >  *
> >  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
> >  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> >  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> >  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
> >  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> >  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> >  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> >  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> >  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> >  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
> >  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> >  * SUCH DAMAGE.
> >  * ====================================================================
> >  *
> >  * This software consists of voluntary contributions made by many
> >  * individuals on behalf of the Apache Software Foundation.  For more
> >  * information on the Apache Software Foundation, please see
> >  * <http://www.apache.org/>.
> >  *
> >  * [Additional notices, if required by prior licensing conditions]
> >  *
> >  */
> > 
> > 
> > package org.apache.catalina.logger;
> > 
> > import java.sql.Timestamp;
> > 
> > import org.apache.catalina.Lifecycle;
> > import org.apache.catalina.LifecycleEvent;
> > import org.apache.catalina.LifecycleException;
> > import org.apache.catalina.LifecycleListener;
> > import org.apache.catalina.util.LifecycleSupport;
> > import org.apache.catalina.util.StringManager;
> > 
> > import java.util.logging.Logger;
> > import java.util.logging.Level;
> > import java.util.logging.Formatter;
> > import java.util.logging.Handler;
> > import java.util.logging.LogRecord;
> > 
> > 
> > /**
> >  * Implementation of <b>Logger</b> that sends log messages to the
> >  * Jdk logger 
> >  *
> >  * @version $Revision: $ $Date: $
> >  */
> > 
> > public class JdkLogger
> >     extends LoggerBase
> >     implements Lifecycle {
> > 
> > 
> >     // ----------------------------------------------------- Instance Variables
> > 
> > 
> >     /**
> >      * The descriptive information about this implementation.
> >      */
> >     protected static final String info =
> >         "org.apache.catalina.logger.JdkLogger/1.0";
> > 
> >     /**
> >      * The lifecycle event support for this component.
> >      */
> >     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
> > 
> >     /**
> >      * The string manager for this package.
> >      */
> >     private StringManager sm =
> >         StringManager.getManager(Constants.Package);
> > 
> >     /**
> >      * Has this component been started?
> >      */
> >     private boolean started = false;
> > 
> > 
> >     /**
> >      * The default JDK logging domain that these messages are logged to
> >      */
> >     private String domain = "tomcat";
> > 
> > 
> >     /**
> >      * The we are using.  We set it immediately incase we get calls
> >      */
> >     private Logger jlog = Logger.getLogger(domain);
> > 
> > 
> >     // ------------------------------------------------------------- Properties
> > 
> > 
> > 
> >     /**
> >      * Return the logging domain in which we create log files.
> >      */
> >     public String getDomain() {
> > 
> >         return (domain);
> > 
> >     }
> > 
> > 
> >     /**
> >      * Set the domain in which we send our log files
> >      *
> >      * @param domain The new domain
> >      */
> >     public void setDomain(String domain) {
> > 
> >         String oldDomain = this.domain;
> >         this.domain = domain;
> >         support.firePropertyChange("domain", oldDomain, this.domain);
> > 
> > 	// there doesnt seem to be any semantics for changing a Logger's name, so
> > 	// we just replace it.
> > 	jlog = Logger.getLogger(domain);
> >     }
> > 
> > 
> >     // --------------------------------------------------------- Public Methods
> > 
> >     /**
> >      * Writes an explanatory message and a stack trace for a given
> >      * <code>Throwable</code> exception to the logger.
> >      * This message will be logged unconditionally.
> >      *
> >      * @param message A <code>String</code> that describes the error
or
> >      *  exception
> >      * @param exception The <code>Exception</code> error or exception
> >      */
> >     public void log(Exception exception, String message){
> > 	logCallerStack( Level.INFO, message, exception );
> >     }
> > 
> >     /**
> >      * Writes an explanatory message and a stack trace for a given
> >      * <code>Throwable</code> exception to the logger
> >      * This message will be logged unconditionally.
> >      *
> >      * @param message A <code>String</code> that describes the error
or
> >      *  exception
> >      * @param throwable The <code>Throwable</code> error or exception
> >      */
> >     public void log(String message, Throwable throwable){
> > 	logCallerStack( Level.INFO, message, throwable );
> >     }
> >    
> >     /**
> >      * Writes the specified message and exception to the logger,
> >      * if the logger is set to a verbosity level equal
> >      * to or higher than the specified value for this message.
> >      *
> >      * @param message A <code>String</code> the message to log
> >      * @param verbosity Verbosity level of this message
> >      */
> >     public void log(String message, int verbosity){
> >         if (this.verbosity < verbosity)
> > 	    return;
> > 
> > 	// Translate tomcat verbosity into JDK Levels
> > 	Level jlevel = Level.INFO;
> > 	if ( verbosity == FATAL )        jlevel = Level.SEVERE;
> > 	else if ( verbosity == ERROR )   jlevel = Level.SEVERE;
> > 	else if ( verbosity == WARNING ) jlevel = Level.WARNING;
> > 	else if ( verbosity == DEBUG )   jlevel = Level.FINE;
> > 
> > 	logCallerStack( jlevel, message, null );
> >     }
> > 
> >     /**
> >      * Writes the specified message and exception to the logger,
> >      * if the logger is set to a verbosity level equal
> >      * to or higher than the specified value for this message.
> >      *
> >      * @param message A <code>String</code> that describes the error
or
> >      *  exception
> >      * @param throwable The <code>Throwable</code> error or exception
> >      * @param verbosity Verbosity level of this message
> >      */
> >     public void log(String message, Throwable throwable, int verbosity){
> >         if (this.verbosity < verbosity) 
> > 	    return;
> > 
> > 	// Translate tomcat verbosity into JDK Levels
> > 	Level jlevel = Level.INFO;
> > 	if ( verbosity == FATAL )        jlevel = Level.SEVERE;
> > 	else if ( verbosity == ERROR )   jlevel = Level.SEVERE;
> > 	else if ( verbosity == WARNING ) jlevel = Level.WARNING;
> > 	else if ( verbosity == DEBUG )   jlevel = Level.FINE;
> > 
> > 	logCallerStack( jlevel, message, throwable );
> >     }
> > 
> > 
> >     /**
> >      * Writes the specified message to a the logger
> >      *
> >      * @param message A <code>String</code> specifying the message to
be logged
> >      */
> >     public void log(String message) {
> > 	logCallerStack( Level.INFO, message, null );
> >     }
> > 
> > 
> >     // -------------------------------------------------------- Private Methods
> > 
> >     /**
> >      * Writes the specified message to a the logger and attempts to unroll
> >      * the stack to include the Class and method of the caller. Trys to be
> >      * clever by detecting other wrappers around logging (ie. frames with
> >      * methods name log() and internalLog() are skipped in determing the
> >      * messages stack of origin)
> >      *
> >      * @param jLevel A <code>java.util.logging.Level</code> instance
to indicate the desired logging level
> >      * @param message A <code>String</code> specifying the message to
be logged
> >      * @param throwable The <code>Throwable</code> error or exception
> >      */
> >     private void logCallerStack( Level jlevel, String message, Throwable throwable
){
> >         // Hack (?) to get the stack trace.
> >         Throwable dummyException=new Throwable();
> >         StackTraceElement locations[]=dummyException.getStackTrace();
> >         // Caller will be the third element
> >         String cname="unknown";
> >         String method="unknown";
> > 
> > 	// tomcat has methods named log() and internalLog() that are sometimes on the stack
> >         if( locations!=null && locations.length >2 ) {
> > 	    StackTraceElement caller=null;
> > 	    for (int stackLevel=2;stackLevel<locations.length;stackLevel++){
> > 		caller = locations[stackLevel];
> > 		method=caller.getMethodName();
> > 		if ( !method.equals("log") && !method.equals("internalLog") ){
> > 		    cname=caller.getClassName();
> > 		    // method += " [DEPTH "+stackLevel+"]";  uncomment this to see how much stack
walking is going on.
> > 		    break;
> > 		}
> > 	    }
> > 	}
> >         if( throwable==null ) {
> >             jlog.logp( jlevel, cname, method, message );
> >         } else {
> >             jlog.logp( jlevel, cname, method, message, throwable );
> >         }
> > 
> >     }
> > 
> > 
> >     // ------------------------------------------------------ Lifecycle Methods
> > 
> > 
> >     /**
> >      * Add a lifecycle event listener to this component.
> >      *
> >      * @param listener The listener to add
> >      */
> >     public void addLifecycleListener(LifecycleListener listener) {
> > 
> >         lifecycle.addLifecycleListener(listener);
> > 
> >     }
> > 
> > 
> >     /**
> >      * Get the lifecycle listeners associated with this lifecycle. If this 
> >      * Lifecycle has no listeners registered, a zero-length array is returned.
> >      */
> >     public LifecycleListener[] findLifecycleListeners() {
> > 
> >         return lifecycle.findLifecycleListeners();
> > 
> >     }
> > 
> > 
> >     /**
> >      * Remove a lifecycle event listener from this component.
> >      *
> >      * @param listener The listener to add
> >      */
> >     public void removeLifecycleListener(LifecycleListener listener) {
> > 
> >         lifecycle.removeLifecycleListener(listener);
> > 
> >     }
> > 
> > 
> >     /**
> >      * Prepare for the beginning of active use of the public methods of this
> >      * component.  This method should be called after <code>configure()</code>,
> >      * and before any of the public methods of the component are utilized.
> >      *
> >      * @exception LifecycleException if this component detects a fatal error
> >      *  that prevents this component from being used
> >      */
> >     public void start() throws LifecycleException {
> > 
> >         // Validate and update our current component state
> >         if (started)
> >             throw new LifecycleException( "alreadyStarted");
> >         lifecycle.fireLifecycleEvent(START_EVENT, null);
> >         started = true;
> > 
> >     }
> > 
> > 
> >     /**
> >      * Gracefully terminate the active use of the public methods of this
> >      * component.  This method should be the last one called on a given
> >      * instance of this component.
> >      *
> >      * @exception LifecycleException if this component detects a fatal error
> >      *  that needs to be reported
> >      */
> >     public void stop() throws LifecycleException {
> > 
> >         // Validate and update our current component state
> >         if (!started)
> >             throw new LifecycleException("notStarted");
> >         lifecycle.fireLifecycleEvent(STOP_EVENT, null);
> >         started = false;
> > 
> >     }
> > 
> > 
> > }
> > 
> > 
> > 
> > 
> > 
> > ------------------------------------------------------------------------
> > 
> > --
> > To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
> > For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>
> 
> 
> -- 
> ________________________________________________________________
> Patrick Luby                     Email: patrick.luby@sun.com
> Sun Microsystems                         Phone: 408-276-7471
> 901 San Antonio Road, USCA14-303
> Palo Alto, CA 94303-4900
> ________________________________________________________________
> 
> 
> --
> To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
> For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>



--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>


Mime
View raw message