Invariant Properties

  • rss
  • Home

Log once or log early?

Bear Giles | October 16, 2010

First, a really good resource: Java antipatterns.  I plead the Fifth on how many of these things I still do on occasion.

I disagree on one point though – logging once.  I hate reading duplicate stack traces as much as everyone else but I think it’s a mistake to only log once.  What are the problems?

  • Swallowed Exceptions.  It still happens. A lot.  When it does you’ll lose all evidence of a problem unless you logged something earlier.
  • Summarized Exceptions. This is showing the message without the stack trace.  In an ideal world this would tell us exactly what we need to know but in practice it’s often a very generic message.
  • Lost Exceptions. A stack trace will recursively call getCause(). So far so good — but did you know that SQLException includes a nextException() method?  It’s used because a single problem will often cause multiple SQL exceptions and the ‘interesting’ one is usually not the one that’s ultimately propagated to the caller.  The standard stack trace method isn’t smart enough to follow these links.
  • Lost Information.  A stack trace shows the line where the exception occurred but tells us nothing about the context.

There are two sane alternatives.  The first approach is to look for the site of the (probable) original exception so you can catch it, log the method arguments and exception message and then rethrow the exception.   It’s a single line or two in the log and will give you a lot of insight into duplicating the problem.

The second approach is to write an AOP interceptor that you use liberally.  It’s a simple pass-through interceptor except that, in the event of an exception, it will log the method arguments before rethrowing the exception.  This gives you a stack trace complete with method arguments.

I like the second approach since it’s extremely powerful during development but can be easily from the production system.

  1. import java.util.logging.Logger;
  2. import javax.interceptor.AroundInvoke;
  3. import javax.interceptor.InvocationContext;
  4.  
  5. /*
  6.  * Simple interceptor that logs method arguments when an exception  occurs. A simple
  7.  * variant of this lets a method discover it's stack trace at any time. (Just remember
  8.  * to use a ThreadLocal Stack.)
  9.  *
  10.  * @author bgiles
  11.  */
  12. public class SimpleInterceptor {
  13.    private static final Logger log =    Logger.getLogger(SimpleInterceptor.class.getName());
  14.  
  15.    /**
  16.     * Simple interceptor that logs method arguments when an exception  occurs.
  17.     *
  18.     * @param invocation
  19.     * @return
  20.     * @throws Exception
  21.     */
  22.    @AroundInvoke
  23.    public Object logArgumentsOnException(InvocationContext invocation)
  24.        throws Exception {
  25.       Object results = null;
  26.  
  27.       try {
  28.          results = invocation.proceed();
  29.       } catch (Exception e) {
  30.          StringBuilder sb = new StringBuilder(invocation.getMethod().getName());
  31.          sb.append("(");
  32.  
  33.          for (Object o : invocation.getParameters()) {
  34.             sb.append(String.valueOf(o));
  35.             sb.append(", ");
  36.          }
  37.  
  38.          sb.setLength(sb.length() - 2);
  39.          sb.append("): ");
  40.          sb.append(e.getClass().getName());
  41.          sb.append(": ");
  42.          sb.append(e.getMessage());
  43.          log.warning(sb.toString());
  44.          throw e;
  45.       }
  46.       return results;
  47.    }
  48. }
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

/*
 * Simple interceptor that logs method arguments when an exception  occurs. A simple
 * variant of this lets a method discover it's stack trace at any time. (Just remember
 * to use a ThreadLocal Stack.)
 *
 * @author bgiles
 */
public class SimpleInterceptor {
   private static final Logger log =    Logger.getLogger(SimpleInterceptor.class.getName());

   /**
    * Simple interceptor that logs method arguments when an exception  occurs.
    *
    * @param invocation
    * @return
    * @throws Exception
    */
   @AroundInvoke
   public Object logArgumentsOnException(InvocationContext invocation)
       throws Exception {
      Object results = null;

      try {
         results = invocation.proceed();
      } catch (Exception e) {
         StringBuilder sb = new StringBuilder(invocation.getMethod().getName());
         sb.append("(");

         for (Object o : invocation.getParameters()) {
            sb.append(String.valueOf(o));
            sb.append(", ");
         }

         sb.setLength(sb.length() - 2);
         sb.append("): ");
         sb.append(e.getClass().getName());
         sb.append(": ");
         sb.append(e.getMessage());
         log.warning(sb.toString());
         throw e;
      }
      return results;
   }
}
Categories
Uncategorized
Comments rss
Comments rss
Trackback
Trackback

« Hot certifications Project Euler: Fibonacci Sequences »

Leave a Reply

Click here to cancel reply.

You must be logged in to post a comment.

Archives

  • May 2020 (1)
  • March 2019 (1)
  • August 2018 (1)
  • May 2018 (1)
  • February 2018 (1)
  • November 2017 (4)
  • January 2017 (3)
  • June 2016 (1)
  • May 2016 (1)
  • April 2016 (2)
  • March 2016 (1)
  • February 2016 (3)
  • January 2016 (6)
  • December 2015 (2)
  • November 2015 (3)
  • October 2015 (2)
  • August 2015 (4)
  • July 2015 (2)
  • June 2015 (2)
  • January 2015 (1)
  • December 2014 (6)
  • October 2014 (1)
  • September 2014 (2)
  • August 2014 (1)
  • July 2014 (1)
  • June 2014 (2)
  • May 2014 (2)
  • April 2014 (1)
  • March 2014 (1)
  • February 2014 (3)
  • January 2014 (6)
  • December 2013 (13)
  • November 2013 (6)
  • October 2013 (3)
  • September 2013 (2)
  • August 2013 (5)
  • June 2013 (1)
  • May 2013 (2)
  • March 2013 (1)
  • November 2012 (1)
  • October 2012 (3)
  • September 2012 (2)
  • May 2012 (6)
  • January 2012 (2)
  • December 2011 (12)
  • July 2011 (1)
  • June 2011 (2)
  • May 2011 (5)
  • April 2011 (6)
  • March 2011 (4)
  • February 2011 (3)
  • October 2010 (6)
  • September 2010 (8)

Recent Posts

  • 8-bit Breadboard Computer: Good Encapsulation!
  • Where are all the posts?
  • Better Ad Blocking Through Pi-Hole and Local Caching
  • The difference between APIs and SPIs
  • Hadoop: User Impersonation with Kerberos Authentication

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Pages

  • About Me
  • Notebook: Common XML Tasks
  • Notebook: Database/Webapp Security
  • Notebook: Development Tips

Syndication

Java Code Geeks

Know Your Rights

Support Bloggers' Rights
Demand Your dotRIGHTS

Security

  • Dark Reading
  • Krebs On Security Krebs On Security
  • Naked Security Naked Security
  • Schneier on Security Schneier on Security
  • TaoSecurity TaoSecurity

Politics

  • ACLU ACLU
  • EFF EFF

News

  • Ars technica Ars technica
  • Kevin Drum at Mother Jones Kevin Drum at Mother Jones
  • Raw Story Raw Story
  • Tech Dirt Tech Dirt
  • Vice Vice

Spam Blocked

53,793 spam blocked by Akismet
rss Comments rss valid xhtml 1.1 design by jide powered by Wordpress get firefox