TLOG日志框架springboot项目集成与扩展
创始人
2025-05-29 07:21:21
0

目录

前言

一、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.yomahubtlog-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.log10MBtrue%d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level %logger{50} - %msg[%A][%R]%nerrorACCEPTDENY${LOG_PATH}/${LOG_NAME}/log_info.log${LOG_PATH}/${LOG_NAME}/info/log-info-%d{yyyy-MM-dd}.%i.log10MBtrue%d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level %logger{50} - %msg[%A][%R]%ninfoACCEPTDENY${LOG_PATH}/${LOG_NAME}/log_all.log${LOG_PATH}/${LOG_NAME}/all/log-all-%d{yyyy-MM-dd}.%i.log10MBtrue%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]%ndebug

二、TLOG扩展开发自己的starter

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);@Autowiredprivate LogProperties logProperties;@Autowiredprivate LogContext logContext;@Overridepublic boolean supports(MethodParameter methodParameter, Type type, Class> aClass) {return logProperties.getResponse().isEnabled() && !StringUtils.isEmpty(TLogContext.getTraceId());}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class> aClass) throws IOException {return httpInputMessage;}@Overridepublic 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;}@Overridepublic 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);@Autowiredprivate LogProperties logProperties;@Autowiredprivate LogContext logContext;@Overridepublic 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*/@Overridepublic 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() {@Overridepublic void runTask() {log.info("我是异步线程日志");}
});

2.kafka等消息队列

TLogMqWrapBean tLogMqWrap = new TLogMqWrapBean(bizBean);
mqClient.send(tLogMqWrap);对于消费者端,你需要这么做://从mq里接受到tLogMqWrapBean
TLogMqConsumerProcessor.process(tLogMqWrapBean, new TLogMqRunner() {@Overridepublic void mqConsume(BizBean o) {//业务操作}
});

总结

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

相关内容

热门资讯

【十二天学java】day04... 第一章 流程控制语句 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影...
Redis(十):主从模式 前言 上一篇介绍了 Redis 应对并发问题的方案。这节开始介绍 Redis 的主从模式。 由于 R...
C指针:程序员的望远镜 C指针:程序员的望远镜一、什么是指针1.1 指针的定义1.2 指针和普通变量的区别1....
牛客网Java面试题及答案整理... 学习如逆水行舟,尤其是 IT 行业有着日新月异的节奏,我们更要抓紧每一次...
江西宜春智慧停车欠费清缴享7折... 极目新闻记者 杜光然 近日,江西网友发视频称,宜春智慧停车公司开启了端午缴费特惠活动,车主享停车费7...
律数科技申请基于区块链的小额金... 金融界2025年5月31日消息,国家知识产权局信息显示,北京律数科技有限公司申请一项名为“一种基于区...
好用的5款国产低代码平台介绍 一、云程低代码平台 云程低代码平台是一款基于springboot、vue.js技术的企业级低代码...
【数据结构第三章】- 队列 目录 一、队列的定义和特点 二、循环队列 2.1 - CircularQueue.h 2.2 - C...
如何将pdf文件压缩?pdf压... PDF是一种常见的文档格式,因为包括文本格式和图像,我们往往采用这种格式...
0X30数学知识 - 质数 定义: 若一个正整数无法被除了1和它自身之外的任何自然数整除,则称该数...