首页 > 代码库 > Exception时信息的记录

Exception时信息的记录

系统总有出现异常的时候,那么出现异常时应该如何处理?

 

一直以来,我都以为这么处理就足够的:

  • 在日志中打印Exception的堆栈信息,以便排查原因
  • 反馈给用户系统xxx出现问题
package com.nicchagil.util.requestlogger;import java.io.IOException;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.log4j.Logger;public class RequestDemoServlet extends HttpServlet {        private final Logger logger = Logger.getLogger(RequestDemoServlet.class);           public RequestDemoServlet() {        super();    }    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {            ResultSet rs = null;        PreparedStatement pstmt = null;        Connection conn = null;        try {            Class.forName("oracle.jdbc.driver.OracleDriver");            conn = DriverManager.getConnection(                    "jdbc:oracle:thin:@hostname:port:sid", "username",                    "password");                        pstmt = conn.prepareStatement("select * from t_xxx t where t.id = ? ");                        pstmt.setString(1, "paramter");            rs = pstmt.executeQuery();                        while (rs.next()) {                System.out.println("‘" + rs.getString("result1") + "‘ - " + "‘" + rs.getString("result2") + "‘");            }                    } catch (ClassNotFoundException e) {            // Print exception logs            logger.error("Failed to query xxx", e);                        // Prompt that system error            response.getWriter().write("Failed to query xxx!");                    } catch (SQLException e) {            // Print exception logs            logger.error("Failed to query xxx", e);                        // Prompt that system error            response.getWriter().write("Failed to query xxx!");                    } catch (Throwable t) {            // Print exception logs            logger.error("System error", t);                        // Prompt that system error            response.getWriter().write("System error!");                    } finally {            try {                if (rs != null) {                    rs.close();                    rs = null;                }                if (pstmt != null) {                    pstmt.close();                    pstmt = null;                }                if (conn != null) {                    conn.close();                    conn = null;                }            } catch (SQLException e) {                // Print exception logs                logger.error("System error", e);                                // Prompt that system error                response.getWriter().write("System error!");            }        }        }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}
RequestDemoServlet

 

日前,得到一位资深同事Glen的指点,深知以上的操作是不足够的。

简单来说,我们需要记录,谁在什么时候做了什么事情

尽量详细地记录这些信息,让我们拥有更详细的信息用于排查问题(不知道请求参数的情况下,确实难以定位问题);在和其他团队作联合调试时,我们也可以提供足够的信息,不致陷于尴尬、被动地位。

  • 当前登录用户的ID或代号(在系统需要登录并用户已登录的前提下)
  • 当前请求的URL
  • 当前的请求参数

 

一般情况下,Web Project是在Servlet(或使用框架时所称的Action、Controller、Ctrl)处理Exception的。

除了“当前的请求参数”外,其他的都较好处理。因为每个请求的参数不尽一致,在每个Servlet都hardcode来打印各个参数,这是一个累人的活。

这里,分享一个静态方法用于打印HttpServletRequest的全部请求参数,这样就不致于每次都hardcode打印请求参数了。

package com.nicchagil.util.requestlogger;import java.util.Iterator;import java.util.Map;import javax.servlet.http.HttpServletRequest;public class RequestLogger {        /**     * toString for HttpServletRequest Parameters     * @param request     * @return     */    public static String toString(HttpServletRequest request) {                Map map = request.getParameterMap();                /* Since there are String[] in the map, can not return map.toString() directly. */                if (map == null || map.isEmpty()) {            return "";        }                StringBuffer sb = new StringBuffer();        Object key = null;        String[] value = null;        Iterator iterator = map.keySet().iterator();                while (iterator.hasNext()) {            key = iterator.next();            value = (String[])map.get(key);                        sb.append(key.toString()).append(" : ").append(toString(value, true));            sb.append("\n");        }                return sb.toString();    }        /**     * toString for String Array      * @param stringArray     * @return     */    public static String toString(String[] stringArray, boolean alwaysArray) {                if (stringArray == null || stringArray.length == 0) {            return "";        }                if (!alwaysArray) {            if (stringArray.length == 1) {                return stringArray[0];            }        }                StringBuffer sb = new StringBuffer();        sb.append("[");                for (int i = 0; i < stringArray.length; i++) {            sb.append(stringArray[i]);                        if (i < stringArray.length - 1) {                sb.append(", ");            }        }                sb.append("]");                return sb.toString();    }}
RequestLogger