链路与日志关联分析

最近更新时间:2026-03-03 15:22:17

我的收藏
随着微服务架构的逐渐流行,在复杂且庞大的系统中准确地定位一个请求的完整生命周期,逐渐成为了研发人员面临的最大痛点之一。以研发自测过程为例,开发人员通常希望在发起 HTTP/RPC 测试请求后,能够以一个简单的方式获取整个测试请求的上下文信息。这其中通常包括相关的上下游链路、各个服务内部请求的方法堆栈,以及链路上打印的日志等数据,对于指标-链路-日志的一体化监控的需求已经迫在眉睫。
腾讯云应用性能监控(APM)作为本身包含指标-链路的全链路监控平台,已与 腾讯云日志服务(CLS) 联手打通,实现指标-链路-日志的一体化监控。在查看链路详情时,关联查看所对应的信息,完成从链路到日志的排查流程。

前提条件

请确保应用已经接入应用性能监控(APM),并参考日志服务(CLS)入门指南 将业务日志上报到腾讯云日志服务(CLS)。
说明:
为了保障您日志数据的可靠性以及更高效地使用日志服务,建议您使用 CLS 优化后的接口/Agent 上传结构化日志:
通过 API/SDK 上报,详情请参见 上传日志 中的 contents 部分。
通过 Agent 上报,详情请参见 使用 JSON 提取模式采集日志

操作步骤

步骤1:将 TraceID 和 SpanID 打印到日志中

为了实现链路和日志的关联查询,您需要将 TraceID 和 SpanID 输出到日志中。对于通过如下方案接入的应用,可以在不修改代码的情况下,将 TraceID 和 SpanID 自动注入到日志中:
对于通过其他方式接入的应用,请参考 其他方案,从链路上下文中获取 TraceID 和 SpanID,并附加到日志内容中。

步骤2:在系统配置页面关联日志

2. 在左侧菜单栏选择应用性能监控 > 系统配置,进入业务系统配置页面。
3. 选择对应的业务系统,在日志关联中单击编辑
4. 配置日志关联信息。
开启关联日志。
选择对应的日志地域、日志集、日志主题,并指定 TraceID 和 SpanID 所在的字段。
5. 配置完后单击确定即可。

除了可以在业务系统级别配置日志关联以外,也可以在应用级别配置日志关联,请到 应用性能监控 > 系统配置 > 应用配置 中进行操作,具体的配置方式与业务系统级别相同。

步骤3:在链路查询页面查看日志信息

2. 在左侧菜单栏选择应用性能监控 > 链路追踪,进入链路追踪页面。
3. 选择对应的业务系统,找到对应的 TraceID,单击 TraceID 进入链路详情。
4. Trace 日志Span 日志标签页中,可以查询该链路对应的日志信息。


将 TraceID 和 SpanID 打印到日志中

腾讯云增强版 OpenTelemetry Java 探针

对于满足要求的日志组件,通过修改日志配置文件中的 pattern,即可实现对 TraceID 和 SpanID 的注入。在日志配置文件中,TraceID 和 SpanID 分别使用 %X{trace_id}%X{span_id}字段注入。
日志框架
支持的版本范围
Log4j
1.2+
Log4j2
2.7+
Logback
1.0+

Log4j

log4j.properties 文件修改示例:
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=trace_id: %X{trace_id} span_id: %X{span_id} - %m%n

Log4j2

Log4j2支持多种格式的配置文件,包括 XML、JSON、YAML、Properties 等。以 XML 格式为例,Pattern 有多种写法,请根据已有的写法参考其中一种:
方式一
方式二
方式三
<PatternLayout pattern="trace_id: %X{trace_id} span_id: %X{span_id} - %m%n"/>
<PatternLayout>
<Pattern>trace_id: %X{trace_id} span_id: %X{span_id} - %m%n</Pattern>
</PatternLayout>
<Layout type="PatternLayout" pattern="trace_id: %X{trace_id} span_id: %X{span_id} - %m%n"/>

Logback

logback.xml 文件修改示例:
<encoder>
<pattern>trace_id: %X{trace_id} span_id: %X{span_id} %msg%n</pattern>
</encoder>

SkyWalking Java 探针

请根据日志组件的类型,从 SkyWalking 官网获取在日志中注入 TraceID 和 SpanID 的操作指引。
Log4j
Log4j2
Logback

腾讯云 OpenTelemetry-Go 探针

对于满足要求的日志组件,无需额外的任何操作,即可实现对 TraceID 和 SpanID 的注入。如果探针检测到活跃 Span 的存在,会分别以trace_idspan_id作为标记,向日志中注入 TraceID 和 SpanID。
日志框架
包路径
支持的版本范围
Zap
go.uber.org/zap/zapcore
1.20.0+
Logrus
github.com/sirupsen/logrus
1.5.0+
Zerolog
github.com/rs/zerolog
1.10.0+
go-kit/log
github.com/go-kit/log
0.1.0+
Go 标准库 log
log
无限制
Go 标准库 slog
log/slog
无限制
以 Zap 为例,注入 TraceID 和 SpanID 后生成的日志内容如下所示:
{"level":"info","msg":"this is info message","trace_id":"38e6910973e1c0c11351e502329d2d72","span_id":"6f4efff78445ea61"}

OpenTelemetry-Python

对于内置 logging 库,以及底层调用内置 logging 库的日志组件,通过添加OTEL_PYTHON_LOG_CORRELATION环境变量,即可实现对 TraceID 和 SpanID 的注入。
# Enable Log Correlation
OTEL_PYTHON_LOG_CORRELATION=true
tapm-instrument \\
--traces_exporter otlp \\
--metrics_exporter otlp \\
--logs_exporter none \\
--service_name python-web-test \\
--resource_attributes "token=xxxxx" \\
--exporter_otlp_endpoint xxxxxx \\
python main.py
开启日志关联后,生成的日志内容如下所示:
2026-02-25 19:51:25,069 INFO [__main__] [main.py:19] [trace_id=c20f528fa45eebc2cbdae9e341ced39a span_id=fa84ffb16a978ab6 resource.service.name=python-web-test trace_sampled=True]

OpenTelemetry-JS

对于满足要求的日志组件,无需额外的任何操作,即可实现对 TraceID 和 SpanID 的注入。如果探针检测到活跃 Span 的存在,会分别以trace_idspan_id作为标记,向日志中注入 TraceID 和 SpanID。
日志框架
包路径
支持的版本范围
Winston
github.com/winstonjs/winston
1.0.0+
Pino
github.com/pinojs/pino
5.14.0+
Bunyan
trentm/node-bunyan
1.0.0+
以 Bunyan 为例,注入 TraceID 和 SpanID 后生成的日志内容如下所示:
INFO: this is info message: GET / | trace_id="e793e3edafb93f98a8a395c13096a26f" span_id="9564de488477c6a8" trace_flags="01"
需要注意的是,如果在 Winston 框架中对日志进行自定义格式化,需要参考如下代码,手动将 TraceID 和 SpanID 附加到日志内容中:
const logger = winston.createLogger({
level: "info",
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(({ timestamp, level, message, trace_id, span_id }) => {
return `${timestamp} [${level.toUpperCase()}] [trace_id=${trace_id} span_id=${span_id}]: ${message}`;
})
),
transports: [new winston.transports.Console()],
});

OpenTelemetry-dotnet

对于满足要求的日志组件,通过修改日志配置文件中的 pattern,即可实现对 TraceID 和 SpanID 的注入。
日志框架
支持的版本范围
Log4Net
2.0.13+
NLog
5.0.0+

Log4Net

在日志配置文件中,TraceID 和 SpanID 分别使用%property{trace_id}%property{span_id}字段注入。
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message trace_id=%property{trace_id} span_id=%property{span_id} %newline" />
</layout>

NLog

在日志配置文件中,TraceID 和 SpanID 分别使用${event-properties:TraceId}span_id=${event-properties:SpanId}字段注入。
<target xsi:type="File" name="file" fileName="logs/app.log"
layout="${longdate} [${level:uppercase=true}] ${logger} - ${message} trace_id=${event-properties:TraceId} span_id=${event-properties:SpanId}" />


其他方案

对于其他方案,请使用 OpenTelemetry SDK 从链路上下文中获取 TraceID 和 SpanID,并附加到日志内容中。例如,通过 OpenTelemetry-Go SDK 接入的应用,可以参考如下代码片段将 TraceID 和 SpanID 打印到日志中:
func logWithTrace(ctx context.Context, format string, args ...interface{}) {
span := trace.SpanFromContext(ctx)
sc := span.SpanContext()

traceID := sc.TraceID().String()
spanID := sc.SpanID().String()

msg := fmt.Sprintf(format, args...)
log.Printf("[trace_id: %s span_id: %s] %s", traceID, spanID, msg)
}