Automatic instrumentation covers framework-level operations, but business logic — order processing, third-party API calls, custom queue handling — often deserves its own spans.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.
TracingInterface gives you a single trace() method that wraps any callable in a properly lifecycle-managed span, handles exceptions, and propagates context, all without the ceremony of building a tracer, starting a span, and managing scopes manually.
Interface Signature
Tracing implementation also implements Symfony’s ResetInterface, so span state is cleared automatically between Messenger worker cycles, FrankenPHP loops, and RoadRunner requests — no stale context leaks between jobs.
Injecting and Using TracingInterface
Use constructor injection to receive the service. Because you typehint against the interface rather than the concrete class, swapping it out in tests requires no container override.order.fulfill span automatically becomes the parent of inventory.reserve and payment.charge because trace() activates the span as the current context for the duration of the callback. No manual context threading is required.
Parameters Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
$name | non-empty-string | (required) | Span name shown in your backend — use dot-namespaced names like db.query, payment.charge, inventory.reserve for readability |
$callback | callable(): T | (required) | The callable to execute inside the span; its return value is returned from trace() unchanged |
$attributes | array<string, mixed> | [] | Key-value span attributes applied before the callback runs — useful for IDs, types, and context that are known upfront |
$kind | SpanKind::KIND_* | KIND_INTERNAL | OTel span kind: KIND_INTERNAL (default), KIND_CLIENT (outgoing RPC/DB calls), KIND_SERVER (inbound calls), KIND_PRODUCER (message publish), KIND_CONSUMER (message processing) |
Setting Span Attributes
Attributes are set before the callback executes, so they appear on the span even if the callback throws:Exception Handling
If the callback throws,trace() calls recordException() and sets STATUS_ERROR on the span before re-throwing the original exception. Your error budgets and alerting rules on the backend will see the failure without any extra code.
Testing
Because all service code typehints againstTracingInterface, testing is straightforward with PHPUnit stubs:
For integration tests that should assert on span output, configure an in-memory exporter in your test environment. The stub approach is recommended for unit tests where you care about logic, not observability.
Behavior Without an Active SDK
WhenOTEL_PHP_AUTOLOAD_ENABLED is not set to true (or when no SDK is configured), TracingInterface::trace() checks whether the tracer is enabled and, if not, invokes the callback directly without creating any span. There is no performance overhead and no errors — the service degrades gracefully to a plain function call.
ResetInterface and long-running processes — Tracing implements Symfony’s ResetInterface. The Messenger worker, FrankenPHP, and RoadRunner all call reset() between requests/messages, which clears the cached tracer reference and enabled flag. This guarantees that a stale “enabled=false” decision from one cycle does not carry over to the next after the SDK is reloaded.