private void fillTraceContext(CharsetDetectRequestWrapper reqWrapper) { TraceContext traceContext = TraceContext.get(); Pair<String, String> traceAndStep = FilterHelpers.getTraceIdAndRpcId(reqWrapper); traceContext.setTraceId(traceAndStep.first); traceContext.setParentRpcId(traceAndStep.second); traceContext.setSpider(FilterHelpers.isSpider(reqWrapper)); traceContext.setColor(FilterHelpers.isColorized(reqWrapper)).setFail(false); }
private void copyResponse(HttpServletResponse res, BufferedResponseWrapper wrapper) throws IOException { if (wrapper.isError()) { res.setContentType("text/html; charset=UTF-8"); res.sendError(wrapper.getStatus()); } // 发送响应内容 wrapper.flushBuffer(); if (wrapper.getLength() > 0) { if (wrapper.isGZipped()) { res.setHeader("Content-Encoding", "gzip"); } if (!res.isCommitted()) { String traceId = TraceContext.get().getTraceId(); if (!Strings.isNullOrEmpty(traceId)) { res.setHeader("x-trace-id", traceId); } res.setContentLength(wrapper.getLength()); wrapper.writeTo(res.getOutputStream()); res.flushBuffer(); } } }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; // 设定请求开始时间 FilterHelpers.getRequestTime(req); if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(req)) { // Proceed without invoking this filter... chain.doFilter(request, response); } else { // Do invoke this filter... request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE); CharsetDetectRequestWrapper reqWrapper = new CharsetDetectRequestWrapper(req); boolean gzip = false; // 是否启用GZip压缩 if (enableGZip) { String encoding = req.getHeader("Accept-Encoding"); if (encoding != null && encoding.contains("gzip")) { gzip = true; } } BufferedResponseWrapper resWrapper = new BufferedResponseWrapper(res, gzip); try { // XXX: 生成traceId,需要请求_traceId的参数,所以必须放到CharsetEncodingHandler后面 fillTraceContext(reqWrapper); chain.doFilter(reqWrapper, resWrapper); if (TraceContext.get().isColor()) { Cookie cookie = new Cookie("_color", "1"); cookie.setMaxAge(3600); cookie.setPath("/"); resWrapper.addCookie(cookie); } } catch (Exception e) { LOG.error("{}", req.getRequestURL(), e); resWrapper.setStatus(500); // 这里把异常抛出去,针对服务端异常,接入层nginx可以统计到,否则就统计不到 throw new ServletException( req.getRequestURL() + ", message: " + e.getMessage(), e.getCause()); } finally { request.removeAttribute(alreadyFilteredAttributeName); try { if (resWrapper.getLocation() != null) { res.sendRedirect(resWrapper.getLocation()); } else { setContentType(res); try { copyResponse(res, resWrapper); } catch (Exception e) { long cost = FilterHelpers.getCostTime(req); LOG.error("{}, cost={}ms", req.getRequestURL(), cost, e); } } } finally { TraceContext c = TraceContext.get(); TraceContext.remove(); // 染色日志发送到总线上 if (c.isColor()) { sendTrace(req, c, resWrapper); } // 统计页面状态信息 PageStatusReporter.getInstance().stat(req, c.getCost(), res.getStatus(), c.isSpider()); } } } }