@Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    // HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    StatHttpServletResponseWrapper responseWrapper =
        new StatHttpServletResponseWrapper(httpResponse);

    final String method = request.getParameter(Constants.SYS_PARAM_KEY_METHOD);
    final String appkey = request.getParameter(Constants.SYS_PARAM_KEY_APPKEY);
    long startNano = System.nanoTime();
    long startMillis = System.currentTimeMillis();

    serviceAppStat.beforeInvoke();

    ServiceMethodStat methodStat = serviceAppStat.getMethodStat(appkey, method);
    if (methodStat == null) {
      methodStat = serviceAppStat.getMethodStat(appkey, method);
    }

    if (methodStat != null) {
      methodStat.beforeInvoke(startMillis);
    }

    Throwable error = null;
    try {
      chain.doFilter(request, responseWrapper);
    } catch (IOException e) {
      error = e;
      throw e;
    } catch (ServletException e) {
      error = e;
      throw e;
    } catch (RuntimeException e) {
      error = e;
      throw e;
    } catch (Error e) {
      error = e;
      throw e;
    } finally {
      long endNano = System.nanoTime();
      long nanos = endNano - startNano;
      serviceAppStat.afterInvoke(error, nanos);

      if (methodStat != null) {
        methodStat.afterInvoke(error, nanos);
        request.setAttribute(SERVICE_EXEC_TIME, nanos / (1000 * 1000));
      }
    }
  }
 @Override
 public void destroy() {
   serviceAppStat.destroy();
 }