package cn.org.rapid_framework.web.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.filter.OncePerRequestFilter;
import cn.org.rapid_framework.web.util.FilterConfigUtils;
/**
* 性能filter。
*
* <p>
* web.xml配置文件格式如下:
* <pre><![CDATA[
<filter>
<filter-name>PerformanceFilter</filter-name>
<filter-class>cn.org.rapid_framework.web.filter.PerformanceFilter</filter-class>
<init-param>
<param-name>threshold</param-name>
<param-value>3000</param-value>
</init-param>
</filter>
]]></pre>
* </p>
*
* <p>
* 其中<code>threshold</code>参数表明超时阈值,如果处理的总时间超过该值,则filter会以warning的方式记录该次操作。
* </p>
*
* @author badqiu
*
*/
public class PerformanceFilter extends OncePerRequestFilter implements Filter {
int threshold = 3000;
boolean includeQueryString = false;
private static final Log log = LogFactory.getLog(PerformanceFilter.class);
public void destroy() {
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String requestString = dumpRequest(request);
Throwable failed = null;
long start = System.currentTimeMillis();
try {
chain.doFilter(request, response);
} catch (Throwable e) {
failed = e;
rethrowThrowable(failed);
} finally {
long duration = System.currentTimeMillis() - start;
if (failed != null) {
log.error("["+requestString+",F,"+duration+"ms");
} else if (duration > threshold) {
log.warn("["+requestString+",Y,"+duration+"ms");
} else if (log.isInfoEnabled()) {
log.info("["+requestString+",Y,"+duration+"ms");
}
}
}
private static void rethrowThrowable(Throwable failed) throws Error, IOException, ServletException {
if (failed != null) {
if (failed instanceof Error) {
throw (Error) failed;
} else if (failed instanceof RuntimeException) {
throw (RuntimeException) failed;
} else if (failed instanceof IOException) {
throw (IOException) failed;
} else if (failed instanceof ServletException) {
throw (ServletException) failed;
}else {
throw new RuntimeException(failed);
}
}
}
@Override
public void initFilterBean() throws ServletException {
this.threshold = FilterConfigUtils.getIntParameter(getFilterConfig(), "threshold", threshold);
this.includeQueryString = FilterConfigUtils.getBooleanParameter(getFilterConfig(), "includeQueryString", includeQueryString);
log.info("PerformanceFilter started with threshold:"+threshold+"ms includeQueryString:"+includeQueryString);
}
/**
* 取得request的内容(HTTP方法, URI)
*
* @param request HTTP请求
*
* @return 字符串
*/
protected String dumpRequest(ServletRequest request) {
HttpServletRequest req = (HttpServletRequest)request;
StringBuffer buffer = new StringBuffer(req.getMethod());
buffer.append("__").append(req.getRequestURI());
if(includeQueryString) {
String queryString = req.getQueryString();
if (StringUtils.isNotBlank(queryString)) {
buffer.append("?").append(queryString);
}
}
return buffer.toString();
}
}