本文介绍如何使用OpenTelemetry将TraceId和SpanId自动写入日志。TraceId与SpanId写入日志后,您可以将分布式链路数据与日志数据关联起来,实现更高效的故障诊断和性能分析。
Java
支持的日志库
更多信息,请参见 Logger MDC auto-instrumentation。
日志框架 | 自动埋点支持的版本 | 手动埋点需要引入的依赖 |
Log4j1 | 1.2+ | 无 |
Log4j2 | 2.7+ | |
Logback | 1.0+ |
使用Log4j2
在pom.xml中添加OpenTelemetry Log4j2依赖。
请将
OPENTELEMETRY_VERSION
替换为最新版本。<dependencies> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-log4j-context-data-2.17-autoconfigure</artifactId> <version>OPENTELEMETRY_VERSION</version> <scope>runtime</scope> </dependency> </dependencies>
修改log4j2.xml配置,在pattern中添加
%X{trace_id}
与%X{span_id}
,可以将TraceId与SpanId自动写入日志。以下为日志格式示例:
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} - %msg%n"/> </Console> </Appenders> <Loggers> <Root> <AppenderRef ref="Console" level="All"/> </Root> </Loggers> </Configuration>
使用Logback
在pom.xml中添加OpenTelemetry Logback依赖。
请将
OPENTELEMETRY_VERSION
替换为最新版本。<dependencies> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-logback-mdc-1.0</artifactId> <version>OPENTELEMETRY_VERSION</version> </dependency> </dependencies>
修改logback.xml配置,在pattern中添加
%X{trace_id}
与%X{span_id}
,可以将TraceId与SpanId自动写入日志。以下为日志格式示例:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} %msg%n</pattern> </encoder> </appender> <!-- Just wrap your logging appender, for example ConsoleAppender, with OpenTelemetryAppender --> <appender name="OTEL" class="io.opentelemetry.instrumentation.logback.mdc.v1_0.OpenTelemetryAppender"> <appender-ref ref="CONSOLE"/> </appender> <!-- Use the wrapped "OTEL" appender instead of the original "CONSOLE" one --> <root level="INFO"> <appender-ref ref="OTEL"/> </root> </configuration>
使用Logback(SpringBoot项目)
Spring Boot项目内置了日志框架,并且默认使用Logback作为其日志实现。如果您的Java项目为SpringBoot项目,只需少量配置即可将TraceId写入日志。
在application.properties中设置logging.pattern.level,添加%mdc{trace_id}
与%mdc{span_id}
到日志中。
logging.pattern.level=trace_id=%mdc{trace_id} span_id=%mdc{span_id} %5p
以下为日志示例:
2024-06-26 10:56:31.200 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=1b08f18b8858bb9a INFO 53724 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-06-26 10:56:31.201 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=1b08f18b8858bb9a INFO 53724 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2024-06-26 10:56:31.209 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=1b08f18b8858bb9a INFO 53724 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 8 ms
2024-06-26 10:56:31.296 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=5743699405074f4e INFO 53724 --- [nio-8081-exec-1] com.example.httpserver.ot.OTServer : hello world
Go
OpenTelemetry Go不支持自动注入,需要在记录日志时手动注入TraceId和SpanId。
使用logrus
引入依赖。
import ( oteltrace "go.opentelemetry.io/otel/trace" "github.com/sirupsen/logrus" )
创建工具函数,从Span中提取SpanID和TraceID,并添加到Logrus日志字段。
func LogrusFields(span oteltrace.Span) logrus.Fields { return logrus.Fields{ "trace_id": span.SpanContext().TraceID().String(), "span_id": span.SpanContext().SpanID().String(), } }
创建一个Span后,即可记录带有TraceId和SpanId的日志。
... _, span := tracer.Start(ctx, "spanName") defer span.End() logEntry := logrus.WithFields(LogrusFields(span)) logEntry.Info("This is an info message with trace and span ID") ...
Python
OpenTelemetry Python支持自动将TraceId与SpanId注入到日志中。更多信息,请参见 OpenTelemetry Logging Instrumentation。
使用logging
设置环境变量OTEL_PYTHON_LOG_CORRELATION为
true
,开启自动将TraceId与SpanId添加到日志条目中的能力。export OTEL_PYTHON_LOG_CORRELATION=true
在日志格式中添加
%(otelTraceID)s
和%(otelSpanID)s
,OpenTelemetry会自动将日志中的%(otelTraceID)s
和%(otelSpanID)s
替换为TraceId和SpanId。以下为logging.Formatter示例。
formatter = logging.Formatter( '%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s] - %(message)s' )
以下为日志示例。
2024-06-25 10:00:55,494 INFO [app] [app.py:80] [trace_id=70561de6a164ac991bfff2281b7f**** span_id=4b7f3c798460**** resource.service.name=ot-python-demo] - hello world
操作示例
下文将以Demo应用Helloword为例,说明如何在Python中自动将TraceId与SpanId注入到日志中。
请确保您已安装Python和pip。本示例使用的是Python 3.12.4、pip 24.1.1。
安装本示例使用到的Flask框架。
pip3 install flask
预期输出:
Successfully installed Jinja2-3.1.4 MarkupSafe-2.1.5 Werkzeug-3.0.3 blinker-1.8.2 click-8.1.7 flask-3.0.3 itsdangerous-2.2.0
输出类似信息,说明Flask框架安装成功。
安装OpenTelemetry Python相关的包和工具。
pip3 install opentelemetry-distro \ opentelemetry-exporter-otlp opentelemetry-bootstrap -a install
预期输出:
Successfully installed opentelemetry-instrumentation-dbapi-0.46b0 Successfully installed opentelemetry-instrumentation-requests-0.46b0 Successfully installed opentelemetry-instrumentation-urllib3-0.46b0
输出类似信息,说明OpenTelemetry Python相关的包和工具安装成功。
创建Demo应用。
import logging from logging.handlers import RotatingFileHandler from flask import Flask import os app = Flask(__name__) # 创建格式化器,其中包含OpenTelemetry上下文信息 formatter = logging.Formatter( '%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s] - %(message)s' ) # 创建一个RotatingFileHandler来记录日志到文件 # 注意将/path/to/app.log替换为您的日志文件存放的实际路径 file_handler = RotatingFileHandler('/path/to/app.log', maxBytes=10000, backupCount=1) file_handler.setLevel(logging.INFO) file_handler.setFormatter(formatter) app.logger.addHandler(file_handler) @app.route('/') def hello_world(): app.logger.info('Hello World!!!') return 'Hello, World!' if __name__ == '__main__': app.run()
运行Demo应用,预期输出:
* Running on http://127.0.**.**:5000
说明应用部署成功。
设置环境变量,开启自动将TraceId与SpanId添加到日志条目中的能力,并自动将OpenTelemetry的仪器化代码植入应用程序中。
export OTEL_PYTHON_LOG_CORRELATION=true export OTEL_SERVICE_NAME=ot-python-demo export OTEL_TRACES_EXPORTER=otlp export OTEL_METRICS_EXPORTER=none # 请将test.py替换为实际文件名称 opentelemetry-instrument python3 test.py
查看日志文件,日志样例如下。
2024-06-25 10:00:55,494 INFO [app] [test.py:80] [trace_id=70561de6a164ac991bfff2281b7f**** span_id=4b7f3c798460**** resource.service.name=ot-python-demo] - hello world
说明TraceId与SpanId已被添加到日志条目中。