网罗开发 (小红书、快手、视频号同名)
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验 。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索"展菲",即可纵览我在各大平台的知识足迹。
📣 公众号"Swift社区",每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友"fzhanfei",与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
-
- 摘要
- 引言
- 为什么仅靠日志是不够的?
- [让日志"有链路感":TraceId 串联服务](#让日志“有链路感”:TraceId 串联服务)
-
- [什么是 TraceId?](#什么是 TraceId?)
- [如何让 TraceId 进入日志?](#如何让 TraceId 进入日志?)
- [实战:Node.js 接入 OpenTelemetry + 日志 TraceId](#实战:Node.js 接入 OpenTelemetry + 日志 TraceId)
-
- 安装依赖
- [初始化 Trace 与日志绑定](#初始化 Trace 与日志绑定)
- [打印日志时自动带 TraceId](#打印日志时自动带 TraceId)
- 用户反馈"下单慢",但日志没报错
- 支付请求失败,找不到原因
- 异常没有被抛出,但用户操作失败
- [QA 环节](#QA 环节)
-
- [Q:日志增加 TraceId 会带来性能问题吗?](#Q:日志增加 TraceId 会带来性能问题吗?)
- [Q:是否所有服务都要接入 OpenTelemetry?](#Q:是否所有服务都要接入 OpenTelemetry?)
- [Q:如何传递 TraceId 给下游?](#Q:如何传递 TraceId 给下游?)
- 总结
摘要
在分布式系统中,仅靠报错日志往往无法快速定位问题。我们经常面对"系统没报错,但就是慢"或"偶发错误找不到原因"的情况。本文将介绍如何将日志与分布式追踪(如 Jaeger、OpenTelemetry)结合,基于 traceId
串联整个链路上下游,快速排查服务瓶颈与异常。文章附带可运行的示例代码,适用于 Node.js 与 Spring Boot 应用。
引言
现代系统越来越复杂,一个请求常常会穿越多个服务。传统的日志打印、error 记录虽然必要,但无法提供完整上下文信息。我们需要一种方法,把日志"串"起来,看清每一次调用背后的路径和耗时。
这就引出了两个关键词:日志增强 与 分布式追踪(Tracing)。我们要做的,是在已有日志体系中引入 traceId,打通链路,实现更强的可观测能力。
为什么仅靠日志是不够的?
无上下文信息
日志打印往往是局部信息,比如:
bash
[2024-06-01 12:00:01] OrderService: created order 1234
但这个订单是怎么来的?从哪个接口发起的?下游库存扣减成功了吗?日志无法回答。
无法定位慢调用和瓶颈
一个请求"变慢",日志可能没有错误,但我们也不知道哪一步耗时最多。链路追踪能帮我们抓出"慢点"。
让日志"有链路感":TraceId 串联服务
什么是 TraceId?
TraceId 是分布式追踪系统为一次请求分配的唯一标识。只要服务之间传递这个 ID,我们就可以在日志中追踪整个流程。
常用追踪组件:
- Jaeger:CNCF 项目,支持多语言
- OpenTelemetry:统一标准,支持日志、Trace、Metrics
如何让 TraceId 进入日志?
通过 TraceId,我们可以做到这样的日志输出:
bash
[traceId=abc123] UserService: received login request
[traceId=abc123] AuthService: token verified
[traceId=abc123] OrderService: created order
是不是清晰多了?
实战:Node.js 接入 OpenTelemetry + 日志 TraceId
安装依赖
bash
npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node winston
初始化 Trace 与日志绑定
js
// tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
instrumentations: [getNodeAutoInstrumentations()]
});
sdk.start();
js
// logger.js
const { context, trace } = require('@opentelemetry/api');
const winston = require('winston');
const logger = winston.createLogger({
format: winston.format.printf(({ level, message }) => {
const span = trace.getSpan(context.active());
const traceId = span ? span.spanContext().traceId : 'unknown';
return `[${level}] [traceId=${traceId}] ${message}`;
}),
transports: [new winston.transports.Console()]
});
module.exports = logger;
打印日志时自动带 TraceId
js
// index.js
require('./tracing');
const logger = require('./logger');
logger.info('User logged in');
用户反馈"下单慢",但日志没报错
做法:
- 通过
traceId
在 Jaeger 中查看链路 - 发现库存服务耗时 1.8s,是主要瓶颈
- 查看库存服务日志,锁等待严重
- 分析后优化锁粒度,减少并发冲突
支付请求失败,找不到原因
做法:
- 用户提供 TraceId
- 日志中按 TraceId 搜索整条链路
- 发现某一步 HTTP 401,Token 被刷掉
- 推测是 Token 过期提前引起的边界异常,补了自动续签逻辑
异常没有被抛出,但用户操作失败
做法:
- 用 TraceId 找到用户请求路径
- 发现调用链中有异常处理被
try...catch
吃掉 - 增加日志告警输出异常堆栈,问题快速解决
QA 环节
Q:日志增加 TraceId 会带来性能问题吗?
A:不会明显影响。TraceId 是字符串拼接,日志系统本身 IO 成本更高。
Q:是否所有服务都要接入 OpenTelemetry?
A:建议逐步接入。可先从用户入口服务开始,再串联关键业务服务。
Q:如何传递 TraceId 给下游?
A:大多数 HTTP client 支持自定义 Header,传递 traceparent
即可。
总结
日志只是"看见问题"的起点。只有把日志与链路追踪结合起来,我们才能真正做到**"看清问题"**。通过 TraceId 串联的链路日志,可以:
- 更快定位问题源头
- 更清楚知道瓶颈在哪
- 更系统地理解服务之间的调用关系