TLOG日志框架springboot项目集成与扩展

目录

前言

一、TLOG开源组件集成

1.maven引入

2. 日志文件logback-spring.xml修改

二、TLOG扩展开发自己的starter

1.项目层级

2.扩展点:1.打印请求url 2.打印响应日志

a.打印请求日志中的url实现RequestBodyAdvice 

b.打印响应日志实现ResponseBodyAdvice

 c.打印内容

三、多线程与kafka消息队列,方法中traceId的传递

1.线程池

2.kafka等消息队列



前言

随着微服务盛行,很多公司都把系统按照业务边界拆成了很多微服务,在排错查日志的时候。因为业务链路贯穿着很多微服务节点,导致定位某个请求的日志以及上下游业务的日志会变得有些困难,那么今天所介绍的这款开源工具一定是一个不错的选择


一、TLOG开源组件集成

  1.maven引入

      
            com.yomahub
            tlog-all-spring-boot-starter
            ${tlog.version}
        

2. 日志文件logback-spring.xml修改



    
    

    
    

    
    
        
        ${LOG_PATH}/${LOG_NAME}/log_error.log
        
        
            
            ${LOG_PATH}/${LOG_NAME}/error/log-error-%d{yyyy-MM-dd}.%i.log
            
            
                10MB
            
        
        
        true
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level %logger{50} - %msg[%A][%R]%n
        
        
        
            error
            ACCEPT
            DENY
        
    


    
    
        
        ${LOG_PATH}/${LOG_NAME}/log_info.log
        
        
            
            ${LOG_PATH}/${LOG_NAME}/info/log-info-%d{yyyy-MM-dd}.%i.log
            
            
                10MB
            
        
        
        true
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level %logger{50} - %msg[%A][%R]%n
        
        
        
            info
            ACCEPT
            DENY
        
    

    
    
        ${LOG_PATH}/${LOG_NAME}/log_all.log
        
        
            
            ${LOG_PATH}/${LOG_NAME}/all/log-all-%d{yyyy-MM-dd}.%i.log
            
            
                10MB
            
        
        
        true
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level %logger{50} - %msg[%A][%R]%n
        
    

    
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level %logger{50} - %msg[%A][%R]%n
        
        
        
            debug
        
    

    
    
    
    

    
    
        
        
        

        
        
    

二、TLOG扩展开发自己的starter

1.项目层级

TLOG日志框架springboot项目集成与扩展_第1张图片

2.扩展点:1.打印请求url 2.打印响应日志

a.打印请求日志中的url实现RequestBodyAdvice 


/**
 * 日志请求拦截
 * @author liangxi.zeng
 */
@ControllerAdvice
@Component
public class LogRequestBodyAdvice implements RequestBodyAdvice {

    private static final Logger log = LoggerFactory.getLogger(LogRequestBodyAdvice.class);

    @Autowired
    private LogProperties logProperties;

    @Autowired
    private LogContext logContext;

    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class> aClass) {
        return logProperties.getResponse().isEnabled() && !StringUtils.isEmpty(TLogContext.getTraceId());
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class> aClass) throws IOException {
        return httpInputMessage;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class> aClass) {
        try {
            if(logProperties.getRequest().isEnabled()) {
                String url = logContext.getUrlTl().get();
                if (StringUtils.isEmpty(url)) {
                    url = LogUtil.getUrl(methodParameter);
                }
                if (!LogUtil.isIgnore(logProperties.getRequest().getIgnoreList(), url)) {
                    HttpHeaders headers = httpInputMessage.getHeaders();
                    if (headers != null) {
                        List contentTypeList = headers.get(LogUtil.CONTENT_TYPE);
                        if (!CollectionUtils.isEmpty(contentTypeList) &&
                                !LogUtil.isUpload(contentTypeList.get(0))) {
                            log.info("requestBody参数:{}", JSON.toJSONString(body));
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("日志请求打印异常,不影响业务,吞并异常",e);
        }
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class> aClass) {
        return body;
    }
}

b.打印响应日志实现ResponseBodyAdvice

/**
 * 脱敏日志响应拦截
 * @author liangxi.zeng
 */
@ControllerAdvice
@Component
public class LogResponseBodyAdvice implements ResponseBodyAdvice {

    private static final Logger log = LoggerFactory.getLogger(LogResponseBodyAdvice.class);

   @Autowired
   private LogProperties logProperties;

    @Autowired
    private LogContext logContext;

    @Override
    public boolean supports(MethodParameter returnType, Class> converterType) {
        return logProperties.getResponse().isEnabled() && !StringUtils.isEmpty(TLogContext.getTraceId());
    }

    /**
     * @param body
     * @param methodParameter
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType selectedContentType,
                                  Class> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        try {
            if(logProperties.getResponse().isEnabled()) {
                String url = logContext.getUrlTl().get();
                if (StringUtils.isEmpty(url)) {
                    url = LogUtil.getUrl(methodParameter);
                }
                if (!LogUtil.isIgnore(logProperties.getResponse().getIgnoreList(), url)) {
                    StringBuffer logBuffer = new StringBuffer("结束请求URL[{}]的调用,");
                    StopWatch stopWatch = logContext.getInvokeTimeTL().get();
                    if (Objects.nonNull(stopWatch)) {
                        stopWatch.stop();
                        logBuffer.append("耗时为:").append(stopWatch.getTime()).append("毫秒;");
                    }
                    if (LogUtil.isJson(selectedContentType.toString())) {
                        logBuffer.append("响应内容为:").append(JSON.toJSONString(body));
                    } else if (LogUtil.isUpload(selectedContentType.toString())) {
                        logBuffer.append("文件上传,无需打印上传");
                    } else {
                        logBuffer.append("响应内容为:").append(body);
                    }
                    log.info(logBuffer.toString(), url);
                }
            }
        } catch (Exception e) {
            log.error("日志响应打印异常,不影响业务,吞并异常",e);
        }
        return body;
    }


}

 c.打印内容

三、多线程与kafka消息队列,方法中traceId的传递

1.线程池

ExecutorService pool = Executors.newFixedThreadPool(5);
pool.submit(new TLogInheritableTask() {
    @Override
    public void runTask() {
      log.info("我是异步线程日志");
    }
});

2.kafka等消息队列

TLogMqWrapBean tLogMqWrap = new TLogMqWrapBean(bizBean);
mqClient.send(tLogMqWrap);

对于消费者端,你需要这么做:

//从mq里接受到tLogMqWrapBean
TLogMqConsumerProcessor.process(tLogMqWrapBean, new TLogMqRunner() {
    @Override
    public void mqConsume(BizBean o) {
	    //业务操作
    }
});

总结

TLog是一个轻量级的分布式日志标记追踪神器,10分钟即可接入,自动对日志打标签完成微服务的链路追踪。支持log4j,log4j2,logback三大日志框架,在我使用的时候,有些不满足业务需要,所以我自己在读了源码后进行了个性化定制,现在已经在项目中使用

你可能感兴趣的:(项目应用,java,TLOG,链路跟踪,多线程,消息队列,traceId)