• SpringBoot 2.5.5整合轻量级的分布式日志标记追踪神器TLog


    TLog能解决什么痛点#

      随着微服务盛行,很多公司都把系统按照业务边界拆成了很多微服务,在排错查日志的时候。因为业务链路贯穿着很多微服务节点,导致定位某个请求的日志以及上下游业务的日志会变得有些困难。

      这时候很多童鞋会开始考虑上SkyWalking,Pinpoint等分布式追踪系统来解决,基于OpenTracing规范,而且通常都是无侵入性的,并且有相对友好的管理界面来进行链路Span的查询。

    但是搭建分布式追踪系统,熟悉以及推广到全公司的系统需要一定的时间周期,而且当中涉及到链路span节点的存储成本问题,全量采集还是部分采集?如果全量采集,就以SkyWalking的存储来举例,ES集群搭建至少需要5个节点。这就需要增加服务器成本。况且如果微服务节点多的话,一天下来产生几十G上百G的数据其实非常正常。如果想保存时间长点的话,也需要增加服务器磁盘的成本。

    当然分布式追踪系统是一个最终的解决方案,如果您的公司已经上了分布式追踪系统,那TLog并不适用。

    项目整合#

    项目结构#

    添加依赖#

    复制代码
            
            <dependency>
                <groupId>com.yomahubgroupId>
                <artifactId>tlog-all-spring-boot-starterartifactId>
                <version>1.5.0version>
            dependency>
    复制代码

    logback-spring.xml#

    复制代码
    xml version="1.0" encoding="UTF-8"?>
    
    
    
    
    <configuration  scan="true" scanPeriod="10 seconds">
    
        <contextName>logbackcontextName>
        
        <property name="log.path" value="applog/" />
        <property name="log.name" value="springboot-tlog"/>
        <property name="CONSOLE_LOG_PATTERN_FILE" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %C:%M:%L [%thread] %-5level %msg%n"/>
    
        
        
        <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
        <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
        <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
        
        <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    
        
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            
    
    
    
            <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
                <Pattern>${CONSOLE_LOG_PATTERN}Pattern>
                
                <charset>UTF-8charset>
            encoder>
        appender>
    
    
        
        
        <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            
            <file>${log.path}/${log.name}/${log.name}_info.logfile>
            
            <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
                <pattern>${CONSOLE_LOG_PATTERN_FILE}pattern>
                <charset>UTF-8charset>
            encoder>
            
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                
                <fileNamePattern>${log.path}/${log.name}/info/${log.name}-info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
                
                <maxHistory>180maxHistory>
            rollingPolicy>
            
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>infolevel>
                <onMatch>ACCEPTonMatch>
                <onMismatch>DENYonMismatch>
            filter>
        appender>
    
        
        <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            
            <file>${log.path}/${log.name}/${log.name}_error.logfile>
            
            <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
                <pattern>${CONSOLE_LOG_PATTERN_FILE}pattern>
                <charset>UTF-8charset> 
            encoder>
            
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log.path}/${log.name}/error/${log.name}-error-%d{yyyy-MM-dd}.%i.logfileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
                
                <maxHistory>180maxHistory>
            rollingPolicy>
            
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERRORlevel>
                <onMatch>ACCEPTonMatch>
                <onMismatch>DENYonMismatch>
            filter>
        appender>
    
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="ERROR_FILE" />
        root>
    
        
    
    configuration>
    复制代码

    请求类#

    复制代码
    package com.ybchen.request;
    
    import lombok.Data;
    
    /**
     * @author: chenyanbin 2022-10-18 23:03
     */
    @Data
    public class PersonRequest {
        private Long id;
        private Long age;
        private String name;
    }
    复制代码

    Controller#

    复制代码
    package com.ybchen.controller;
    
    import com.ybchen.request.PersonRequest;
    import com.yomahub.tlog.core.annotation.TLogAspect;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author: chenyanbin 2022-10-18 22:56
     */
    @RestController
    @Slf4j
    public class DemoController {
        @TLogAspect({"id"})
        @GetMapping("demo1")
        public void demo1(String id, String name) {
            log.info("这是第一条日志---->简单例子");
            log.info("这是第二条日志---->简单例子");
            log.info("这是第三条日志---->简单例子");
            new Thread(() -> log.info("这是异步日志---->简单例子")).start();
        }
    
        @TLogAspect({"id", "name"})
        @GetMapping("demo2")
        public void demo2(String id, String name) {
            log.info("这是第一条日志----->多个数值");
            log.info("这是第二条日志----->多个数值");
            log.info("这是第三条日志----->多个数值");
            new Thread(() -> log.info("这是异步日志----->多个数值")).start();
        }
    
        @TLogAspect(value = {"id", "name"}, pattern = "<-{}->", joint = "_")
        @GetMapping("demo3")
        public void demo3(String id, String name) {
            log.info("多个数值-------->加了patter和joint的示例");
        }
    
        @TLogAspect(str = "陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/")
        @GetMapping("demo4")
        public void demo4(String name){
            log.info("这是第一条日志----->常量字符串标签");
            log.info("这是第二条日志----->常量字符串标签");
            log.info("这是第三条日志----->常量字符串标签");
            new Thread(() -> log.info("这是异步日志----->常量字符串标签")).start();
        }
    
        @TLogAspect({"request.id","request.age"})
        @GetMapping("demo5")
        public void demo4(PersonRequest request){
            log.info("多参数加多层级示例");
        }
    }
    复制代码

    SpanId的生成规则#

     

     TLog业务标签#

      很多公司的系统在打日志的时候,每打一个日志里都会带入一些业务信息,比如记录ID,会员CODE,方便业务日志的定位。现在有了TLog,不仅能做分布式链路标签追加,还能自动帮你做业务标签的添加。这样在定位日志的时候可以更加方便的搜索。

      Tlog支持方法级别的自定义业务标签。你可以在方法上定义简单的标注,来实现在某一个方法的日志里,统一加入业务的指标标签,用于更加细致的定位。

    演示#

    示例1#

    复制代码
        @TLogAspect({"id"})
        @GetMapping("demo1")
        public void demo1(String id, String name) {
            log.info("这是第一条日志---->简单例子");
            log.info("这是第二条日志---->简单例子");
            log.info("这是第三条日志---->简单例子");
            new Thread(() -> log.info("这是异步日志---->简单例子")).start();
        }
    复制代码

     

    复制代码
    2022-10-18 23:14:37.450  INFO 88321 --- [nio-8080-exec-4] com.ybchen.controller.DemoController     : <0><11477324755760832> [id:"10086"] 这是第一条日志---->简单例子
    2022-10-18 23:14:37.451  INFO 88321 --- [nio-8080-exec-4] com.ybchen.controller.DemoController     : <0><11477324755760832> [id:"10086"] 这是第二条日志---->简单例子
    2022-10-18 23:14:37.451  INFO 88321 --- [nio-8080-exec-4] com.ybchen.controller.DemoController     : <0><11477324755760832> [id:"10086"] 这是第三条日志---->简单例子
    2022-10-18 23:14:37.452  INFO 88321 --- [      Thread-12] com.ybchen.controller.DemoController     : <0><11477324755760832> [id:"10086"] 这是异步日志---->简单例子
    2022-10-18 23:14:41.160  INFO 88321 --- [nio-8080-exec-5] com.ybchen.controller.DemoController     : <0><11477324998899392> [id:"10087"] 这是第一条日志---->简单例子
    2022-10-18 23:14:41.160  INFO 88321 --- [nio-8080-exec-5] com.ybchen.controller.DemoController     : <0><11477324998899392> [id:"10087"] 这是第二条日志---->简单例子
    2022-10-18 23:14:41.160  INFO 88321 --- [nio-8080-exec-5] com.ybchen.controller.DemoController     : <0><11477324998899392> [id:"10087"] 这是第三条日志---->简单例子
    2022-10-18 23:14:41.161  INFO 88321 --- [      Thread-13] com.ybchen.controller.DemoController     : <0><11477324998899392> [id:"10087"] 这是异步日志---->简单例子
    2022-10-18 23:14:43.938  INFO 88321 --- [nio-8080-exec-6] com.ybchen.controller.DemoController     : <0><11477325181023936> [id:"10085"] 这是第一条日志---->简单例子
    2022-10-18 23:14:43.939  INFO 88321 --- [nio-8080-exec-6] com.ybchen.controller.DemoController     : <0><11477325181023936> [id:"10085"] 这是第二条日志---->简单例子
    2022-10-18 23:14:43.939  INFO 88321 --- [nio-8080-exec-6] com.ybchen.controller.DemoController     : <0><11477325181023936> [id:"10085"] 这是第三条日志---->简单例子
    2022-10-18 23:14:43.940  INFO 88321 --- [      Thread-14] com.ybchen.controller.DemoController     : <0><11477325181023936> [id:"10085"] 这是异步日志---->简单例子
    复制代码

    示例二#

    复制代码
        @TLogAspect({"id", "name"})
        @GetMapping("demo2")
        public void demo2(String id, String name) {
            log.info("这是第一条日志----->多个数值");
            log.info("这是第二条日志----->多个数值");
            log.info("这是第三条日志----->多个数值");
            new Thread(() -> log.info("这是异步日志----->多个数值")).start();
        }
    复制代码
    复制代码
    2022-10-18 23:22:33.941  INFO 88321 --- [nio-8080-exec-8] com.ybchen.controller.DemoController     : <0><11477355982223040> [id:"10085",name:"alex"] 这是第一条日志----->多个数值
    2022-10-18 23:22:33.946  INFO 88321 --- [nio-8080-exec-8] com.ybchen.controller.DemoController     : <0><11477355982223040> [id:"10085",name:"alex"] 这是第二条日志----->多个数值
    2022-10-18 23:22:33.947  INFO 88321 --- [nio-8080-exec-8] com.ybchen.controller.DemoController     : <0><11477355982223040> [id:"10085",name:"alex"] 这是第三条日志----->多个数值
    2022-10-18 23:22:33.950  INFO 88321 --- [      Thread-15] com.ybchen.controller.DemoController     : <0><11477355982223040> [id:"10085",name:"alex"] 这是异步日志----->多个数值
    2022-10-18 23:22:37.744  INFO 88321 --- [nio-8080-exec-9] com.ybchen.controller.DemoController     : <0><11477356232308416> [id:"10086",name:"alex"] 这是第一条日志----->多个数值
    2022-10-18 23:22:37.744  INFO 88321 --- [nio-8080-exec-9] com.ybchen.controller.DemoController     : <0><11477356232308416> [id:"10086",name:"alex"] 这是第二条日志----->多个数值
    2022-10-18 23:22:37.744  INFO 88321 --- [nio-8080-exec-9] com.ybchen.controller.DemoController     : <0><11477356232308416> [id:"10086",name:"alex"] 这是第三条日志----->多个数值
    2022-10-18 23:22:37.745  INFO 88321 --- [      Thread-16] com.ybchen.controller.DemoController     : <0><11477356232308416> [id:"10086",name:"alex"] 这是异步日志----->多个数值
    复制代码

    示例三#

    复制代码
        @TLogAspect(value = {"id", "name"}, pattern = "<-{}->", joint = "_")
        @GetMapping("demo3")
        public void demo3(String id, String name) {
            log.info("多个数值-------->加了patter和joint的示例");
        }
    复制代码
    2022-10-18 23:24:52.137  INFO 88321 --- [nio-8080-exec-1] com.ybchen.controller.DemoController     : <0><11477365039888064> <-id:"10086"_name:"alex"-> 多个数值-------->加了patter和joint的示例
    2022-10-18 23:24:56.329  INFO 88321 --- [nio-8080-exec-2] com.ybchen.controller.DemoController     : <0><11477365314614976> <-id:"10089"_name:"alex"-> 多个数值-------->加了patter和joint的示例

    示例四#

    复制代码
        @TLogAspect(str = "陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/")
        @GetMapping("demo4")
        public void demo4(String name){
            log.info("这是第一条日志----->常量字符串标签");
            log.info("这是第二条日志----->常量字符串标签");
            log.info("这是第三条日志----->常量字符串标签");
            new Thread(() -> log.info("这是异步日志----->常量字符串标签")).start();
        }
    复制代码
    复制代码
    2022-10-18 23:29:25.801  INFO 10245 --- [nio-8080-exec-4] com.ybchen.controller.DemoController     : <0><11477382974797504> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是第一条日志----->常量字符串标签
    2022-10-18 23:29:25.802  INFO 10245 --- [nio-8080-exec-4] com.ybchen.controller.DemoController     : <0><11477382974797504> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是第二条日志----->常量字符串标签
    2022-10-18 23:29:25.802  INFO 10245 --- [nio-8080-exec-4] com.ybchen.controller.DemoController     : <0><11477382974797504> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是第三条日志----->常量字符串标签
    2022-10-18 23:29:25.803  INFO 10245 --- [       Thread-8] com.ybchen.controller.DemoController     : <0><11477382974797504> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是异步日志----->常量字符串标签
    2022-10-18 23:29:30.216  INFO 10245 --- [nio-8080-exec-5] com.ybchen.controller.DemoController     : <0><11477383264138944> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是第一条日志----->常量字符串标签
    2022-10-18 23:29:30.217  INFO 10245 --- [nio-8080-exec-5] com.ybchen.controller.DemoController     : <0><11477383264138944> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是第二条日志----->常量字符串标签
    2022-10-18 23:29:30.217  INFO 10245 --- [nio-8080-exec-5] com.ybchen.controller.DemoController     : <0><11477383264138944> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是第三条日志----->常量字符串标签
    2022-10-18 23:29:30.218  INFO 10245 --- [       Thread-9] com.ybchen.controller.DemoController     : <0><11477383264138944> [陈彦斌博客地址:https://www.cnblogs.com/chenyanbin/] 这是异步日志----->常量字符串标签
    复制代码

    示例五#

    @TLogAspect支持点操作符,适用于对象的取值,支持类型:

    • Bean对象
    • Map对象
    • Json格式的字符串
    • Fastjson的JSONObject对象

    复制代码
        @TLogAspect({"request.id","request.age"})
        @GetMapping("demo5")
        public void demo4(PersonRequest request){
    
            log.info("多参数加多层级示例");
        }
    
    
    
    ================
    
    
    
    @Data
    public class PersonRequest {
        private Long id;
        private Long age;
        private String name;
    }
    复制代码
    2022-10-18 23:32:58.761  INFO 14747 --- [nio-8080-exec-2] com.ybchen.controller.DemoController     : <0><11477396931212992> [request.id:10089,request.age:27] 多参数加多层级示例
    2022-10-18 23:33:03.289  INFO 14747 --- [nio-8080-exec-3] com.ybchen.controller.DemoController     : <0><11477397228025536> [request.id:10099,request.age:27] 多参数加多层级示例
  • 相关阅读:
    arm_按键中断控制LED、蜂鸣器、风扇
    【使用 Python 实现算法】02 原生类型与内置函数
    图像与点云三维重建算法
    055-第三代软件开发-控制台输出彩虹日志
    【数据结构】链表面试题总结(持续更新中...)
    mysql修改数据库名称
    Android sqlite 使用简介
    【无标题】
    Promise.all 使用方法
    html常用标签
  • 原文地址:https://www.cnblogs.com/chenyanbin/p/16804650.html