在Java中提取用户友好的异常详细信息

时间:2010-05-07 17:46:55

标签: java logging java-ee exception

我有一个我正在处理的J2EE Web应用程序,当发生异常时,我想获得有关异常的一些基本细节并记录它。我正在记录的消息应该是非常基本的,这可能对运行Web服务器的人有意义。

使用e.getMessage()是最好的记录吗?感谢。

5 个答案:

答案 0 :(得分:3)

可能。问题是,如果没有至少调用方法信息,这不是非常有用

考虑以下内容

/**
 * Returns <i>class.method:linenumber</i> of the caller (or, more accurately
 * the caller of the caller).
 * </p>
 *
 * <p>
 * Returns unknown if stacktrace is mucked up. Uses reflection and string
 * concatenation, so don't overuse this for trivial matters. For exception
 * handling and for logging, on the other hand, it is useful.
 *
 * @return method name of caller's caller and line number (String)
 */
public static String returnCaller( Class ignoreMe )
{

    String              ignoreClass = ignoreMe.getName();
    StackTraceElement[] steArr      = new Throwable().getStackTrace();

    if (steArr != null)
    {
        // subscript 1 is returnCaller().
        // subscript 2 is the caller of returnCaller()
        // subscript 3 is the caller of the caller of returnCaller()...
        for( int i = 0; i < steArr.length; i++)
        {
            if (steArr[i] == null)
                break;

            String myclass = steArr[i].getClassName();

            if (myclass.equals(ErrorHandle.class.getName()))
                continue;

            if (ignoreClass.equals(myclass))
                continue;

            return steArr[i].getClassName()
                    + "."
                    + steArr[i].getMethodName()
                    + ":"
                    + steArr[i].getLineNumber();
        }
    }

    return "unknown";
}

答案 1 :(得分:3)

我做了一些非常相似的事情。但首先,您根本不需要将错误传达给用户。告诉他们错误是如何发生的,因为你无论如何都会记录错误。 (如果用户知道由于NPE或IO错误而发生错误,即使您将其重命名为更“友好”的术语,这是否有意义?)

首先,您可能需要考虑re-throwing all of your Exceptions as runtime (unchecked) exceptions。这将强制集中和一致地记录错误。否则,您将不得不希望错误处理代码的每个实例都能正确记录它。要重新抛出SQLExceptions,例如:

    try{
        conn.close();
    } catch(SQLException ex){
        //logger.error("Cannot close connection"); //don't log this here, do it centrally
        throw new RuntimeException(ex);
    }

您需要将用户转发到常规错误页面,只是告诉他们发生了错误。这向他们表明他们所做的一切都没有得到处理。这非常重要,因此他们不会反击并不断尝试一次又一次地输入付款。让他们知道出现问题以及(a)联系服务台或(b)将表单放在默认错误页面中,该页面可以记录故障单或向服务台发送电子邮件。要完成此任务,您需要在web.xml中定义:

<error-page>
  <error-code>500</error-code>
  <location>/Error.jsp</location>
</error-page>

接下来,在error.jsp页面(或servlet)内部,如果容器允许您将堆栈跟踪引用为request.getAttribute("javax.servlet.error.message"));,请在此处记录错误。

,创建一个仅对响应起作用的过滤器,如下所示:

try {
    chain.doFilter(req, res);
 } catch (Exception e) {
    logger.error("pass any Mapped Diagnostic Context here", e); //log here, centrally
    throw new RuntimeException(e); //throws back to the container so that the error page will be seen
}

这将捕获所有传播的异常(未经检查和未被捕获),记录它们,然后重新抛出它们以便它们调用错误页面。这将导致错误报告

  1. 准确(每个错误实例一个日志)
  2. 可靠(如果用户收到错误,则会收到记录详细信息
  3. 一致(标准化,如果您实施重新抛出已检查的异常未经检查,您将能够看到所有异常,并且还会阻止用户进入容易出错的区域,因为他们插入了废话,因此您面临着灾难性数据清理任务的风险进入表格或左表未填充的关键表)
  4. 最后,您可能需要考虑使用log4j并使用输出到某处的appender,您可以查看错误,而无需等待操作团队将它们发送给您。如果您经常维护应用程序,那么就更容易了。

答案 2 :(得分:2)

仅记录异常消息不是一个好主意;你失去了发生异常的那一行,这使得在代码中找到记录的异常大多数时候都是噩梦。

记录整个异常/堆栈跟踪。

答案 3 :(得分:1)

我默认获得整个堆栈跟踪,这样我就可以看到错误发生时发生的更多上下文。

如果你使用log4j并将异常传递给它的一个日志记录方法,它将打印你给它的任何消息,加上异常的消息及其堆栈跟踪:

log.error("caught an exception", throwable);

如果您有容易出错的事情,例如调用Web服务,您可以将异常中包含的异常包装为您分配非常明确的消息,因此当管理员看到该消息时会告诉他们发生了什么。

就此而言,您可以保留单独的日志,一个用于开发人员的堆栈跟踪,另一个用于编写管理员友好的消息。您可以使用异常处理程序尝试将异常映射到友好消息,然后将该消息写入管理日志。

答案 4 :(得分:0)

如果您只是想通知系统管理员,那个问题出了问题,但是没有开发人员必须查看它,因为它是一些暂时已知的问题,或者可以通过系统管理员解决,一个好的描述性消息就足够了。在所有其他情况下,每个开发人员都非常感谢在异常时获得完整的堆栈跟踪以及系统状态(输入参数等等)(如果可用)。