Return-Path: Delivered-To: apmail-logging-log4j-user-archive@www.apache.org Received: (qmail 82244 invoked from network); 24 Apr 2008 13:05:30 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 24 Apr 2008 13:05:30 -0000 Received: (qmail 54054 invoked by uid 500); 24 Apr 2008 13:05:25 -0000 Delivered-To: apmail-logging-log4j-user-archive@logging.apache.org Received: (qmail 54027 invoked by uid 500); 24 Apr 2008 13:05:25 -0000 Mailing-List: contact log4j-user-help@logging.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Log4J Users List" Reply-To: "Log4J Users List" Delivered-To: mailing list log4j-user@logging.apache.org Received: (qmail 54015 invoked by uid 99); 24 Apr 2008 13:05:25 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Apr 2008 06:05:25 -0700 X-ASF-Spam-Status: No, hits=2.0 required=10.0 tests=SPF_PASS,URIBL_BLACK X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: local policy) Received: from [207.239.111.117] (HELO NET2.mdinsurance.state.md.us) (207.239.111.117) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Apr 2008 13:04:32 +0000 Received: from MIAMAILDOMAIN1-MTA by NET2.mdinsurance.state.md.us with Novell_GroupWise; Thu, 24 Apr 2008 09:04:50 -0400 Message-Id: <48104D25.1915.0068.0@mdinsurance.state.md.us> X-Mailer: Novell GroupWise Internet Agent 7.0.2 Date: Thu, 24 Apr 2008 09:04:39 -0400 From: "Robert Pepersack" To: "Log4J Users List" Subject: Re: FileAppender Truncates Stack Trace References: <480F6211.1915.0068.0@mdinsurance.state.md.us> <9DABEA5B-3058-47C0-B1C0-F589C26748C3@apache.org> In-Reply-To: <9DABEA5B-3058-47C0-B1C0-F589C26748C3@apache.org> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline X-Virus-Checked: Checked by ClamAV on apache.org 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 =3D layout; } /** * Implement the abstract append method * inherited from AppenderSkeleton, which * AppenderSkeleton calls from doAppend(). */ public void append(LoggingEvent event) { ThrowableInformation throwableInfo =3D null; Throwable throwable =3D null; Throwable cause =3D null; String exceptionId =3D null; StackTraceElement[] stackTrace =3D null; String smallIndent =3D " "; String largeIndent =3D " at "; StringBuffer stringBuffer =3D 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 =3D event.getThrowableInformation()) !=3D 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 =3D throwableInfo.getThrowable()) !=3D null) { cause =3D throwable; // Drill down to the point where there is // no cause encapsulated by the current // cause. while(cause !=3D null) { stringBuffer.append(smallIndent); // "Caused by: " is unnecessary for the // outermost Throwable. if (cause !=3D throwable) { stringBuffer.append("Caused by: "); } stringBuffer.append(cause.toString() + "\n"); // Get the StackTraceElements for this cause. stackTrace =3D cause.getStackTrace(); // Loop through all of the StackTraceElements // for this cause and append them to the // StringBuffer. for(int i =3D 0; i < stackTrace.length; i++) { stringBuffer.append(largeIndent + stackTrace[i] + "\n"); } cause =3D 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 =3D true; } } Thanks, Bob >>> Curt Arnold 04/23/2008 6:19 PM >>> Okay, I'm assuming that somewhere this exception is passed to log4j in =20 something like: try { /// } catch(Exception ex) { logger.info("Some app message", ex); } Using a standard layout, the stack trace will get rendered by =20 WriterAppender.subAppend. this.qw.write(this.layout.format(event)); if(layout.ignoresThrowable()) { String[] s =3D event.getThrowableStrRep(); if (s !=3D null) { int len =3D s.length; for(int i =3D 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 =20 in org.apache.log4j.spi.LoggingEvent;getThrowableStrRep() to render =20 the exception which will eventually end up at =20 org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep() which =20 will then call the printStackTrace() method of the exception. The =20 SymSQLException.printStackTrace() implementation (or the underlying =20 JVM) is most likely the source of the ".. 14 more". At least as I understand the situation, OnlyOnceErrorHandler would not =20 be involved. It would only be involved if the appender was raising =20 exceptions and you mentioned using a FileAppender and a file appender =20 should not be raising SQL exceptions. A custom object renderer would not be useful unless the exception was =20 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 =20 write a custom appender (likely either wrapping or extending =20 PatternLayout) which returns false ignoresThrowable() and then appends =20 your custom equivalent to printStackTrace() the the result of the =20 PatternLayout.format. On Apr 23, 2008, at 3:28 PM, Matthew Kemp wrote: > You can create your own custom object renderer that will properly =20 > 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 =20 >> NULL >> value into column 'id', table 'table'; column does not allow nulls. =20 >> 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 =20 >> Source) >> at com.sybase.jdbc3.jdbc.SybStatement.nextResult(Unknown =20 >> Source) >> at com.sybase.jdbc3.jdbc.SybStatement.nextResult(Unknown =20 >> Source) >> at com.sybase.jdbc3.jdbc.SybStatement.queryLoop(Unknown Source) >> at =20 >> 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. =20 >> 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=20 >> For additional commands, e-mail: log4j-user-help@logging.apache.org=20 >> >> --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org=20 For additional commands, e-mail: log4j-user-help@logging.apache.org=20 --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org For additional commands, e-mail: log4j-user-help@logging.apache.org