You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Bob Herrmann <bo...@jadn.com> on 2002/07/22 16:51:01 UTC

JDK 1.4 Logging

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



Re: JDK 1.4 Logging

Posted by Bob Herrmann <bo...@jadn.com>.
On Mon, 2002-07-22 at 12:37, Remy Maucherat wrote:
> 
> Assuming people actually like the JDK 1.4 logger and think it's useful, 
> I like that solution better (there are flags, use them).

The JDK Logger is pretty cool. Although the default output is pretty
plain. I use it with my own formatter. My formatter is tweaked for
Tomcat - so it condenses some information and colorizes some
information.

This is a sample of its output,

	http://hue.jadn.com:81/~bob/xdmp.png

My formatter is attached. It assumes an Xterm window sized to 175 or so.

Cheers,
-bob



Re: JDK 1.4 Logging

Posted by Remy Maucherat <re...@apache.org>.
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" 

Assuming people actually like the JDK 1.4 logger and think it's useful, 
I like that solution better (there are flags, use them).

Remy


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by Patrick Luby <pa...@sun.com>.
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:   <ma...@jakarta.apache.org>
>>>For additional commands, e-mail: <ma...@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:   <ma...@jakarta.apache.org>
>>For additional commands, e-mail: <ma...@jakarta.apache.org>
> 
> 
> 
> 
> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by Bob Herrmann <bo...@jadn.com>.
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:   <ma...@jakarta.apache.org>
> > For additional commands, e-mail: <ma...@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:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by Patrick Luby <pa...@sun.com>.
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:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by Remy Maucherat <re...@apache.org>.
costinm@covalent.net wrote:
> On 22 Jul 2002, Bob Herrmann wrote:
> 
> 
>>This could be fixed by adding these methods to Log of commons-logger
>>
>> void trace(Object msg, Throwable thr, String className, String method);
>> void debug(Object msg, Throwable thr, String className, String method);
>> void info(Object msg, Throwable thr, String className, String method);
>> void warn(Object msg, Throwable thr, String className, String method);
>> void error(Object msg, Throwable thr, String className, String method);
>> void fatal(Object msg, Throwable thr, String className, String method);
> 
> 
> I think there is a simpler solution for this class of problems, and 
> that would also work with log4j and doesn't require _any_ API change.
> ( only changes to the adapter implementations )
> 
> Any 'wrapper' will use:
>   factory=LogFactory.getFactory();
>    
>   factory.setAttribute( "commons-logging.wrapperClass", 
>                         "[CLASSNAME-OF-WRAPPER]");
>   factory.getLog(), etc.
> 
> The classname of wrapper will be passed to the impl..
> 
>  - for log4j - this just gets passed further, since log4j already supports 
> this feature.
>  - for jdk1.4 or other loggers who don't support wrapping - there is 
> already code in Jdk14Logger that walks the stack trace. Curently it
> uses a hard-coded '2 levels up', but it can use the wrapperClass
>  and walk up to find it.

Looks good :) +1.

Remy


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by co...@covalent.net.
On 22 Jul 2002, Bob Herrmann wrote:

> That is an interesting idea, although in my particular case, I walk
> the stack a variable amount. Namely if the stack has method "log()" or
> method "internalLog()" I keep unrolling the stack - this may not be
> a great idea - but it gives good stack traces without changing
> other parts of tomcat.

We'll walk a variable ammount as well - until the first class after 
wrapperClass ( i.e. we look for the caller of a method in wrapperClass ).

I don't think supporting wrappers which are wrapped by 
other wrappers is a goal :-)

Wrapping commons-logging ( which is a wrapper ) as a transition
mechanism should be enough.


> If a webapp wants to use its own logger wrapper, and the factory
> has a single attribute - would there be a conflict here?

That may be a problem. I'm not worried about webapps ( they 
shouldn't play with logger-wrapping :-), but about jasper
which may want to wrap as well.

There is a solution tough - add all the 'wrapperClass' 
passed to the factory to list, and check for any of them
when we un-wrap the stack. This will allow an unlimited number
of wrappers - as long as one wrapper doesn't call another wrapper
that wraps commons-logging, the wrapper. 

We should just use commons-logging - it is nice to have a 
smooth transition, but this should be just that, I don't 
think we should try to solve all the wrapping problems.

Costin


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by Bob Herrmann <bo...@jadn.com>.
On Mon, 2002-07-22 at 14:18, costinm@covalent.net wrote:
>...
> I think there is a simpler solution for this class of problems, and 
> that would also work with log4j and doesn't require _any_ API change.
> ( only changes to the adapter implementations )
> 
> Any 'wrapper' will use:
>   factory=LogFactory.getFactory();
>    
>   factory.setAttribute( "commons-logging.wrapperClass", 
>                         "[CLASSNAME-OF-WRAPPER]");
>   factory.getLog(), etc.
> 
> The classname of wrapper will be passed to the impl..
> 
>  - for log4j - this just gets passed further, since log4j already supports 
> this feature.
>  - for jdk1.4 or other loggers who don't support wrapping - there is 
> already code in Jdk14Logger that walks the stack trace. Curently it
> uses a hard-coded '2 levels up', but it can use the wrapperClass
>  and walk up to find it.

That is an interesting idea, although in my particular case, I walk
the stack a variable amount. Namely if the stack has method "log()" or
method "internalLog()" I keep unrolling the stack - this may not be
a great idea - but it gives good stack traces without changing
other parts of tomcat.

If a webapp wants to use its own logger wrapper, and the factory
has a single attribute - would there be a conflict here?

-bob





--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


[logging] [PATCH] JDK 1.4 Logging

Posted by Bob Herrmann <bo...@jadn.com>.
On Tue, 2002-07-23 at 15:03, Bob Herrmann wrote:
> On Mon, 2002-07-22 at 14:18, costinm@covalent.net wrote:
> > 
> > I think there is a simpler solution for this class of problems, and 
> > that would also work with log4j and doesn't require _any_ API change.
> > ( only changes to the adapter implementations )
> > 
> > Any 'wrapper' will use:
> >   factory=LogFactory.getFactory();
> >    
> >   factory.setAttribute( "commons-logging.wrapperClass", 
> >                         "[CLASSNAME-OF-WRAPPER]");
> >   factory.getLog(), etc.
> 

Hi.  This patch to commons logging allow you to specify which methods
in the call stack are uninteresting when using the JDK1.4 Logger. In
Tomcat this seems to be all methods named "log" and "internalLog."  This
is based on Costin's idea of uninteresting classes, but seems to work
better for method names (in Tomcat anyway.)

It is something of a back door.  It is primarily for projects that
are in the process of converting to using commons-logging.

Is this an acceptable change to commons-logging ?

Cheers,
-bob

P.S. this patch is updated from the one posted to tomcat-dev


[PATCH] Re: JDK 1.4 Logging

Posted by Bob Herrmann <bo...@jadn.com>.
On Mon, 2002-07-22 at 14:18, costinm@covalent.net wrote:
> 
> I think there is a simpler solution for this class of problems, and 
> that would also work with log4j and doesn't require _any_ API change.
> ( only changes to the adapter implementations )
> 
> Any 'wrapper' will use:
>   factory=LogFactory.getFactory();
>    
>   factory.setAttribute( "commons-logging.wrapperClass", 
>                         "[CLASSNAME-OF-WRAPPER]");
>   factory.getLog(), etc.

Ok, I experimented some with this.  I found that the "wrapperMethod"
(namely looking for method names "log()" and "internalLog()") are more
effective than a classname for identifying "uninteresting" stack frames.

Seems Tomcat has 71 classes with a method named "log()" and often
logs messages from within the class itself.

The attached "patch.txt is the Change to commons.

The CommonsLogger.java is a new tomcat logger that sends output
to the commons-logger.

Does this look good?

Cheers,
-bob



> 
> The classname of wrapper will be passed to the impl..
> 
>  - for log4j - this just gets passed further, since log4j already supports 
> this feature.
>  - for jdk1.4 or other loggers who don't support wrapping - there is 
> already code in Jdk14Logger that walks the stack trace. Curently it
> uses a hard-coded '2 levels up', but it can use the wrapperClass
>  and walk up to find it.
> 
> 
> Costin
> 
> 
> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by co...@covalent.net.
On 22 Jul 2002, Bob Herrmann wrote:

> This could be fixed by adding these methods to Log of commons-logger
> 
>  void trace(Object msg, Throwable thr, String className, String method);
>  void debug(Object msg, Throwable thr, String className, String method);
>  void info(Object msg, Throwable thr, String className, String method);
>  void warn(Object msg, Throwable thr, String className, String method);
>  void error(Object msg, Throwable thr, String className, String method);
>  void fatal(Object msg, Throwable thr, String className, String method);

I think there is a simpler solution for this class of problems, and 
that would also work with log4j and doesn't require _any_ API change.
( only changes to the adapter implementations )

Any 'wrapper' will use:
  factory=LogFactory.getFactory();
   
  factory.setAttribute( "commons-logging.wrapperClass", 
                        "[CLASSNAME-OF-WRAPPER]");
  factory.getLog(), etc.

The classname of wrapper will be passed to the impl..

 - for log4j - this just gets passed further, since log4j already supports 
this feature.
 - for jdk1.4 or other loggers who don't support wrapping - there is 
already code in Jdk14Logger that walks the stack trace. Curently it
uses a hard-coded '2 levels up', but it can use the wrapperClass
 and walk up to find it.


Costin


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by Bob Herrmann <bo...@jadn.com>.
On Mon, 2002-07-22 at 13:00, costinm@covalent.net wrote:
> I'm close to -1 on this patch.
> 
> I think the right long-term solution is to use commons-logging in
> all tomcat and jasper, and stop defining our interfaces.
> 
> I am +1 on fixing commons-logger, this will probably be
> usefull for other packages that switch to commons-logger.

I agree.  I originally implemented a commons-logger logger, but
the result wasn't very satisfying.  Mostly when the commons-logger
uses JDK1.4 it always shows my logger's class and method name.

This could be fixed by adding these methods to Log of commons-logger

 void trace(Object msg, Throwable thr, String className, String method);
 void debug(Object msg, Throwable thr, String className, String method);
 void info(Object msg, Throwable thr, String className, String method);
 void warn(Object msg, Throwable thr, String className, String method);
 void error(Object msg, Throwable thr, String className, String method);
 void fatal(Object msg, Throwable thr, String className, String method);

Although, the bigger problem is all the Loggers have unique features
and trying to squeeze them through the commons-logger API is going to
result in impedance mismatch.  Not sure what to do about this.

I can take stab at this little change (although it means touching
just about every class in commons-logging.)  Is it worth it?  Votes?

Cheers,
-bob

	


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by Remy Maucherat <re...@apache.org>.
costinm@covalent.net wrote:
> I'm close to -1 on this patch.
> 
> I think the right long-term solution is to use commons-logging in
> all tomcat and jasper, and stop defining our interfaces.
> 
> I am +1 on fixing commons-logger, this will probably be
> usefull for other packages that switch to commons-logger.

I share Costin's opinion on the subject: Tomcat should switch (over 
time) to commons-logging, not the individual loggers which are supposed 
to be abstracted by commons-logging.

Remy


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JDK 1.4 Logging

Posted by co...@covalent.net.
I'm close to -1 on this patch.

I think the right long-term solution is to use commons-logging in
all tomcat and jasper, and stop defining our interfaces.

I am +1 on fixing commons-logger, this will probably be
usefull for other packages that switch to commons-logger.


Costin


On 22 Jul 2002, 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
> 
> 
> 


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>