cyberclick-tech/otel-bundle

OpenTelemetry Symfony bundle with tracing, logging correlation, Doctrine instrumentation and Messenger middleware

Maintainers

Package info

github.com/cyberclick-tech/otel-bundle

Type:symfony-bundle

pkg:composer/cyberclick-tech/otel-bundle

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.0.5 2026-03-14 16:06 UTC

This package is auto-updated.

Last update: 2026-03-14 16:34:58 UTC


README

Symfony bundle for OpenTelemetry instrumentation. Provides automatic tracing for HTTP requests, outgoing HTTP calls, console commands, Doctrine queries, and Symfony Messenger messages, plus log-trace correlation via Monolog.

Installation

composer require cyberclick-tech/otel-bundle

Register the bundle in config/bundles.php:

CyberclickTech\OtelBundle\CyberclickOtelBundle::class => ['all' => true],

Configuration

Set the required environment variables:

OTEL_SERVICE_NAME=myapp
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318

Optional:

OTEL_DB_INSTANCE=mydb  # Database name shown in DB spans (defaults to empty)

What it does out of the box

  • HTTP tracing: Creates spans for every incoming HTTP request with http.method, http.route, http.host, http.status_code
  • Console tracing: Creates spans for console commands with exit codes
  • Log correlation: Injects trace_id and span_id into Monolog log records via a processor

Optional instrumentation

The following features require explicit configuration in your app's services:

HTTP client tracing

Traces outgoing HTTP calls made via Symfony HttpClient. You choose which clients to instrument by decorating them in your services config:

# Trace ALL outgoing HTTP calls
CyberclickTech\OtelBundle\HttpClient\TracingHttpClient:
    decorates: http_client
    arguments:
        $client: '@.inner'
        $tracer: '@cyberclick_otel.tracer'
# Trace only a specific scoped client
CyberclickTech\OtelBundle\HttpClient\TracingHttpClient:
    decorates: http_client.catastro
    arguments:
        $client: '@.inner'
        $tracer: '@cyberclick_otel.tracer'

Spans are created with http.method, http.url, http.host, http.status_code.

Doctrine tracing

Creates spans for every SQL query with db.system, db.name, db.statement, db.operation.

If you use Doctrine's standard configuration, add the middleware to your DBAL connection:

doctrine:
    dbal:
        connections:
            default:
                middlewares:
                    - 'CyberclickTech\OtelBundle\Doctrine\TracingMiddleware'

If you use a custom EntityManagerFactory, inject the middleware and pass it to setMiddlewares():

use CyberclickTech\OtelBundle\Doctrine\TracingMiddleware;
use Doctrine\DBAL\Driver\Middleware;

public static function create(array $parameters, ?Middleware $tracingMiddleware = null): EntityManager
{
    $dbalConfig = new \Doctrine\DBAL\Configuration();
    if ($tracingMiddleware !== null) {
        $dbalConfig->setMiddlewares([$tracingMiddleware]);
    }
    // ...
}
# services.yaml
App\EntityManagerFactory:
    arguments:
        $tracingMiddleware: '@CyberclickTech\OtelBundle\Doctrine\TracingMiddleware'

Messenger middleware

Traces Symfony Messenger message handling:

framework:
    messenger:
        buses:
            command.bus:
                middleware:
                    - cyberclick_otel.messenger.tracing_middleware

Message tracer (RabbitMQ consumers)

MessageTracerInterface provides manual span management for RabbitMQ consumers with automatic forceFlush() for long-running processes:

use CyberclickTech\OtelBundle\Tracing\MessageTracerInterface;

final class MyConsumer
{
    public function __construct(private MessageTracerInterface $tracer) {}

    public function consume(string $queueName, string $body): void
    {
        $this->tracer->start($queueName, $body);
        $this->tracer->recordSpan('my_event', $body, 'domain_event', 'consume');

        try {
            // process message...
            $this->tracer->stopSpan('my_event');
            $this->tracer->end('OK');
        } catch (\Throwable $e) {
            $this->tracer->registerError($e);
            $this->tracer->stopSpan('my_event');
            $this->tracer->end('KO');
        }
    }
}

Custom span attributes

To add application-specific attributes to HTTP and message spans (e.g., tenant ID, user ID), implement SpanAttributeExtractorInterface:

use CyberclickTech\OtelBundle\SpanAttributeExtractorInterface;
use Symfony\Component\HttpFoundation\Request;

final class MyAppSpanAttributeExtractor implements SpanAttributeExtractorInterface
{
    /**
     * Attributes added to the root HTTP span (called during kernel.controller).
     */
    public function fromRequest(Request $request): array
    {
        return [
            'enduser.id' => $request->attributes->get('authenticated_uid'),
            'tenant.id' => $request->get('tenantId'),
        ];
    }

    /**
     * Attributes added to RabbitMQ consumer spans.
     */
    public function fromMessageBody(?string $body): array
    {
        $data = json_decode($body ?? '{}');
        return [
            'tenant.id' => $data?->data?->attributes?->tenant_id ?? null,
        ];
    }
}

Register it in your services config to override the default (no-op) extractor:

Actel\Shared\Infrastructure\OpenTelemetry\MyAppSpanAttributeExtractor: ~

CyberclickTech\OtelBundle\SpanAttributeExtractorInterface:
    alias: Actel\Shared\Infrastructure\OpenTelemetry\MyAppSpanAttributeExtractor

Service IDs

Service Description
cyberclick_otel.tracer_provider TracerProvider instance
cyberclick_otel.tracer TracerInterface instance
cyberclick_otel.messenger.tracing_middleware Messenger middleware
CyberclickTech\OtelBundle\Tracing\MessageTracerInterface Message tracer for consumers
CyberclickTech\OtelBundle\Doctrine\TracingMiddleware Doctrine DBAL middleware
CyberclickTech\OtelBundle\HttpClient\TracingHttpClient HTTP client decorator (manual registration)

Requirements

  • PHP >= 8.2
  • Symfony 6.4 or 7.x
  • OpenTelemetry PHP SDK