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.

This guide takes you from a freshly installed bundle to your first live trace in under five minutes. You will set a handful of environment variables, run the built-in doctor command to confirm everything is wired correctly, and then make a request to see spans appear in your tracing backend. No custom code is required to get automatic instrumentation running.

Prerequisites

Before starting, make sure you have the following in place:

Getting Started

1

Install the bundle

If you haven’t already, add the bundle to your project:
composer require traceway/opentelemetry-symfony
Then install the OTLP exporter and an HTTP client to ship traces:
composer require open-telemetry/exporter-otlp php-http/guzzle7-adapter
Symfony Flex registers the bundle automatically. Without Flex, add it to config/bundles.php:
return [
    // ...
    Traceway\OpenTelemetryBundle\OpenTelemetryBundle::class => ['all' => true],
];
2

Set environment variables

Add the following variables to your .env file (or .env.local to keep them out of version control):
OTEL_PHP_AUTOLOAD_ENABLED=true
OTEL_SERVICE_NAME=my-symfony-app
OTEL_TRACES_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/json
VariablePurpose
OTEL_PHP_AUTOLOAD_ENABLEDActivates the OpenTelemetry SDK when Composer’s autoloader is loaded. Must be true.
OTEL_SERVICE_NAMEIdentifies your application in the tracing backend. Use a short, stable name.
OTEL_TRACES_EXPORTERThe exporter to use. Set to otlp for any OpenTelemetry-compatible backend.
OTEL_EXPORTER_OTLP_ENDPOINTBase URL of your OTLP receiver. Port 4318 is standard for HTTP.
OTEL_EXPORTER_OTLP_PROTOCOLWire format for OTLP export. Use http/json for the widest compatibility.
http/json is the best default protocol if you have not installed the ext-protobuf C extension. It works on every managed Symfony host and is fully supported by Jaeger, Grafana Tempo, Honeycomb, Traceway, and AWS X-Ray. Switch to http/protobuf later if you need lower serialization overhead in production.
3

Verify the wiring with traceway:doctor

Run the built-in diagnostic command to confirm that the SDK is configured correctly and your OTLP endpoint is reachable:
bin/console traceway:doctor
A healthy output looks like this:
Runtime
  ✓ ext-opentelemetry not loaded (no conflict risk)
SDK configuration
  ✓ OTEL_SERVICE_NAME = "my-symfony-app"
  ✓ OTEL_TRACES_EXPORTER = otlp
Connectivity
  ✓ OTLP endpoint reachable (HTTP 404, 7ms)
Results: 9 ok, 0 warning, 0 error, 3 skipped, 0 info
An HTTP 404 response from the OTLP endpoint connectivity check is expected and counts as reachable — it means the server responded, which is all the check needs to confirm. A real connection refused or DNS failure produces an error.
You can also output results as JSON for CI pipeline consumption:
bin/console traceway:doctor --format=json
4

Make a request and see your traces

Start your Symfony application and make any HTTP request — a page load, an API call, or even a console command:
# HTTP request
curl http://localhost:8000/

# Or a console command
bin/console about
Open your tracing backend and look for a trace named after your service (my-symfony-app). You should see spans for the HTTP request, any database queries, cache operations, and template renders — all automatically, without writing a single line of instrumentation code.

What’s Traced Automatically

Once the bundle is installed and configured, the following components produce spans with no additional setup:
  • HTTP requests — every incoming request with route template, status code, and client IP
  • Console commands — name, arguments, exit code, and any thrown exceptions
  • Outgoing HttpClient calls — with W3C trace context propagation to downstream services
  • Messenger messages — producer and consumer spans with async context propagation
  • Doctrine DBAL queries — parameterised SQL, transactions, and database metadata
  • Cache operationsget (hit/miss), delete, and invalidateTags per pool
  • Twig renders — template name and nested includes
  • Mailer sends — two-span split across MailerInterface::send and the transport layer
  • Scheduler jobsRecurringMessage execution with trigger metadata
  • Monolog logstrace_id and span_id injected into every log record

Manual Instrumentation

For business-logic spans beyond automatic instrumentation, inject TracingInterface into any service:
use Traceway\OpenTelemetryBundle\TracingInterface;

class OrderService
{
    public function __construct(private readonly TracingInterface $tracing) {}

    public function process(int $orderId): void
    {
        $this->tracing->trace('order.validate', fn () => $this->validate($orderId));
        $this->tracing->trace('order.fulfill', function () {
            $this->tracing->trace('inventory.reserve', fn () => $this->reserve());
            $this->tracing->trace('payment.charge', fn () => $this->charge());
        });
    }
}
In tests, stub the interface with $this->createStub(TracingInterface::class) — the stub invokes the callback directly so your business logic runs unmodified.

Next Steps

Configuration Reference

Explore all open_telemetry configuration options — excluded paths, metrics, log export, SDK settings, and more.

Metrics

Enable opt-in OTel metrics and create custom counters and histograms with MeterRegistryInterface.

Build docs developers (and LLMs) love