tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Patrick Luby <patrick.l...@sun.com>
Subject Re: JDK 1.4 Logging
Date Mon, 22 Jul 2002 16:43:05 GMT
Bob,

That would work. I forgot that Remy now puts out a JDK 1.4 build of 
Tomcat and using the build flags would allow it to be picked up by users 
of the JDK 1.4 builds.

Patrick

Bob Herrmann wrote:
> 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>


-- 
________________________________________________________________
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>


Mime
View raw message