【第34章】Spring Cloud之SkyWalking分布式日志
文章目录
- 前言
- 一、准备
- 1. 引入依赖
- 二、日志配置
- 1. 打印追踪ID
- 2. gRPC 导出
- 三、完整日志配置
- 四、日志展示
- 1. 前端
- 2. 后端
- 总结
前言
前面已经完成了请求的链路追踪,这里我们通过SkyWalking来处理分布式日志;
场景描述:我们有三个服务消费者,提供者和用户服务,三个服务都有自己的日志文件,但是我一个请求会贯穿三个服务,不能说我一个服务的日志文件挨个去找,这太麻烦了,如果有更多的服务呢,这时候代价会更大;
SkyWalking为我们解决了这个问题,每当请求进来的时候会生成一个追踪ID(TID)
一、准备
1. 引入依赖
我们首先引入skywalking整合logback的工具包
<!-- 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
<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 导出
<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 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. 后端
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记。
相关文章:
【第34章】Spring Cloud之SkyWalking分布式日志
文章目录 前言一、准备1. 引入依赖 二、日志配置1. 打印追踪ID2. gRPC 导出 三、完整日志配置四、日志展示1. 前端2. 后端 总结 前言 前面已经完成了请求的链路追踪,这里我们通过SkyWalking来处理分布式日志; 场景描述:我们有三个服务消费者…...
easy-es动态索引支持
背景 很多项目目前都引入了es,由于es弥补了mysql存储及搜索查询的局限性,随着技术的不断迭代,原生的es客户端使用比较繁琐不直观,上手代价有点大,所以easy-es框架就面世了,学习成本很低,有空大…...
SWC(Speedy Web Compiler)
概述 SWC 由 Rust 编写, 既可用于编译,也可用于打包。 对于编译,它使用现代 JavaScript 功能获取 JavaScript / TypeScript 文件并输出所有主流浏览器支持的有效代码。 SWC在单线程上比 Babel 快 20 倍,在四核上快 70 倍。 简…...
【计算机网络】传输层协议UDP
目录 一、端口号1.1 端口号范围划分1.2 认识知名端口号 二、UDP协议2.1 UDP协议端格式2.2 UDP的特点2.3 UDP的缓冲区2.4 UDP使用注意事项2.5 基于UDP的应用层协议 一、端口号 传输层协议负责数据的传输,从发送端到接收端。端口号标识一个主机上进行通信的不同的应用…...
Docker+PyCharm远程调试环境隔离解决方案
DockerPyCharmMiniconda实现深度学习代码远程调试和环境隔离 本文详细介绍了如何在局域网环境下,利用Docker、PyCharm和Miniconda构建一个高效的深度学习远程调试平台。首先在服务器(server)上,通过Docker构建包含不同CUDA环境的镜…...
数字化转型的理论框架对比:从多维视角指导企业成功变革对比DPBOKIT4ITCOBITTOGAF
数字化转型的多维框架解析 在数字化时代,企业如何有效实现数字化转型已成为其生存和发展的关键问题。然而,市场上关于数字化管理的各种框架和理论并存,企业需要根据自身的需求选择最适合的指导路径。本文将通过对几个核心理论框架的对比&…...
【C++掌中宝】深入解析C++命名空间:有效管理代码的利器
文章目录 前言1. namespace 的价值2. namespace 的定义3. 命名空间的本质4. 嵌套的命名空间5. 命名空间的使用6. using 指令7. 补充结语 前言 假设这样一种情况,当一个班上有两个名叫 Zara 的学生时,为了明确区分它们,我们在使用名字之外&am…...
2024/9/21 leetcode 21.合并两个有序链表 2.两数相加
目录 21.合并两个有序链表 题目描述 题目链接 解题思路与代码 2.两数相加 题目描述 题目链接 解题思路与代码 --------------------------------------------------------------------------- 21.合并两个有序链表 题目描述 将两个升序链表合并为一个新的 升序 链表并返…...
Python学习的主要知识框架
Python的主要学习知识点非常广泛且深入,但我可以为您概括一些核心的学习领域,帮助您系统地掌握Python编程。以下是Python学习的主要知识框架: 1. Python基础语法 数据类型:整数、浮点数、字符串、布尔值、列表、元组、字典、集合…...
LLaMA-Factory 使用 alpaca 格式的数据集
LLaMA-Factory 使用 alpaca 格式的数据集 flyfish alpaca 格式最初与Stanford大学的一个研究项目相关联,该项目旨在通过少量高质量的数据来微调大型语言模型。它受到了Alpaca模型(一种基于LLaMA的指令跟随模型)的影响,该模型是在…...
【Mysql】Mysql数据库基础
1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…...
一文彻底让你搞懂轨迹规划(总结)
机器人在运行中不可避免的会进行运动,那么就会产生出轨迹规划的概念。 轨迹规划的特点:用一定的函数形式表示控制量(位置,速度,加速度)的控制律,根据约束或最优目标,求取控制控制参…...
windows C++ 并行编程-异步消息块(二)
overwrite_buffer 类 concurrency::overwrite_buffer 类与 unbounded_buffer 类类似,只不过 overwrite_buffer 对象仅存储一条消息。 此外,当目标接收来自 overwrite_buffer 对象的消息时,不会从缓冲区中删除该消息。 因此,多个目…...
【软件基础知识】什么是 API,详细解读
想象一下,你正在使用智能手机上的天气应用。你打开应用,瞬间就能看到实时天气、未来预报,甚至是空气质量指数。但你有没有想过,这些数据是如何神奇地出现在你的屏幕上的?答案就在三个字母中:API。 API,全称Application Programming Interface(应用程序编程接口),是现代软件世…...
计算机四级-计算机网络
一、基础知识 1.对计算机网络发展具有重要影响的广域网是:ARPANET 随机争用型的介质访问控制方法起源于:ALOHANET 2.计算机网络发展阶段: A)第一阶段的主要成果是计算机技术与通信技术的结合 B)第二阶段的主要成果…...
【linux 获取时间】
linux 获取时间接口 我们在开发调试过程中,可能遇到一些和调用时序相关的问题,为了查看哪个步骤先调用,哪个步骤后调用,我们可以使用函数打印或者主动trace堆栈…但是有的时候我们需要排查2个接口调用的时间间隔,我们可…...
Dockerfile部署xxljob
使用Dockerfile部署xxljob 1. 背景 我们在使用定时任务调度时,通常会使用xxljob容器化部署xxljob,通常使用 docker pull xuxueli/xxl-job-admin:2.4.0 拉取镜像并启动容器。这种方式对于x86架构服务器来说,没有任何问题。但是在arm架构的服…...
Conda新建python虚拟环境问题
Conda新建python虚拟环境问题: 【问题1】 conda create --name yolov8 python3.10 -y Retrieving notices: …working… done Channels: defaults Platform: win-64 Collecting package metadata (repodata.json): failed UnavailableInvalidChannel: HTTP 404 NO…...
这几个优秀的工具网站真心值得推荐——搜嗖工具箱
即时工具 https://www.67tool.com/ 这是一个专注提升效率的办公工具网站;这也是一个拥有260多款自研在线工具和200多个客户端离线工具的服务网站;这还是一个可以满足包括视频处理、音频处理、图片处理、文档处理、文档转换、办公辅助、图表生成、文本工…...
ESP32开发 -- VSCODE+PlatformIO环境安装
参看官网安装:PlatformIO IDE for VSCode 一、安装PlatformIO IDE 参看:日常生活小技巧 – Visual Studio Code 简单使用 扩展中搜索platformIO IDE 当安装完提示重启之后。 打开一个要创建新工程的文件夹: 点击 Create New Project&…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
