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