本文介紹如何使用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已被添加到日志條目中。