2012-11-17 87 views
1

EDIT2
@paradigmatic提出了重定向而不是抛出异常的好处;解决了日志记录问题。 Play 2中的问题是重定向需要在所谓的Action范围内发生,而日期解析器调用并非总是如此。Java 7:抛出没有堆栈跟踪的异常

作为一种解决方法,我使用了Play的全局拦截器,大概相当于一个Java servlet过滤器。

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)) 
} 

编辑
这里有一个小范围内一起工作:

// 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) 

和测试自定义异常处理程序:

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

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

上调用一个无效的年月日的日期解析器字符串记录30行堆栈跟踪到日志(这发生在Play框架/ Netty容器的上游,是tter比默认的100线迹):

"20120099".to_date 

ORIGINAL
有在我的application.log是越来越充满了与该应该成功提供有效的yyyyMMdd URI日期URI日期解析器操作失误的问题。

但是,一些用户试图通过输入无效日期来避免这种情况,希望获得免费访问付费用户专用内容。这是毫无意义的,因为它根本无法工作,但无论如何,我的应用程序日志中都有这些错误跟踪的MB。

有没有办法将一个真正修剪到日志中的Exception?我发现this SO answer,但在我的应用程序中,它看起来像容器(Netty上的Play框架)进入混合并将其自己的30行堆栈跟踪记录到日志中(30行比100好,但仍有29太多)

同样,我发现this thread在Java 7和新的选项抑制堆栈跟踪;然而,出于某种原因,尽管使用了Java 1.7,但为Java 1.7配置了Eclipse,但只有Throwable的旧2参数方法可用(并且在单击到Throwable类时可以看到4参数方法;也许是Scala 2.9.2库问题?)

无论如何,理想情况下,我可以简单地记录单行异常消息而不是厨房水槽。

+0

写下你的代码,你可能没有打印堆栈跟踪 –

+1

为什么在第一个地方抛出Exception?是否有可能接受任何日期(有效与否),并在无效时重定向到页面? – paradigmatic

+0

@paradigmatic好点,问题是我相信Play 2 Scala重定向必须发生在Action范围内(例如“def index = Action {Ok.redirect(”/ foo“)}”); uri日期解析器调用站点并不总是出现在Action范围内,所以我没有办法重定向(你是对的,这是首选解决方案) – virtualeyes

回答

2

你的问题是,虽然你可以抑制你自己的代码抛出异常的堆栈跟踪,但是你不能对它将被框架封装的异常做任何事情。我能看到的唯一途径是不允许框架根据您的异常(执行您自己的顶级处理)或调整日志记录配置。

+0

+1,尽管这不是我想听到的;-)也许调整log4j config会给我希望有灵活性。谢谢 – virtualeyes

1

我认为你有两个选择:

  1. 控制记录不保存堆栈跟踪一些例外。
  2. 编写一个后处理器,用于过滤掉日志文件中的痕迹。

除非您有磁盘空间不足的危险,否则我认为#2是更好的选择,因为如果您确实有错误,则可以返回完整日志并获取所有异常历史记录。

想法#2背后的理念是磁盘空间很便宜,但在调试过程中信息可能很珍贵。记录大量数据。通常情况下,使用脚本将日志写入磁盘后检查日志。

例如,如果有一种您不希望看到的日志条目类型,但如果它确实出现需要立即采取措施,请编写一个脚本来搜索它,并在发现电子邮件时发送给您一。

这种方法中最有用的脚本形式之一是删除堆栈跟踪行。通常,您只需要知道发生了什么异常,并且堆栈跟踪占用很多屏幕空间而不会告诉你很多。如果您确实需要调查异常,请返回完整日志,查找异常行,并查看堆栈跟踪以及紧接异常之前发生的事情。

如果您的日期例外太多,请让脚本放下即使是异常行。如果您想跟踪它们发生的频率,请运行一个脚本来计算每小时的日期异常。

这种脚本通常会花费几分钟的时间用最喜欢的正则表达式语言编程。

+0

+1,磁盘空间不是问题,它更需要日志中的相关痕迹。我会调整log4j,看看我是否可以在没有跟踪的情况下记录这个特定的错误条件。谢谢 – virtualeyes

+0

@virtualeyes我根据磁盘空间不是问题的假设扩展了我的答案。 –