Prerequisites

  • Python with opentelemetry-api and opentelemetry-sdk installed in a dedicated environment.
  • A fresh process for this runnable console demonstration; existing applications should reuse their configured provider and logging handlers.

Install dependencies

python3 -m pip install opentelemetry-api opentelemetry-sdk

Runnable example

import json
import logging
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter

provider = TracerProvider(resource=Resource.create({"service.name": "checkout-demo"}))
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("correlation-demo")

class TraceJSON(logging.Formatter):
    def format(self, record):
        ctx = trace.get_current_span().get_span_context()
        payload = {"message": record.getMessage(), "service.name": "checkout-demo"}
        if ctx.is_valid:
            payload["trace_id"] = format(ctx.trace_id, "032x")
            payload["span_id"] = format(ctx.span_id, "016x")
        return json.dumps(payload)

logger = logging.getLogger("checkout-demo")
logger.setLevel(logging.INFO)
logger.propagate = False
handler = logging.StreamHandler()
handler.setFormatter(TraceJSON())
logger.addHandler(handler)
with tracer.start_as_current_span("checkout"):
    logger.info("checkout completed")
logger.info("outside request")
provider.shutdown()

Connect your backend

This demonstration uses console export so no backend is required. For an application, configure your existing OTLP trace exporter and log shipper, preserve trace_id and span_id as searchable fields, and configure the log backend link to your trace backend. The formatter enriches stdout/stderr logs; it does not export OpenTelemetry log records.

Verification checklist

  1. Save the Python example as demo.py and run python3 demo.py.
  2. Compare the checkout log trace_id and span_id with the console-exported span: the hexadecimal identifiers must match.
  3. The outside request log must have no trace_id or span_id. A fabricated or stale identifier would create a false join.
  4. After connecting a backend, emit a known request, find its log, open the trace by ID, and confirm the service and operation.

Common failures

Troubleshooting the connection
SymptomCheck
Missing IDsThe log ran outside an active span, or context was lost across a thread/task boundary. Check instrumentation and context propagation.
Trace cannot be foundSampling, export failures, retention, or the wrong backend/tenant may prevent lookup even when a valid ID exists.
Duplicate logs or spansReuse the application provider and handlers; do not stack this standalone setup on automatic instrumentation.
Sensitive recordsUse stable event messages and approved fields; do not place credentials or customer payloads into logs.

Related concepts

Related signals

Related patterns

Related guides

Official documentation