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
- Save the Python example as demo.py and run python3 demo.py.
- Compare the checkout log trace_id and span_id with the console-exported span: the hexadecimal identifiers must match.
- The outside request log must have no trace_id or span_id. A fabricated or stale identifier would create a false join.
- After connecting a backend, emit a known request, find its log, open the trace by ID, and confirm the service and operation.
Common failures
| Symptom | Check |
|---|---|
| Missing IDs | The log ran outside an active span, or context was lost across a thread/task boundary. Check instrumentation and context propagation. |
| Trace cannot be found | Sampling, export failures, retention, or the wrong backend/tenant may prevent lookup even when a valid ID exists. |
| Duplicate logs or spans | Reuse the application provider and handlers; do not stack this standalone setup on automatic instrumentation. |
| Sensitive records | Use stable event messages and approved fields; do not place credentials or customer payloads into logs. |