1

EDIT2
@paradigmatic made a good point in suggesting to redirect rather than throw the exception; that solves the logging issue. The problem in Play 2 is that redirects need to occur within so-called Action scope, which is not always the case with date parser calls.

As a workaround, I went with Play's global interceptor, presumably the equivalent of a Java servlet filter.

val ymdMatcher = "\\d{8}".r // matcher for yyyyMMdd URI param
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
def ymd2Date(ymd: String) = ymdFormat.parseDateTime(ymd)

override def onRouteRequest(r: RequestHeader): Option[Handler] = {
  import play.api.i18n.Messages
  ymdMatcher.findFirstIn(r.uri) map{ ymd=>
    try { ymd2Date( ymd); super.onRouteRequest(r) }
    catch { case e:Exception => // kick to "bad" action handler on invalid date 
      Some(controllers.Application.bad(Messages("bad.date.format"))) 
    }
  } getOrElse(super.onRouteRequest(r))
}

EDIT
Here 's a little context to work with:

// String "pimp": transforms ymdString.to_date call into JodaTime instance
class String2Date(ymd: String) {
  def to_date = {  
    import play.api.i18n.Messages
    try{ ymdFormat.parseDateTime(ymd) } 
    catch { case e:Exception => throw new NoTrace(Messages("bad.date.format")) }
  }
  val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
}
@inline implicit final def string2Date(ymd: String) = new String2Date(ymd)

and a test custom exception handler:

public class NoTrace extends Exception {
  static final long serialVersionUID = -3387516993124229948L;

  @Override
  public Throwable fillInStackTrace() {
      return null;
  }      
  public NoTrace(String message) {
    super(message);
  }
}

Calling the date parser on an invalid yyyyMMdd string logs 30 line stack trace to the log (this occurs upstream by Play framework/Netty container, better than default 100 line trace):

"20120099".to_date

ORIGINAL
Have an issue where my application.log is getting filled with errors related to a uri date parser operation that should succeed given a valid yyyyMMdd uri date.

However, some users try to circumvent this by entering invalid dates in hopes of gaining free access to paid subscriber-only content. It's pointless, as it simply won't work, but regardless, I have MBs of these error traces in my application log.

Is there a way to throw a truly trimmed down Exception to the log? I found this SO answer, but in my application it looks like the container (Play framework on Netty) gets into the mix and logs its own 30 line stack trace to the log (30 lines is better than 100, but still 29 too many)

Similarly, I found this thread in regard to Java 7 and the new option to suppress stack trace; however, for some reason, despite being on Java 1.7, with Eclipse configured for Java 1.7, only the old 2 param method of Throwable is available (and I do see the 4 param method when I click through to the Throwable class; maybe a Scala 2.9.2 library issue?)

At any rate, ideally I can simply log a 1-line exception message and not the kitchen sink.

Community
  • 1
  • 1
virtualeyes
  • 11,147
  • 6
  • 56
  • 91
  • Write your code, you may not have printed the stack trace – Bhavik Ambani Nov 17 '12 at 12:01
  • 1
    Why is the Exception thrown in the fist place ? Is it possible to accept any date (valid and not) and redirect to a page when it's invalid ? – paradigmatic Nov 17 '12 at 12:45
  • @paradigmatic good point, the problem is that I believe in Play 2 Scala redirects have to occur within Action scope (e.g. "def index = Action { Ok.redirect("/foo") }"); uri date parser call site does not always occur within Action scope, so I have no way to redirect (you are correct that this is the preferred solution) – virtualeyes Nov 17 '12 at 12:51
  • I must have missed something, why can't you just catch the exception, and err.out whatever line you like? – lynks Nov 17 '12 at 12:54
  • @lynks because regardless of the message I pass into the Exception constructor, 100 additional lines of wondrous stack trace joy go with it into the log – virtualeyes Nov 17 '12 at 13:03

3 Answers3

3

Simply override this method in your custom exception class:

@Override
public Throwable fillInStackTrace() {
    return this;
}      

after adding this method your trace method will not print

DraxDomax
  • 1,008
  • 1
  • 9
  • 28
VRadhe
  • 529
  • 5
  • 8
2

Your trouble is that although you can suppress the stacktrace of the exception your own code threw, there is nothing you can do about the exception it will be wrapped into by the framework. The only avenue I can see is not allowing the framework to catch your exception at all (doing your own top-level handling) or tweaking the logging configuration.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
2

I think you have two options:

  1. Control the logging to not save stack traces for some exceptions.
  2. Write a post-processor that filters out the traces from the log file.

Unless you are in danger of running out of disk space, I think #2 is the better option, because if you do have a bug you can go back to the full log and have all the exception history.

The philosophy behind idea #2 is that disk space is cheap, but information can be precious during debug. Log a lot of data. Normally, use scripts to examine the log after it has been written to disk.

For example, if there is a type of log entry that you never expect to see, but that demands immediate action if it does appear, write a script that searches for it, and send you an e-mail if it finds one.

One of the most useful forms of script in this approach is one that drops stack trace lines. Usually, you only need to know what exceptions are happening, and the stack trace takes up a lot of screen space without telling you much. If you do need to investigate an exception, go back to the full log, find the exception line, and look at the stack trace and at what was happening immediately before the exception.

If there are too many of your date exceptions, have the script drop even the exception line. If you want to track how often they are happening, run a script that counts date exceptions per hour.

That sort of script typically costs a few minutes of programming in your favorite regex-capable script language.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
  • +1, disk space not an issue, it's more wanting relevant traces in the log. I'll tweak log4j and see if I can get this particular error condition logged without the trace. Thanks – virtualeyes Nov 17 '12 at 12:43
  • @virtualeyes I've expanded my answer based on the assumption that disk space is not an issue. – Patricia Shanahan Nov 17 '12 at 16:13