日誌分級輸出到指定文件

 log4j.properties文件java

#根設置,輸出級別爲DEBUG級別, 輸出文件爲 ERRORA,stdout,DEBUGA
log4j.rootLogger=DEBUG,ERRORA,stdout,DEBUGA

#過濾掉spring框架下的額外日誌
#log4j.category.org.springframework = WARN

#輸出到控制檯
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c{1}:%L - %m%n

#輸出DEBUG信息到指定文件
log4j.appender.DEBUGA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DEBUGA.layout=org.apache.log4j.PatternLayout
log4j.appender.DEBUGA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.appender.DEBUGA.datePattern=yyyy-MM-dd'.log'
log4j.appender.DEBUGA.Threshold = DEBUG
log4j.appender.DEBUGA.append=true
log4j.appender.DEBUGA.File=d:/log/debug_log.log
log4j.appender.DEBUGA.filter.F1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.DEBUGA.filter.F1.LevelMin=DEBUG
log4j.appender.DEBUGA.filter.F1.LevelMax=INFO

#輸出error到指定文件
log4j.appender.ERRORA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ERRORA.layout=org.apache.log4j.PatternLayout
log4j.appender.ERRORA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.appender.ERRORA.datePattern=yyyy-MM-dd'.log'
log4j.appender.ERRORA.Threshold = ERROR
log4j.appender.ERRORA.append=true
log4j.appender.ERRORA.File=d:/errorlog/error_log.log

#打印sql語句
log4j.logger.com.ibatis=DEBUG
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

 

爲了對每一個請求的進行日誌輸出,咱們須要配置攔截器spring

<!-- 攔截器配置,攔截順序:先執行後定義的,排在第一位的最後執行。-->
<mvc:interceptors>
    <!-- API訪問日誌記錄攔截器 -->
    <mvc:interceptor>
        <mvc:mapping path="/user/**" />
        <bean class="com.utils.ApiLogInterceptor" />
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/childs/**" />
        <bean class="com.utils.ApiLogInterceptor" />
    </mvc:interceptor>

</mvc:interceptors>

開發自定義的攔截器,實現 HandlerInterceptor 接口sql

public class ApiLogInterceptor  implements HandlerInterceptor {

   private static final Logger logger = org.apache.log4j.Logger.getLogger(ApiLogInterceptor.class);

   private static final ThreadLocal<Long> startTimeThreadLocal =
         new NamedThreadLocal<Long>("ThreadLocal StartTime");
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
      if (logger.isDebugEnabled()){
         long beginTime = System.currentTimeMillis();//一、開始時間  
           startTimeThreadLocal.set(beginTime);      //線程綁定變量(該數據只有當前請求的線程可見)  
           logger.debug("開始計時: {"+new SimpleDateFormat("HH:mm:ss.SSS").format(beginTime)+"}  URI: {"+request.getRequestURI()+"}");
      }
      return true;
   }

   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
      if (modelAndView != null){
         logger.info("ViewName: " + modelAndView.getViewName());
      }
   }

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {

      logger.debug("Header: " + request.getHeader("user-agent"));
      logger.debug("RequestURI: " + request.getRequestURI());
      logger.debug("Method: " + request.getMethod());
      logger.debug("ParameterMap: " + request.getParameterMap().toString());

      // 打印JVM信息
      if (logger.isDebugEnabled()){
         long beginTime = startTimeThreadLocal.get();//獲得線程綁定的局部變量(開始時間)  
         long endTime = System.currentTimeMillis();     //二、結束時間  
         logger.debug("計時結束:{"+new SimpleDateFormat("HH:mm:ss.SSS").format(endTime)+"}  耗時:{"+DateUtils.formatDateTime(endTime - beginTime)+"}  URI: {"+request.getRequestURI()+"}  最大內存: {"+(Runtime.getRuntime().maxMemory()/1024/1024)+"}m  已分配內存: {"+(Runtime.getRuntime().totalMemory()/1024/1024)+"}m  已分配內存中的剩餘空間: {"+(Runtime.getRuntime().freeMemory()/1024/1024+"}m  最大可用內存: {"+(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024)+"}m") ;
      }
   }
}

 

自定義攔截器會針對 /user/** 和 /childs/** 的請求進行攔截,輸出日誌。apache

測試後發現,錯誤日誌既沒有在控制檯打印出來也沒有輸出到文件,由於咱們須要配置spring-mvc的全局異常處理器,實現 HandlerExceptionResolver  接口api

public class DefaultExceptionHandler implements HandlerExceptionResolver {

    private static final Logger logger = org.apache.log4j.Logger.getLogger(DefaultExceptionHandler.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        logger.error("異常信息", ex);

        String url = request.getRequestURL().toString();

        if (url.contains("api")) {
            try {
                /**
                 * 來自app的請求異常處理
                 */
                response.setStatus(HttpStatus.OK.value());
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(new Gson().toJson("系統錯誤"));
            } catch (IOException e) {
                logger.error("", e);
            }
        } else {
            ModelAndView mv = new ModelAndView();
            mv.setViewName("error");
            return mv;
        }

        return null;
    }

}

還須要在spring-mvc.xml中配置這個beanspring-mvc

<bean id="exceptionHandler" class="com.utils.DefaultExceptionHandler" />

 

再次運行項目,系統出現錯誤的時候,會跳轉到 error.jsp,錯誤信息會被輸出到 error_log 文件。mvc

相關文章
相關標籤/搜索