Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tracewayapp/opentelemetry-symfony-bundle/llms.txt

Use this file to discover all available pages before exploring further.

The bundle provides two complementary log features: log-trace correlation, which injects the active trace_id and span_id into every Monolog record so you can jump from a log line to its matching trace, and OTel log export, which forwards Monolog records to any OpenTelemetry-compatible log backend via the OTel Logs API. Both features work independently and can be enabled or disabled without affecting the other.

Log-Trace Correlation

Log-trace correlation is enabled by default. The TraceContextProcessor reads the active OTel span from the current context and appends trace_id and span_id to the extra array of every Monolog record. If there is no active span (e.g. a log emitted outside a request), the record is passed through unchanged.
# config/packages/open_telemetry.yaml
open_telemetry:
    logs:
        correlation:
            enabled: true    # default — no change needed
With correlation active, every log record written during a traced request or job will carry:
FieldExample value
extra.trace_id4bf92f3577b34da6a3ce929d0e0e4736
extra.span_id00f067aa0ba902b7
These values can be forwarded by any existing Monolog handler (file, Elasticsearch, Datadog, etc.) — no OTel export infrastructure is required.
Correlation is injected by TraceContextProcessor, a standard Monolog ProcessorInterface. It is wired automatically when logs.correlation.enabled: true. If you use Monolog’s IntrospectionProcessor, add it before the trace context processor so the call site is resolved first.

OTel Log Export

OTel log export is opt-in and requires symfony/monolog-bundle. When enabled, the OtelLogHandler is registered as a Monolog handler and exports records to any backend configured via OTEL_LOGS_EXPORTER.

Enabling Export

# config/packages/open_telemetry.yaml
open_telemetry:
    logs:
        export:
            enabled: true
            level: debug                      # minimum Monolog level to export
            capture_code_attributes: false    # fallback debug_backtrace (see below)
            unprefixed_attributes: true       # flat context/extra fields (recommended)
Set the exporter and endpoint via environment variables:
OTEL_LOGS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318

Configuration Options

KeyDefaultDescription
leveldebugMinimum Monolog level forwarded to OTel. Records below this level are dropped before reaching the handler.
capture_code_attributesfalseWhen true and Monolog’s IntrospectionProcessor is not active, the handler walks debug_backtrace() to find the application call site and populate code.* attributes.
unprefixed_attributestrueSee below.

unprefixed_attributes (Default: true)

When unprefixed_attributes: true, log context and extra fields are emitted as flat OTel attributes — for example, a context key user_id becomes the attribute user_id. This matches the convention used by the official OpenTelemetry SDKs for Java, Python, .NET, and JavaScript, making cross-language log correlation dashboards easier to build. When unprefixed_attributes: false, context fields are prefixed as monolog.context.* and extra fields as monolog.extra.*. Use this only if you need to distinguish Monolog-originated attributes from other OTel attributes in a shared schema.
# Recommended (default) — flat attributes matching Java/Python/.NET/JS
open_telemetry:
    logs:
        export:
            unprefixed_attributes: true

# Alternative — namespaced attributes
open_telemetry:
    logs:
        export:
            unprefixed_attributes: false

Instrumentation Scope per Channel

Each Monolog channel becomes its own OTel instrumentation scope. A log from the security channel is exported under the scope name security, and a log from app appears under app. This matches the behavior of the official opentelemetry-logger-monolog contrib handler and allows backends to filter or route logs by channel without introducing a separate attribute.
The Monolog channel name is the instrumentation scope name, not a log attribute. It will not appear as monolog.channel in the exported record — look for it in the scope metadata of your backend’s log viewer.

code.* Attributes

OtelLogHandler emits the following OTel semantic-convention code attributes (Stable):
AttributeSource
code.file.pathAbsolute path to the source file containing the log call
code.line.numberLine number within that file
code.function.nameFully qualified function name, e.g. App\Service\OrderService::process

Source 1 — IntrospectionProcessor (Free)

If Monolog’s IntrospectionProcessor is registered, it writes file, line, class, and function into $record->extra. The handler promotes these to code.* attributes automatically and drops the raw keys from the extra namespace to avoid duplication — no additional configuration required.

Source 2 — capture_code_attributes: true (Opt-in)

When capture_code_attributes: true and the IntrospectionProcessor extras are absent, the handler calls debug_backtrace(), walking past Monolog internals, Symfony Bridge frames, and bundle handler frames to find the first application frame. This adds a small overhead per log record and is disabled by default.
open_telemetry:
    logs:
        export:
            capture_code_attributes: true
If you already have IntrospectionProcessor in your Monolog configuration, capture_code_attributes has no additional effect and can remain false. The backtrace fallback only activates when the processor extras are not populated.

Re-entrance Guard

OtelLogHandler includes a re-entrance guard ($emitting flag). If the OTel export path itself emits a Monolog record (e.g. the OTLP HTTP exporter logs a failed send), the guard prevents infinite recursion. The nested log record is silently dropped rather than causing a loop.

Combining Correlation and Export

Both features can be active simultaneously. When they are, the OTel SDK sets trace_id and span_id natively on the exported LogRecord from the active span context. The handler skips extra.trace_id and extra.span_id values that TraceContextProcessor wrote — they are duplicates at that point — so your exported records will not carry redundant trace fields.
open_telemetry:
    logs:
        correlation:
            enabled: true     # injects into extra for file/Elasticsearch/etc. handlers
        export:
            enabled: true     # forwards to OTel backend; SDK sets trace context natively
            level: warning    # only export warnings and above
For the full list of logs.* configuration keys and the OTEL_LOGS_EXPORTER environment variable reference, see the Configuration Reference.

Build docs developers (and LLMs) love