背景随着微服务流行,很多公司都把零碎依照业务边界拆成了很多微服务,在排错查日志的时候,因为业务链路贯通着很多微服务节点,导致定位某个申请的日志以及上下游业务的日志会变得有些艰难。这时候可能有的小伙伴就会想到应用SkyWalking,Pinpoint等分布式追踪零碎来解决,并且这些零碎通常都是无侵入性的,同时也会提供绝对敌对的治理界面来进行链路Span的查问,然而搭建分布式追踪零碎还是须要肯定的老本的,所以本文要说的并不是这些分布式追踪零碎,而是一款简略、易用、简直零侵入、适宜中小型公司应用的日志追踪框架TLog。TLog简介TLog提供了一种最简略的形式来解决日志追踪问题,TLog会主动的对你的日志进行打标签,帮你主动生成traceId贯通你微服务的一整条链路,在排查日志的时候,能够依据traceId来疾速定位申请解决的链路。TLog不收集日志,只在对你原来打印的日志上加强,将申请链路信息traceId绑定到你打印的日志上。当呈现微服务中那么多节点的状况,官网举荐应用TLog+日志收集计划来解决。当然分布式追踪零碎其实是链路追踪一个最终的解决方案,如果我的项目中曾经上了分布式追踪零碎,那TLog并不实用。如下图,是ELK配合TLog,疾速定位申请解决的链路的示例。

TLog接入1、接入步骤1.1、引入依赖<dependency>
    <groupId>com.yomahub</groupId>
    <artifactId>tlog-all-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>1.2、替换logback配置项

到这其实就曾经实现了配置。1.3、测试

这里是通过slf4j的LoggerFactory获取Logger对象,因为logback适配了slf4j,最终会通过logback来输入日志。

从这能够看出,11794076298070144 就是本次日志输入的时候生成的一个申请的traceId,在排查日志的时候就能够通过这个traceId去搜寻出整个申请的链路日志。2、TLog接入形式TLog总共提供了三种形式接入我的项目Javaagent接入形式字节码注入形式日志框架适配器形式下面案例的接入形式其实是属于日志框架适配器形式,并且是对于Logback框架的适配。TLog除了适配了Logback框架,还适配了Log4j框架和Log4j2框架,我的项目中可自行抉择。Javaagent接入形式和字节码注入形式相比与日志框架适配器形式对代码的入侵性更小,然而这两种形式仅仅只反对SpringBoot我的项目,并且相较于日志框架适配器的形式,MDC和异步日志性能并不反对,所以要想残缺体验TLog的性能,还是倡议抉择日志框架适配器形式,日志框架适配器形式其实接入也很快,其实也就是批改一下配置文件的事。

我的项目环境兼容比照

个性反对比照TLog的基本原理1、日志标签后面在介绍TLog的时候,提到TLog会主动的对你的日志进行打标签,这个标签就是日志标签,一个日志标签最多能够蕴含如下信息:preApp:接口调用方服务名preHost:接口调用方HostpreIp:接口调用方ipcurrIp:以后服务iptraceId:链路id,调用方如果传递就是传递的值,不传递就会从新生成spanId:链路spanId默认是依照如下labelPattern进行数据拼接生成日志标签,所以默认只打出spanId和traceId。

这也就是下面为什么示例中会输入 <0><11794076298070144> 这种格局的起因,后面的0其实就是spanId。如果你想扭转日志标签输入其它信息或者输入的程序,只须要在SpringBoot配置文件中配置日志标签的生成款式就行。tlog.pattern=$preApp][$preIp2、TLogContext

TLogContext是TLog是一个外围的组件,这个组件外部是应用了TransmittableThreadLocal来传递traceId、preApp等信息。当有一个申请过去的时候,会从解析出traceId、preApp等信息,而后设置到TransmittableThreadLocal中,之后就能够在整个调用链路中从TLogContext中获取到traceId等信息。3、TLogRPCHandler

这个组件是用来解决调用方传递的traceId、preApp等信息,设置到TLogContext和MDC中,同时依据日志标签的格局生成日志标签。第三方框架的适配在理论我的项目中,一个申请处理过程可能会呈现以下状况异步线程解决跨服务调用MQ调用那么对于这些状况来说,traceId应该须要在异步线程、跨服务、MQ等中传递,以便更好地排查一个申请的解决链路。而TLog对于以上可能呈现的状况都做了大量的适配,保障traceId可能在异步线程、微服务间、MQ等中可能正确传递。1、异步线程1.1 个别异步线程所谓的个别异步线程就是指间接通过new Thread的办法来创立异步线程,而后来执行,这种形式TLog是人造反对携带traceId的,如图。

执行后果

从这能够看出这种异步形式确实胜利传递了traceId。1.2 线程池对于线程池来说,其实默认也是反对传递traceId,然而因为线程池中的线程是能够复用了,为了保障线程间的数据互不烦扰,须要应用TLogInheritableTask将提交的工作进行包装。ThreadPoolExecutor pool =
        new ThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
pool.execute(new TLogInheritableTask() {
    @Override
    public void runTask() {
      logger.info("异步执行");
    }
});上述代码的写法会有点耦合,每次提交工作都须要创立一个TLogInheritableTask,比拟麻烦,能够按如下写法进行简化。

TLogThreadPoolExecutor本人写个TLogThreadPoolExecutor继承ThreadPoolExecutor,重写execute办法(submit最终也会调用execute办法执行),而后将提交的工作对立包装成TLogInheritableTask,这样须要应用线程池的中央间接创立TLogThreadPoolExecutor就能够了,就不须要在提交工作的时候创立TLogInheritableTask了。ThreadPoolExecutor pool =
        new TLogThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
pool.execute(() -> logger.info("异步执行"));2、对RPC框架的反对除了对异步线程的反对,TLog也反对常见的Dubbo,Dubbox,OpenFeign三大RPC框架,在SpringBoot我的项目中不须要任何配置,只须要引入依赖就能够实现traceId在服务之间的传递2.1 对Dubbo和Dubbox的反对对于Dubbo和Dubbox的反对是基于Dubbo的Filter扩大点来的

TLog通过SPI机制扩大Filter,在消费者发送申请前从TLogContext获取到traceId,而后将traceId和其它调用者数据设置申请数据中,服务提供者在解决申请的时候,也会通过Filter,从申请中获取到traceId等信息,而后设置到TLogContext中,从而实现了traceId在dubbo的消费者和提供者之间的传递。2.2 对OpenFeign的反对对于OpenFeign的反对其实也是通过Feign提供的扩大点RequestInterceptor来实现的

发送申请之前,从TLogContext获取到traceId,将traceId等信息增加到申请头中,而后就能够通过Http申请将traceId等信息传递。当被调用方接管到申请之后,会通过TLogWebInterceptor这个拦截器进行拦挡,从申请头中获取到这些参数,设置到TLogContext中。

3、对罕用Http框架的反对除了一些RPC框架,TLog也对一些Http框架进行了适配,比方HttpClientOkhttphutool-httpRestTemplateforest应用这些Http框架也能够实现traceId的传递其实这些框架的适配跟Feign的适配都是大同小异,都是基于这些Http框架各自提供的扩大点进行适配的,将traceId等信息放到申请头中,这里都不举例了,具体的应用办法能够在官网查看。4、对SpringCloud Gateway的反对同样的,TLog也适配了SpringCloud Gateway

原理也是一样的,就是适配了Gateway的GlobalFilter,从申请头中获取traceId等信息。除了适配了Gateway网关,TLog也适配了Soul网关。5、对MQ的反对对于MQ的反对跟异步线程差不多,须要将你发送的音讯包装成TLogMqWrapBean对象

TLogMqWrapBean发送的时候间接发送TLogMqWrapBean对象过来TLogMqWrapBean<BizBean> tLogMqWrap = new TLogMqWrapBean(bizBean);
mqClient.send(tLogMqWrap);TLogMqWrapBean会将traceId等信息携带,消费者承受到TLogMqWrapBean,而后通过TLogMqConsumerProcessor解决业务音讯。TLogMqConsumerProcessor.process(tLogMqWrapBean, new TLogMqRunner<BizBean>() {
    @Override
    public void mqConsume(BizBean o) {
     //业务操作
    }
});如此就实现了traceId通过MQ传递。在理论应用中,依据不同的MQ的类型,能够将音讯包装成TLogMqWrapBean对象的过程和解决音讯的过程做对立的封装解决,以缩小发送音讯和解决音讯对于TLog的耦合。6、对工作框架的反对TLog次要是反对一下四种工作框架JDK TimerQuartz框架spring-scheduledXXL-JOB框架其中,spring-scheduled和XXL-JOB在SpringBoot环境底下是无需工作配置的,只须要引入依赖即可。Timer在应用的时候须要将工作包装成TLogTimerTask,Quartz须要把QuartzJobBean替换成TLogQuartzJobBean就能够了。小总结其实从下面的各种适配能够看出,其实实质都是一样的,就是依据具体框架的扩大点,在发送申请之前从TLogContext获取到traceId,将traceId等调用者的信息在申请中携带,而后被调用方解析申请,取出traceId和调用者信息,设置到被调用方服务中的TLogContext中。所以,如果一旦须要遇到官网还未适配的框架或者组件,能够参照上述适配过程进行适配即可。最初总的来说,TLog是一款十分优良的日志追踪的框架,很适宜中小公司应用。这里来总结一下TLog的个性通过对日志打标签实现轻量级微服务日志追踪提供三种接入形式:javaagent齐全无侵入接入,字节码一行代码接入,基于配置文件的接入对业务代码无侵入式设计,应用简略,10分钟即可接入反对常见的log4j,log4j2,logback三大日志框架,并提供自动检测,实现适配反对dubbo,dubbox,feign三大RPC框架反对Spring Cloud Gateway和Soul网关反对HttpClient和Okhttp等http调用框架标签传递反对多种工作框架,JDK的TimerTask,Quartz,XXL-JOB,spring-scheduled反对日志标签的自定义模板的配置,提供多个零碎级埋点标签的抉择反对异步线程的追踪,包含线程池,多级异步线程等场景简直无性能损耗,疾速稳固,通过压测,损耗在0.01%因为本文篇幅无限,无奈全面对TLog进行解说,如果想深刻理解该框架,可自行浏览官网或者源码。官网:tlog.yomahub.comgithub地址:github.com/dromara/TLo…