百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

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

myzbx 2024-12-14 13:51 21 浏览

TLog能解决什么痛点

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

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

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

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

项目整合

项目结构

添加依赖

        <!-- 引入全量tlog依赖 -->
        <dependency>
            <groupId>com.yomahub</groupId>
            <artifactId>tlog-all-spring-boot-starter</artifactId>
            <version>1.5.0</version>
        </dependency>

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="10 seconds">

    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <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">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<!--        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
<!--            <level>info</level>-->
<!--        </filter>-->
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!--输出到文件-->
    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/${log.name}/${log.name}_info.log</file>
        <!--日志文件输出格式-->
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
            <pattern>${CONSOLE_LOG_PATTERN_FILE}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/${log.name}/info/${log.name}-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/${log.name}/${log.name}_error.log</file>
        <!--日志文件输出格式-->
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
            <pattern>${CONSOLE_LOG_PATTERN_FILE}</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/${log.name}/error/${log.name}-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <root level="info">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>

    <!-- sql打印 -->
<!--    <logger name="com.ybchen.mapper" level="DEBUG"/>-->
</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-8

来源:https://www.cnblogs.com/chenyanbin/p/16804650.html

相关推荐

一键生成高颜值图表!让你的文字瞬间有画面感,职场人必备!

哈喽,打工人们!忙碌的周中,大熊又来给你们带来一个超实用的效率神器啦!这次的宝藏网站绝对是那种用过就离不开的"真香"型产品!假设你明天就要做重要汇报,可面对一大堆密密麻麻的文字材料,你...

批量将 Word 转换为 PDF/Excel/Txt/图片等多种格式

Word文档是我们工作中经常会打交道的一种文档格式,我们也经常会有需要对Word文档进行格式转换的需求,比如将Word格式转换为PDF、将Word文档转换为Excel、将Word...

绝了!一键用AI生成高颜值动态PPT(附详细步骤+Prompt)

大家好,我是一名酷爱研究AI的产品经理,最近我有个新发现:那些花了你3天做出来的PPT,现在用AI可以1小时搞定!而且颜值还高!为什么AI做PPT比传统方式效率高10倍?我用一张图就能告诉你:AI生成...

ztext - 简单几行代码创建酷炫3D特效文字的开源JS库

把网页上的文字变成酷炫的3D风格,还能制作旋转动效,有了ztext.js,只需要几行代码。ztext能做什么ztext.js是一个能把常规的平面文字变成3D样式的前端开源代码库,让开发者...

文字内插入小图片,也太可爱了吧(文字中怎么插图片)

图文排版H5手机版秀米有小伙伴留言问添加图片的时候可不可以把图片添加到文字之间比如下面这句话中的小贴纸图片后面可以接着输入文字其实吧这就是咱们的『文字内插入小图片』功能嘛可以用来在文字内加个表情包又...

Linux环境下C++代码性能分析方法(linux怎么写c++代码)

技术背景在开发C++应用程序时,找出代码中运行缓慢的部分是进行性能优化的关键。在Linux系统上,有多种工具和方法可用于对C++代码进行性能分析,每种方法都有其特点和适用场景。实现步骤手动中断调试法在...

SVG互动图文,让你的文章更有趣!教你4种简单易学的黑科技玩法!

如果你是一个公众号创作者,那么你一定想知道如何让你的文章更加吸引人,更加有趣,更加有创意。你可能已经尝试过各种图文排版技巧,但是你是否知道,有一种黑科技可以让你的文章变得更加酷炫,更加互动,更加爆款?...

Videoscribe怎么实现实心中文汉字的手绘制作

很多朋友在制作手绘视频的时候,不知道怎么输入实心的中文汉字,之前我们已经给大家分享了怎么输入汉字的方法,但是有一点遗憾的是输出的汉字是空心的手绘展示,在视觉上并不是非常的美观。经过大家不断的探索,终于...

一款用于将文本转化成图表的现代化脚本语言

大家好,又见面了,我是GitHub精选君!今天要给大家推荐一个GitHub开源项目terrastruct/d2,该项目在GitHub有超过10.3kStar,用一句话介绍该项目就是:...

探秘 Web 水印技术(制作水印网站)

作者:fransli,腾讯PCG前端开发工程师Web水印技术在信息安全和版权保护等领域有着广泛的应用,对防止信息泄露或知识产品被侵犯有重要意义。水印根据可见性可分为可见水印和不可见水印(盲水印)...

不忍心卸载的五款神仙工具(不忍心卸载的五款神仙工具是什么)

001.效率工具uTools-装机必备的生产力工具集uTools是一款非常强大的可以装下几乎所有效率工具的电脑生产力工具集,目前拥有Windows、Mac和Linux三个版本。软件界面...

「SVG」飞花令!这份最高检工作报告“超有料”

原标题:【SVG】飞花令!这份最高检工作报告“超有料”栏目主编:秦红文字编辑:沈佳灵来源:作者:最高人民检察院...

svg|2025政府工作报告,有没有你关心的数据?

··<setattributeName="visibility"begin="click+0s"dur="1ms"fill="freeze"restart="never"to="hi...

videoscribe只能输入英文,如何输入中文文本?

videoscribe只能输入英文,如何输入中文文本?打开VideoScribe软件,打开要添加中文字体的位置。打开Photoshop并在文件中创建一个新的透明背景图层。注意:必须是透明背景层。...

五个流行的SVG在线编辑器(svg编辑工具)

随着响应网络的发展,越来越多的高质量的SVG在线编辑器被公众所熟知。SVG矢量图形也越来越受欢迎,以便在任何设备上呈现图像,甚至一些易于使用的SVG在线编辑器,可以替代PS,本文总结了五种流行的SVG...