zoukankan      html  css  js  c++  java
  • Dropwizard+jersey+MDC实现日志跟踪以及接口响应时间统计

    一、实现接口响应时间统计

    1.1添加全局请求过滤器并注册

    import org.apache.log4j.MDC;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.ws.rs.container.ContainerRequestContext;
    import javax.ws.rs.container.ContainerRequestFilter;
    import javax.ws.rs.container.ContainerResponseContext;
    import javax.ws.rs.container.ContainerResponseFilter;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.ext.Provider;
    
    /**
     * @Autor zhangjiawen
     * @Date: 2020/4/10 13:33
     */
    
    @Provider
    public class RequestLogFilter implements ContainerRequestFilter, ContainerResponseFilter {
        private final String BEGIN_LOG="beginLog";
        private static final Logger logger = LoggerFactory.getLogger(RequestLogFilter.class);
    
    
    
        @Override
        public void filter(ContainerRequestContext requestContext)  {
            try {
                String traceId = TraceLogUtils.getTraceId();
                MDC.put(Constants.LOG_TRACE_ID, traceId);
                LogBean logBean = new LogBean(traceId, System.currentTimeMillis());
                // MDC.put(traceId,logBean);  也可将请求参数放到MDC不用缓存,但是我用MDC存对象报类型转换异常不知咋回事,故缓存缓存保存
                requestContext.setProperty(BEGIN_LOG, traceId);
                LogThreadPoolExecutor.getInstance().getThreadPool().submit(() -> {
                    //将请求存入缓存
                    RequestCache.getInstance().add(logBean.getTraceID(), logBean);
                    logger.info("traceid:" + logBean.getTraceID() + " uri: " + requestContext.getUriInfo().getRequestUri()
                            + " method:" + requestContext.getMethod()
                            + " parameters:" + requestContext.getUriInfo().getPathParameters().toString());
                });
            }catch (Exception e){
                e.printStackTrace();
            }
    
    
        }
    
        @Override
        public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)  {
            try{
                long currentTime=System.currentTimeMillis();
                if(requestContext.getProperty(BEGIN_LOG)!=null){
                String  traceID=(String) requestContext.getProperty(BEGIN_LOG);
                LogThreadPoolExecutor.getInstance().getThreadPool().submit(() -> {
                    try {
                        //读取traceid  异步去缓存中取 并消费
                        LogBean logBean = RequestCache.getInstance().get(traceID);
                        StringBuilder sb = new StringBuilder();
                        sb.append("traceid:" + logBean.getTraceID()).append(" ,").append(responseContext.getStatus()).append(" ,")
                                .append(responseContext.getStatusInfo()).append(",  response:{");
                        if(responseContext.getStatus()== Response.Status.CREATED.getStatusCode()){  //文件上传类型没有Entity 故单独处理
                            sb.append(responseContext.getHeaders().getFirst("Location"));
                        }else if(responseContext.getEntity()!=null){
                        sb.append(responseContext.getEntity());}                   
                        sb.append("} usedTime:").append((currentTime - logBean.getRequestDate()) + "(ms)");
                        logger.info(sb.toString());
                        RequestCache.getInstance().remove(traceID);
                        MDC.clear();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                });
            }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    注册过滤器

    environment.jersey().register(RequestLogFilter.class);

    缓存类

    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * @Autor zhangjiawen
     * @Date: 2020/4/13 8:55
     */
    public class RequestCache {
        private  ConcurrentHashMap<String, LogBean> requesMap=null;
    
        private RequestCache(){
            requesMap=new ConcurrentHashMap<>();
        }
    
        private static RequestCache instance = new RequestCache();
    
        public static RequestCache getInstance(){
            return instance;
        }
    
        public void  add(String key,LogBean logBean){
            this.requesMap.put(key,logBean);
        }
        public LogBean get(String key){
           return this.requesMap.get(key);
        }
        public void remove(String key){
            this.requesMap.remove(key);
        }
    
    }

    线程池

    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @Autor zhangjiawen
     * @Date: 2020/4/13 15:48
     */
    public class LogThreadPoolExecutor {
        private ThreadPoolExecutor tpe =null;
        BlockingQueue<Runnable> bq = new ArrayBlockingQueue<Runnable>(10);
        private static LogThreadPoolExecutor logThreadPool=new LogThreadPoolExecutor();
    
        private LogThreadPoolExecutor(){
            tpe= new ThreadPoolExecutor(5,
                    10,
                    500,
                    TimeUnit.MILLISECONDS,
                    new ArrayBlockingQueue<Runnable>(10));
        }
        public static LogThreadPoolExecutor  getInstance(){
            return logThreadPool;
        }
        public ThreadPoolExecutor getThreadPool(){
            return this.tpe;
        }
    
    
    }

    常量类

    /**
     * @Autor zhangjiawen
     * @Date: 2020/4/13 10:15
     */
    public class Constants {
    
        /**
         * 日志跟踪id名。
         */
        public static final String LOG_TRACE_ID = "traceid";
    
        /**
         * 请求头跟踪id名。
         */
        public static final String HTTP_HEADER_TRACE_ID = "app_trace_id";
    }

    日志实体类

    import java.io.Serializable;
    import java.util.UUID;
    
    /**
     * @Autor zhangjiawen
     * @Date: 2020/4/10 15:43
     */
    
    public class LogBean implements Serializable {
        private String traceID;
        private long requestDate;
    
        public LogBean(String traceID, long requestDate) {
            this.traceID = traceID;
            this.requestDate = requestDate;
        }
    
        public LogBean(long requestDate) {
            this.requestDate = requestDate;
            this.traceID=UUID.randomUUID().toString();
        }
    
        public String getTraceID() {
            return traceID;
        }
    
        public void setTraceID(String traceID) {
            this.traceID = traceID;
        }
    
        public long getRequestDate() {
            return requestDate;
        }
    
        public void setRequestDate(long requestDate) {
            this.requestDate = requestDate;
        }
    }

    二、实现日志报错跟踪(为每个异常添加一个串联的traceid)

    添加一个全局异常过滤器

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.slf4j.MDC;
    
    import javax.ws.rs.core.Response;
    import javax.ws.rs.ext.ExceptionMapper;
    import javax.ws.rs.ext.Provider;
    
    /**全局异常过滤
     * @Autor zhangjiawen
     * @Date: 2020/4/13 11:24
     */
    @Provider
    public class GlobalTraceException implements ExceptionMapper<Exception> {
        private static final Logger logger = LoggerFactory.getLogger(GlobalTraceException.class);
        @Override
        public Response toResponse(Exception  e) {
            Response.ResponseBuilder responseBuilder = null;
            try {
                StringBuilder sb = new StringBuilder();
                sb.append(Constants.LOG_TRACE_ID + ": ").append(MDC.get(Constants.LOG_TRACE_ID) == null ? "" : MDC.get(Constants.LOG_TRACE_ID));
            //此处将MDC中traceid 取出并加到报错信息前边 logger.error(sb
    + " error: {}", e.getMessage(), e); ErrorEntity entity = new ErrorEntity(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage()); responseBuilder = Response.ok(entity); }catch (Exception e2){ e2.printStackTrace(); } return responseBuilder.build(); } }

    错误实体类

    //import javax.xml.bind.annotation.XmlRootElement;
    
    /**
     * @Autor zhangjiawen
     * @Date: 2020/4/13 13:23
     */
    //@XmlRootElement//标识该资源可以被jersey转为json或者xml
    public class ErrorEntity {
        private int resp_err_code;
        private String resp_err_msg;
    
        public ErrorEntity(int resp_err_code, String resp_err_msg) {
            this.resp_err_code = resp_err_code;
            this.resp_err_msg = resp_err_msg;
        }
    
        public int getResp_err_code() {
            return resp_err_code;
        }
    
        public void setResp_err_code(int resp_err_code) {
            this.resp_err_code = resp_err_code;
        }
    
        public String getResp_err_msg() {
            return resp_err_msg;
        }
    
        public void setResp_err_msg(String resp_err_msg) {
            this.resp_err_msg = resp_err_msg;
        }
    }

    注册过滤器

    environment.jersey().register(GlobalTraceException.class);

    效果如下

  • 相关阅读:
    桟错误分析方法
    gstreamer调试命令
    sqlite的事务和锁,很透彻的讲解 【转】
    严重: Exception starting filter struts2 java.lang.NullPointerException (转载)
    eclipse 快捷键
    POJ 1099 Square Ice
    HDU 1013 Digital Roots
    HDU 1087 Super Jumping! Jumping! Jumping!(动态规划)
    HDU 1159 Common Subsequence
    HDU 1069 Monkey and Banana(动态规划)
  • 原文地址:https://www.cnblogs.com/jiawen010/p/12703069.html
Copyright © 2011-2022 走看看