全部產品
Search
文件中心

Managed Service for OpenTelemetry:將TraceId和SpanId寫入日誌

更新時間:Jul 11, 2024

本文介紹如何使用OpenTelemetry將TraceId和SpanId自動寫入日誌。TraceId與SpanId寫入日誌後,您可以將分布式鏈路資料與日誌資料關聯起來,實現更高效的故障診斷和效能分析。

Java

支援的日誌庫

更多資訊,請參見 Logger MDC auto-instrumentation

日誌架構

自動埋點支援的版本

手動埋點需要引入的依賴

Log4j1

1.2+

Log4j2

2.7+

opentelemetry-log4j-context-data-2.17-autoconfigure

Logback

1.0+

opentelemetry-logback-mdc-1.0

使用Log4j2

  1. 在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>
  2. 修改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

  1. 在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>
  2. 修改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

  1. 引入依賴。

    import (
        oteltrace "go.opentelemetry.io/otel/trace"
        "github.com/sirupsen/logrus"
    )
  2. 建立工具函數,從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(),
        }
    }
  3. 建立一個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

  1. 設定環境變數OTEL_PYTHON_LOG_CORRELATION為true,開啟自動將TraceId與SpanId添加到日誌條目中的能力。

    export OTEL_PYTHON_LOG_CORRELATION=true
  2. 在日誌格式中添加%(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。

  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架構安裝成功。

  2. 安裝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相關的包和工具安裝成功。

  3. 建立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

    說明應用部署成功。

  4. 設定環境變數,開啟自動將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
  5. 查看記錄檔,日誌範例如下。

    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已被添加到日誌條目中。

調用鏈與Log ServiceSLS雙向關聯

在調用鏈裡關聯日誌

在Log ServiceSLS中關聯調用鏈