腾讯云可观测平台 链路与日志关联分析

随着微服务架构的逐渐流行,在复杂且庞大的系统中准确地定位一个请求的完整生命周期,逐渐成为了研发人员面临的最大痛点之一。以研发自测过程为例,开发人员通常希望在发起 HTTP/RPC 测试请求后,能够以一个简单的方式获取整个测试请求的上下面信息。这其中通常包括相关的上下游链路、各个服务内部请求的方法堆栈,以及链路上打印的日志等数据,对于指标-链路-日志的一体化监控的需求已经迫在眉睫。

相关产品
腾讯云可观测平台 产品页,含版本规格、价格与购买入口。

腾讯云应用性能监控(APM)作为本身包含指标-链路的全链路监控平台,已与 腾讯云日志服务(CLS) 联手打通,实现指标-链路-日志的一体化监控。在查看链路详情时,关联查看所对应的信息,完成从链路到日志的排查流程。

一、前提条件

请确保应用已经接入应用性能监控(APM),并参考日志服务(CLS)入门指南 将业务日志上报到腾讯云日志服务(CLS)。

注意:说明:

注意:为了保障你日志数据的可靠性以及更高效地使用日志服务,建议你使用 CLS 优化后的接口/Agent 上传结构化日志:

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

为了实现链路和日志的关联查询,你需要将 TraceID 和 SpanID 输出到日志中。对于通过如下方案接入的应用,可以在不修改代码的情况下,将 TraceID 和 SpanID 自动注入到日志中:

·腾讯云增强版 OpenTelemetry Java 探针

·SkyWalking Java 探针

·腾讯云 OpenTelemetry-Go 探针

·OpenTelemetry-Python

·OpenTelemetry-JS

·OpenTelemetry-dotnet

对于通过其他方式接入的应用,请参考 其他方案,从链路上下文中获取 TraceID 和 SpanID,并附加到日志内容中。

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

1. 登录 腾讯云可观测平台。

2. 在左侧菜单栏选择应用性能监控 > 系统配置,进入业务系统配置页面。

3. 选择对应的业务系统,在日志关联中单击编辑。

4. 配置日志关联信息。

·开启关联日志。

·选择对应的日志地域、日志集、日志主题,并指定 TraceID 和 SpanID 所在的字段。

5. 配置完后单击确定即可。

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

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

1. 登录 腾讯云可观测平台。

2. 在左侧菜单栏选择应用性能监控 > 链路追踪,进入链路追踪页面。

3. 选择对应的业务系统,找到对应的 TraceID,单击 TraceID 进入链路详情。

4. 在 Trace 日志和 Span 日志标签页中,可以查询该链路对应的日志信息。

五、腾讯云增强版 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.PatternLayoutlog4j.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_id和span_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_id和span_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)}

赞 (0)
上一篇 4天前
下一篇 4天前