All Products
Search
Document Center

Managed Service for OpenTelemetry:Write trace IDs and span IDs to logs

Last Updated:Aug 07, 2024

This topic describes how to use OpenTelemetry to automatically write trace IDs and span IDs to logs. After trace IDs and span IDs are written to logs, you can associate distributed trace data with log data for more efficient fault diagnostics and performance analysis.

Java

Supported logging libraries

For more information, see Logger MDC auto-instrumentation.

Logging framework

Version that supports automatic instrumentation

Required dependency to be introduced for manual instrumentation

Log4j1

1.2 and later

N/A

Log4j2

2.7 and later

opentelemetry-log4j-context-data-2.17-autoconfigure

Logback

1.0 and later

opentelemetry-logback-mdc-1.0

Use Log4j2

  1. Add the OpenTelemetry Log4j2 dependency to the pom.xml file.

    Replace OPENTELEMETRY_VERSION with the latest 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. Open log4j2.xml, and add %X{trace_id} and %X{span_id} to pattern to enable automatic writing of trace IDs and span IDs to logs.

    The following example shows the log format:

    <?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>

Use Logback

  1. Add the OpenTelemetry Logback dependency to the pom.xml file.

    Replace OPENTELEMETRY_VERSION with the latest version.

    <dependencies>
      <dependency>
        <groupId>io.opentelemetry.instrumentation</groupId>
        <artifactId>opentelemetry-logback-mdc-1.0</artifactId>
        <version>OPENTELEMETRY_VERSION</version>
      </dependency>
    </dependencies>
  2. Open logback.xml, and add %X{trace_id} and %X{span_id} to pattern to enable automatic writing of trace IDs and span IDs to logs.

    The following example shows the log format:

    <?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>

Use Logback (Spring Boot projects)

A Spring Boot project has a built-in logging framework, which is Logback by default. If you are developing a Java Spring Boot project, you can enable automatic writing of trace IDs and span IDs to logs with simple configuration.

Open the application.properties file and add application.properties and %mdc{span_id} to logging.pattern.level.

logging.pattern.level=trace_id=%mdc{trace_id} span_id=%mdc{span_id} %5p

The following example shows some logs:

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 in Go does not support automatic writing of trace IDs and span IDs to logs. If you do not perform extra development operations such as the following ones, you need to manually record trace IDs and span IDs.

Use logrus

  1. Add dependencies.

    import (
        oteltrace "go.opentelemetry.io/otel/trace"
        "github.com/sirupsen/logrus"
    )
  2. Create a tool function to extract trace IDs and span IDs from spans and add them to the Logrus log field.

    func LogrusFields(span oteltrace.Span) logrus.Fields {
        return logrus.Fields{
            "trace_id": span.SpanContext().TraceID().String(),
            "span_id": span.SpanContext().SpanID().String(),
        }
    }
  3. After a span is created, a log with a trace ID and a span ID is generated.

    ...
    _, 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 in Python supports automatic writing of trace IDs and span IDs to logs. For more information, see OpenTelemetry Logging Instrumentation.

Use logging

  1. Set the OTEL_PYTHON_LOG_CORRELATION environment variable to true to enable automatic writing of trace IDs and span IDs to logs.

    export OTEL_PYTHON_LOG_CORRELATION=true
  2. Add %(otelTraceID)s and %(otelSpanID)s to the log format. OpenTelemetry automatically replaces %(otelTraceID)s and %(otelSpanID)s in logs with trace IDs and span IDs.

    • The following example shows a log format:

      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'
      )
    • The following example shows a log:

      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

Operation example

In the following example, a demo application named Helloword is used to show how to automatically write trace IDs and span IDs to logs in Python.

Before you start, make sure that Python and pip are installed. In this example, Python 3.12.4 and pip 24.1.1 are used.

  1. Install the Flask framework.

    pip3 install flask

    Expected output:

    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

    If information similar to the preceding output is displayed, the installation is successful.

  2. Install the required OpenTelemetry Python packages and tools.

    pip3 install opentelemetry-distro \
            opentelemetry-exporter-otlp
    opentelemetry-bootstrap -a install

    Expected output:

    Successfully installed opentelemetry-instrumentation-dbapi-0.46b0
    Successfully installed opentelemetry-instrumentation-requests-0.46b0
    Successfully installed opentelemetry-instrumentation-urllib3-0.46b0

    If information similar to the preceding output is displayed, the installation is successful.

  3. Create an application by using the sample code.

    import logging
    from logging.handlers import RotatingFileHandler
    from flask import Flask
    
    import os
    
    app = Flask(__name__)
    
    # Create a formatter that contains the OpenTelemetry context.
    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'
    )
    
    # Create a RotatingFileHandler to write logs to a file.
    # Replace /path/to/app.log with the actual path of the log file.
    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()
    

    Run the demo application. Expected output:

    * Running on http://127.0.**.**:5000

    If information similar to the preceding output is displayed, the application deployment is successful.

  4. Set environment variables to enable automatic writing of trace IDs and span IDs to logs and use OpenTelemetry to automatically instrument the demo application.

    export OTEL_PYTHON_LOG_CORRELATION=true
    export OTEL_SERVICE_NAME=ot-python-demo
    export OTEL_TRACES_EXPORTER=otlp
    export OTEL_METRICS_EXPORTER=none
    
    # Replace test.py with the actual file name.
    opentelemetry-instrument python3 test.py
  5. View the log file. The following example shows a log:

    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

    In this example, a trace ID and a span ID are recorded in the log.

Bilateral association between traces and Simple Log Service

Associate logs with traces. For more information, see Log association.

Associate traces with logs in Simple Log Service. For more information, see Associate application logs with trace IDs in Simple Log Service.