【第34章】Spring Cloud之SkyWalking分布式日志

文章目录


前言

前面已经完成了请求的链路追踪,这里我们通过SkyWalking来处理分布式日志;

场景描述:我们有三个服务消费者,提供者和用户服务,三个服务都有自己的日志文件,但是我一个请求会贯穿三个服务,不能说我一个服务的日志文件挨个去找,这太麻烦了,如果有更多的服务呢,这时候代价会更大;

SkyWalking为我们解决了这个问题,每当请求进来的时候会生成一个追踪ID(TID)


一、准备

1. 引入依赖

我们首先引入skywalking整合logback的工具包

XML 复制代码
<!-- https://mvnrepository.com/artifact/org.apache.skywalking/apm-toolkit-logback-1.x -->
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>9.3.0</version>
</dependency>    

二、日志配置

以下内容基于logback-spring.xml日志配置文件

1. 打印追踪ID

xml 复制代码
<property name="CONSOLE_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr([%tid]) %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(%applicationName[%15.15t]){faint} %clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}:%L) %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>${CONSOLE_LOG_THRESHOLD}</level>
    </filter>
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
            <Pattern>${CONSOLE_PATTERN}</Pattern>
            <charset>${CONSOLE_LOG_CHARSET}</charset>
        </layout>
    </encoder>
</appender>

<root level="DEBUG">
    <appender-ref ref="CONSOLE"/>
</root>

主要是%tid

2. gRPC 导出

java 复制代码
<appender name="GRPC-LOG" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%applicationName[%15.15t]] [%thread] %-5level %logger{36} -%msg%n</Pattern>
        </layout>
    </encoder>
</appender>

<root level="DEBUG">
    <appender-ref ref="GRPC-LOG"/>
</root>

三、完整日志配置

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 引入Spring Boot的默认logback配置 -->
    <property name="CONSOLE_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr([%tid]) %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(%applicationName[%15.15t]){faint} %clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}:%L) %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <property name="FILE_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } %applicationName[%t] ${LOG_CORRELATION_PATTERN:-}%-40.40logger{39}:%L : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <!-- 自定义控制台输出模板 -->
    <property name="LOG_HOME" value="../logs/consumer/"/>
    <property name="LOG_FILE" value="consumer"/>
    <property name="LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START" value="false"/>
    <property name="LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE" value="10MB"/>
    <property name="LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP" value="0"/>
    <property name="LOGBACK_ROLLINGPOLICY_MAX_HISTORY" value="7"/>

    <appender name="GRPC-LOG" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%applicationName[%15.15t]] [%thread] %-5level %logger{36} -%msg%n</Pattern>
            </layout>
        </encoder>
    </appender>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>${CONSOLE_LOG_THRESHOLD}</level>
        </filter>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>${CONSOLE_PATTERN}</Pattern>
                <charset>${CONSOLE_LOG_CHARSET}</charset>
            </layout>
        </encoder>
    </appender>
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${FILE_PATTERN}</pattern>
            <charset>${FILE_LOG_CHARSET}</charset>
        </encoder>
        <file>${LOG_HOME}${LOG_FILE}_debug.log</file>
        <!--大小和时间基于滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}${LOG_FILE}_debug.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            <cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
            <maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
            <totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
            <maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7}</maxHistory>
        </rollingPolicy>
    </appender>
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <pattern>${FILE_PATTERN}</pattern>
            <charset>${FILE_LOG_CHARSET}</charset>
        </encoder>
        <file>${LOG_HOME}${LOG_FILE}_info.log</file>
        <!--大小和时间基于滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}${LOG_FILE}_info.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            <cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
            <maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
            <totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
            <maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7}</maxHistory>
        </rollingPolicy>
    </appender>
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>${FILE_PATTERN}</pattern>
            <charset>${FILE_LOG_CHARSET}</charset>
        </encoder>
        <file>${LOG_HOME}${LOG_FILE}_error.log</file>
        <!--大小和时间基于滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}${LOG_FILE}_error.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            <cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
            <maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
            <totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
            <maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7}</maxHistory>
        </rollingPolicy>
    </appender>
    <!-- 设置特定包的日志级别 -->
    <logger name="org.springframework" level="INFO"/>
    <logger name="org.hibernate" level="INFO"/>
    <logger name="com.alibaba" level="INFO"/>
    <logger name="io.netty" level="INFO"/>
    <logger name="reactor.netty" level="INFO"/>
    <logger name="com.github.xiaoymin.knife4j.spring.gateway.discover" level="INFO"/>
    <logger name="de.codecentric.boot.admin" level="INFO"/>
    <!-- Root Logger -->
    <root level="DEBUG">
        <appender-ref ref="GRPC-LOG"/>
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="DEBUG_FILE"/>
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>
</configuration>

四、日志展示

1. 前端




其他地方都有ALL,唯独服务这里是个单选,我们需要根据追踪ID一个服务一个服务的找,如果能直接根据这个追踪ID去找就好了,不过这样也够用了,就是没那么直观。

2. 后端

bash 复制代码
2024-09-08 20:50:31.453 [TID:a7f970f0b12c411aa2b064304a353602.90.17257998314490001] DEBUG 9752 [consumer-service] [nio-9003-exec-3] o.e.n.c.controller.TestController       :38 : 消费者服务 RestTemplate
2024-09-08 20:50:31.458 [TID:a7f970f0b12c411aa2b064304a353602.90.17257998314490001] DEBUG 3348 [provider-service] [nio-9000-exec-8] o.e.n.p.controller.TestController       :26 : 提供者服务 RestTemplate
2024-09-08 20:50:31.463 [TID:a7f970f0b12c411aa2b064304a353602.90.17257998314490001] DEBUG 2888 [user-service] [nio-9007-exec-1] o.e.user.controller.UserController      :31 : 用户服务 admin

总结

回到顶部

2024已过了大半,回望今年博客数量和质量突飞猛进,感觉学到了很多,也不算虚度吧。

2024-09-08记。

相关推荐
蓝斯4976 小时前
[原创]《C#高级GDI+实战:从零开发一个流程图》第章:增加贝塞尔曲线,上、下、左、右连接点
java·c#·流程图
前端工作日常6 小时前
我学习到的Java 的 Service 分层:itf 和 impl 到底是什么?
java·后端
都叫我大帅哥7 小时前
Spring @Transactional 注解完全指南
java·spring
Java成神之路-7 小时前
G1 垃圾回收器 :SATB + TAMS核心机制深度解析
java·jvm
前端工作日常7 小时前
我学习到的JIT即时编译与机器码缓存失效
java·后端
带刺的坐椅7 小时前
Solon 的 10 种 HTTP 服务器:改一行依赖,换一个引擎
java·solon·jetty·undertow·mcp-server·htttp
xcLeigh8 小时前
Go入门:变量声明的五种方式详解
java·开发语言·golang
AI大模型-小华8 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
Mark_ZP9 小时前
【锁1】Synchronized vs ReentrantLock区别
java
立心者09 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端