logging-log4j-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Robert Pepersack" <RPepers...@mdinsurance.state.md.us>
Subject Re: FileAppender Truncates Stack Trace
Date Thu, 24 Apr 2008 13:04:39 GMT
Thanks for your reply.

I've seen this behavior with many different exception classes, so I think it's the VM.

I've written a couple of appenders before.  For example, I wrote a SystemOutAppender that
solves this problem when printing to the console.  The source code for SystemOutAppender is
below.  How would I adapt this to work as DailyRollingFileAppender and FileAppender?

// SystemOutAppender.java

package myapp;

import org.apache.log4j.Layout;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.apache.log4j.AppenderSkeleton;


/**
 * SystemOutAppender is a custom log4j appender
 * that writes to the console using System.out.
 * Its output includes nested exceptions and their
 * stack traces.
 */
public class SystemOutAppender extends AppenderSkeleton
{

    /**
     * Default constructor.
     */
    public SystemOutAppender(){}


    /**
     * Construct an appender with the specified
     * Layout.
     */
    public SystemOutAppender(Layout layout)
    {
        this.layout = layout;
    }


    /**
     * Implement the abstract append method
     * inherited from AppenderSkeleton, which
     * AppenderSkeleton calls from doAppend().
     */
    public void append(LoggingEvent event)
    {
        ThrowableInformation throwableInfo = null;
        Throwable throwable = null;
        Throwable cause = null;
        String exceptionId = null;
        StackTraceElement[] stackTrace = null;
        String smallIndent = "      ";
        String largeIndent = "          at ";
        StringBuffer stringBuffer = new StringBuffer();

        // Print the information indicated by the
        // Layout.
        stringBuffer.append(this.layout.format(event));

        // Check to see if this LoggingEvent has
        // ThrowableInformation.
        if ((throwableInfo = event.getThrowableInformation()) != null)
        {
            // Check to see if there is a Throwable.
            // If there is a Throwable, check to see
            // if it is RuntimeApplicationException.  If
            // so, then get its exception ID.
            if ((throwable = throwableInfo.getThrowable()) != null)
            {
                cause = throwable;

                // Drill down to the point where there is
                // no cause encapsulated by the current
                // cause.
                while(cause != null)
                {
                    stringBuffer.append(smallIndent);

                    // "Caused by: " is unnecessary for the
                    // outermost Throwable.
                    if (cause != throwable)
                    {
                        stringBuffer.append("Caused by: ");
                    }

                    stringBuffer.append(cause.toString() + "\n");


                    // Get the StackTraceElements for this cause.
                    stackTrace = cause.getStackTrace();

                    // Loop through all of the StackTraceElements
                    // for this cause and append them to the
                    // StringBuffer.
                    for(int i = 0; i < stackTrace.length; i++)
                    {
                        stringBuffer.append(largeIndent +
                                            stackTrace[i] +
                                            "\n");
                    }

                    cause = cause.getCause();
                }
            }
        }

        // Print the contents of the StringBuffer.
        System.out.println(stringBuffer.toString());
    }


    public boolean requiresLayout()
    {
        return true;
    }


    public void close()
    {
        if (this.closed)
        {
            return;
        }

        this.closed = true;
    }

}

Thanks,

Bob

>>> Curt Arnold <carnold@apache.org> 04/23/2008 6:19 PM >>>
Okay, I'm assuming that somewhere this exception is passed to log4j in  
something like:

try {
      ///
} catch(Exception ex) {
     logger.info("Some app message", ex);
}

Using a standard layout, the stack trace will get rendered by  
WriterAppender.subAppend.

     this.qw.write(this.layout.format(event));

     if(layout.ignoresThrowable()) {
       String[] s = event.getThrowableStrRep();
       if (s != null) {
	int len = s.length;
	for(int i = 0; i < len; i++) {
	  this.qw.write(s[i]);
	  this.qw.write(Layout.LINE_SEP);
	}
       }
     }


Most appenders will return ignoreThrowable to true which will result  
in org.apache.log4j.spi.LoggingEvent;getThrowableStrRep() to render  
the exception which will eventually end up at  
org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep() which  
will then call the printStackTrace() method of the exception.  The  
SymSQLException.printStackTrace() implementation (or the underlying  
JVM) is most likely the source of the ".. 14 more".

At least as I understand the situation, OnlyOnceErrorHandler would not  
be involved.  It would only be involved if the appender was raising  
exceptions and you mentioned using a FileAppender and a file appender  
should not be raising SQL exceptions.

A custom object renderer would not be useful unless the exception was  
used as the message parameter, which is probably not the case.

The best way to add a custom rendering of the stack trace would be to  
write a custom appender (likely either wrapping or extending  
PatternLayout) which returns false ignoresThrowable() and then appends  
your custom equivalent to printStackTrace() the the result of the  
PatternLayout.format.



On Apr 23, 2008, at 3:28 PM, Matthew Kemp wrote:

> You can create your own custom object renderer that will properly  
> render the
> whole stack trace. This renderer will need to be included in the log4j
> config and be available on the classpath when log4j initializes.
>
>
> On Wed, Apr 23, 2008 at 3:19 PM, Robert Pepersack <
> RPepersack@mdinsurance.state.md.us> wrote:
>
>> Hello,
>>
>> I'm using FileAppender to log to a log file.  When an exception gets
>> caught and printed, the stack trace is truncated as it usually is by
>> default:
>>
>> Caused by: com.sybase.jdbc3.jdbc.SybSQLException: Attempt to insert  
>> NULL
>> value into column 'id', table 'table'; column does not allow nulls.  
>> Update
>> fails.
>>
>>       at com.sybase.jdbc3.tds.Tds.a(Unknown Source)
>>       at com.sybase.jdbc3.tds.Tds.nextResult(Unknown Source)
>>       at com.sybase.jdbc3.jdbc.ResultGetter.nextResult(Unknown  
>> Source)
>>       at com.sybase.jdbc3.jdbc.SybStatement.nextResult(Unknown  
>> Source)
>>       at com.sybase.jdbc3.jdbc.SybStatement.nextResult(Unknown  
>> Source)
>>       at com.sybase.jdbc3.jdbc.SybStatement.queryLoop(Unknown Source)
>>       at  
>> com.sybase.jdbc3.jdbc.SybCallableStatement.executeQuery(Unknown
>> Source)
>>       at miaJs.jdbc.JdbcFacade.executeQuery(JdbcFacade.java:977)
>>       ... 14 more
>>
>> Instead of  the "... 14 more" at the bottom, I would like to see the
>> entire stack trace.  I know how to get Java to do this by using
>> Throwable.getStackTrace(), and then loop through the array of
>> StackTraceElements.  I looked in the log4j source code.  I think that
>> FileAppender uses the OnlyOnceErrorHandler in its super, superclass
>> AppenderSkeleton.  It looks like OnlyOnceErrorHandler uses LogLog.   
>> But, I'm
>> not sure how to get log4j to print the entire stack trace.
>>
>> Thanks,
>>
>> Bob
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
>> For additional commands, e-mail: log4j-user-help@logging.apache.org 
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org 
For additional commands, e-mail: log4j-user-help@logging.apache.org 


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Mime
View raw message