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