On Mon, 2002-07-22 at 14:18, [EMAIL PROTECTED] 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:   <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

/*
 * $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 [EMAIL PROTECTED]
 *
 * 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 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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Implementation of <b>Logger</b> that appends log messages to the
 * Commons logger 
 *
 * @version $Revision: $ $Date: $
 */

public class CommonsLogger
    extends LoggerBase
    implements Lifecycle {


    // ----------------------------------------------------- Instance Variables


    /**
     * The descriptive information about this implementation.
     */
    protected static final String info =
        "org.apache.catalina.logger.CommonsLogger/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 commons Log to which we are currently logging, if any.
     */
    private Log clog = null;


    /**
     * The domain that these messages are logged to
     */
    private String domain = "CommonsLogger";


    // ------------------------------------------------------------- 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 directory) {

        String oldDomain = this.domain;
        this.domain = domain;
        support.firePropertyChange("domain", oldDomain, this.domain);

        LogFactory.getFactory().setAttribute( "commons-logging.wrapperMethods", "log,internalLog" );

        clog = LogFactory.getLog(this.domain);
    }


    // --------------------------------------------------------- Public Methods

    /**
     * Writes an explanatory message and a stack trace for a given
     * <code>Throwable</code> exception to the commons 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){

        clog.info( message, exception );

    }

    /**
     * Writes an explanatory message and a stack trace for a given
     * <code>Throwable</code> exception to the commons 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){

        clog.info( message, throwable );

    }

    /**
     * Writes the specified message and exception to the servlet log file,
     * usually an event log, 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){
            switch(verbosity){
            case FATAL:
                clog.fatal(message);
                break;
            case ERROR:
                clog.error(message);
                break;
            case WARNING:
                clog.warn(message);
                break;
            case INFORMATION:
                clog.info(message);
                break;
            case DEBUG:
            default:
                clog.debug(message);
                break;
            }
        }
    }

    /**
     * Writes the specified message and exception to the servlet log file,
     * usually an event log, 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) {
            switch(verbosity){
            case FATAL:
                clog.fatal(message, throwable);
                break;
            case ERROR:
                clog.error(message, throwable);
                break;
            case WARNING:
                clog.warn(message, throwable);
                break;
            case INFORMATION:
                clog.info(message, throwable);
                break;
            case DEBUG:
            default:
                clog.debug(message, throwable);
                break;
            }
        }
    }

    /**
     * Writes the specified message to a the commons log
     *
     * @param message A <code>String</code> specifying the message to be logged
     */
    public void log(String message) {

        clog.info( message );
    }


    // ------------------------------------------------------ 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;

        clog = LogFactory.getLog(this.domain);
    }


    /**
     * 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;

    }


}


Index: src/java/org/apache/commons/logging/impl/Jdk14Logger.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/logging/src/java/org/apache/commons/logging/impl/Jdk14Logger.java,v
retrieving revision 1.4
diff -u -r1.4 Jdk14Logger.java
--- src/java/org/apache/commons/logging/impl/Jdk14Logger.java	17 Jul 2002 16:42:40 -0000	1.4
+++ src/java/org/apache/commons/logging/impl/Jdk14Logger.java	23 Jul 2002 18:58:29 -0000
@@ -65,8 +65,11 @@
 
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
 
 import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 
 /**
@@ -95,6 +98,14 @@
 
         logger = Logger.getLogger(name);
 
+        String wrapperMethods = (String) LogFactory.getFactory().getAttribute("commons-logging.wrapperMethods");
+        if ( wrapperMethods != null ){
+            StringTokenizer st = new StringTokenizer("wrapperMethods",",");
+            while (st.hasMoreTokens()) {
+                wrapperMethodsHash.put( st.nextToken(), "" );
+            }
+        }
+
     }
 
 
@@ -106,6 +117,11 @@
      */
     protected Logger logger = null;
 
+    /**
+     * The methods that we ignore in the stack trace
+     */
+    private Hashtable wrapperMethodsHash = new Hashtable();
+
 
     // --------------------------------------------------------- Public Methods
 
@@ -116,10 +132,16 @@
         // Caller will be the third element
         String cname="unknown";
         String method="unknown";
-        if( locations!=null && locations.length >2 ) {
-            StackTraceElement caller=locations[2];
-            cname=caller.getClassName();
-            method=caller.getMethodName();
+        if( locations!=null && locations.length>2 ) {
+            StackTraceElement caller=null;
+            for (int stackLevel=2;stackLevel<locations.length;stackLevel++){
+                caller = locations[stackLevel];
+                cname = caller.getClassName();
+                method = caller.getMethodName();
+                if ( wrapperMethodsHash.get( method ) == null ){
+                    break;
+                } 
+            }
         }
 
         if( ex==null ) {

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to