flow php

Symfony Telemetry Bundle

Flow Symfony Telemetry Bundle provides automatic telemetry integration for Symfony applications, including HTTP request/response tracing, console command instrumentation, and configurable exporters through OpenTelemetry-compatible backends.

Installation

composer require flow-php/symfony-telemetry-bundle:~0.31.0

Overview

This bundle integrates Flow PHP's Telemetry library with Symfony applications. It provides:

  • Automatic resource detection - Detects service name, version, environment, OS, host, and process information
  • 8 auto-instrumentation options - HTTP kernel, console, messenger, Twig, HTTP client, PSR-18 client, Doctrine DBAL, and cache
  • Context propagation - W3C TraceContext and Baggage support for distributed tracing
  • Configurable exporters - Console, memory, void, or OTLP with multiple transport options
  • Full Symfony configuration - Configure everything through Symfony's config system

Configuration Reference

Resource Configuration

The resource node configures OpenTelemetry Resource attributes that identify your service.

flow_telemetry:
  resource:
    detectors:
      enabled: true  # Enable resource detectors (default: true)
      static:
        cache:
          enabled: true  # Cache static attributes (default: true)
          path: null     # Cache path (default: kernel cache dir)
        os:
          enabled: true  # Detect os.type, os.name, os.version, os.description
        host:
          enabled: true  # Detect host.name, host.arch, host.id
        service:
          enabled: true  # Detect service.name, service.version from composer.json
        deployment:
          enabled: true  # Detect deployment.environment.name from kernel environment
        environment:
          enabled: true  # Read OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES
      dynamic:
        process:
          enabled: true  # Detect process.pid, process.runtime.*, process.executable.*
    custom:
      service.name: 'my-app'
      service.version: '1.0.0'
      deployment.environment.name: 'production'

Detector types:

Type Class Category Attributes Detected
os OsDetector static os.type, os.name, os.version, os.description
host HostDetector static host.name, host.arch, host.id
service ComposerDetector static service.name, service.version (from composer.json)
deployment SymfonyDeploymentDetector static deployment.environment.name (from kernel environment)
environment EnvironmentDetector static Reads OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES env vars
process ProcessDetector dynamic process.pid, process.runtime.*, process.executable.*

Static detectors are cached by default. Dynamic detectors run on every request/command.

Custom attributes override auto-detected values.

Clock Configuration

  • type: string|null
  • default: null

Custom PSR-20 clock service ID. If not provided, uses the built-in SystemClock.

flow_telemetry:
  clock_service_id: 'app.clock'

Context Storage

  • type: enum
  • default: memory

Context storage for maintaining trace context across async operations.

flow_telemetry:
  context_storage:
    type: memory  # memory|service
    service_id: null  # Custom service ID (only for type: service)

Propagator

  • type: enum
  • default: w3c

Context propagator for distributed tracing. Determines how trace context is injected/extracted from HTTP headers.

flow_telemetry:
  propagator:
    type: w3c  # w3c|tracecontext|baggage|service
    service_id: null  # Custom service ID (only for type: service)
Type Description
w3c W3C TraceContext + Baggage (recommended)
tracecontext W3C TraceContext only
baggage W3C Baggage only
service Custom propagator service

TracerProvider

Configures the tracer provider for distributed tracing.

flow_telemetry:
  tracer_provider:
    sampler:
      type: always_on  # always_on|always_off|trace_id_ratio|parent_based|service
      ratio: 1.0       # Sampling ratio (0.0-1.0, only for trace_id_ratio)
      service_id: null # Custom sampler service (only for type: service)
    processor:
      type: void  # composite|memory|batching|passthrough|void|service
      batch_size: 512
      service_id: null
      exporter:
        type: void  # memory|console|void|otlp|service

Sampler types:

Type Description
always_on Sample all traces (default)
always_off Sample no traces
trace_id_ratio Sample based on trace ID ratio
parent_based Respect parent span's sampling decision
service Custom sampler service

MeterProvider

Configures the meter provider for metrics collection.

flow_telemetry:
  meter_provider:
    temporality: cumulative  # cumulative|delta
    processor:
      type: void  # composite|memory|batching|passthrough|void|service
      batch_size: 512
      exporter:
        type: void

LoggerProvider

Configures the logger provider for log export.

flow_telemetry:
  logger_provider:
    processor:
      type: void  # composite|memory|batching|passthrough|void|severity_filtering|service
      batch_size: 512
      exporter:
        type: void

Severity filtering (logs only):

flow_telemetry:
  logger_provider:
    processor:
      type: severity_filtering
      minimum_severity: info  # trace|debug|info|warn|error|fatal
      inner_processor:
        type: batching
        exporter:
          type: otlp
          otlp:
            transport:
              endpoint: 'http://otel-collector:4318/v1/logs'

Processor Configuration

Processor types available for tracer_provider, meter_provider, and logger_provider.

void (default)

Discards all data. No additional options.

processor:
  type: void

passthrough

Immediately exports each item.

processor:
  type: passthrough
  exporter:
    type: console

memory

Stores in memory (for testing). No additional options.

processor:
  type: memory

batching

Batches items before export.

Option Type Default Description
batch_size integer 512 Number of items per batch
processor:
  type: batching
  batch_size: 512
  exporter:
    type: otlp
    otlp:
      transport:
        endpoint: 'http://otel-collector:4318/v1/traces'

composite

Combines multiple processors.

Option Type Description
processors array List of processor configs
processor:
  type: composite
  processors:
    - type: batching
      exporter:
        type: otlp
        otlp:
          transport:
            endpoint: 'http://otel-collector:4318/v1/traces'
    - type: memory

service

Custom processor service.

Option Type Description
service_id string Symfony service ID (required)
processor:
  type: service
  service_id: 'app.custom_processor'

severity_filtering (logger_provider only)

Filters logs by minimum severity level.

Option Type Default Description
minimum_severity string info trace|debug|info|warn|error|fatal
inner_processor object - Nested processor configuration
processor:
  type: severity_filtering
  minimum_severity: info
  inner_processor:
    type: batching
    exporter:
      type: otlp
      otlp:
        transport:
          endpoint: 'http://otel-collector:4318/v1/logs'

Exporter Configuration

Exporter types available for processor configurations.

void (default)

Discards all data. No additional options.

exporter:
  type: void

memory

Stores in memory (for testing). No additional options.

exporter:
  type: memory

console

Outputs to console. No additional options.

exporter:
  type: console

otlp

Exports to OTLP-compatible backends (Jaeger, Tempo, etc.).

Option Type Description
transport object Transport configuration (required)
serializer object Serializer configuration
exporter:
  type: otlp
  otlp:
    transport:
      type: curl
      endpoint: 'http://otel-collector:4318/v1/traces'
    serializer:
      type: json

service

Custom exporter service.

Option Type Description
service_id string Symfony service ID (required)
exporter:
  type: service
  service_id: 'app.custom_exporter'

OTLP Transport Configuration

Transport types for OTLP exporters.

curl (default, recommended)

Option Type Default Description
endpoint string - OTLP endpoint URL (required)
timeout integer 30 Request timeout in seconds
connect_timeout integer 10 Connection timeout
compression boolean false Enable compression
follow_redirects boolean true Follow HTTP redirects
max_redirects integer 3 Maximum redirects to follow
proxy string null Proxy URL
ssl_verify_peer boolean true Verify SSL peer
ssl_verify_host boolean true Verify SSL host
ssl_cert_path string null SSL certificate path
ssl_key_path string null SSL key path
ca_info_path string null CA info path
headers object {} Additional HTTP headers
otlp:
  transport:
    type: curl
    endpoint: 'http://otel-collector:4318/v1/traces'
    timeout: 30
    connect_timeout: 10
    compression: false
    follow_redirects: true
    max_redirects: 3
    proxy: null
    ssl_verify_peer: true
    ssl_verify_host: true
    ssl_cert_path: null
    ssl_key_path: null
    ca_info_path: null
    headers:
      Authorization: 'Bearer token'

http

PSR-18 HTTP transport.

Option Type Default Description
endpoint string - OTLP endpoint URL (required)
timeout integer 30 Request timeout in seconds
http_client_service_id string null PSR-18 client service
request_factory_service_id string null PSR-17 request factory
stream_factory_service_id string null PSR-17 stream factory
otlp:
  transport:
    type: http
    endpoint: 'http://otel-collector:4318/v1/traces'
    timeout: 30
    http_client_service_id: null
    request_factory_service_id: null
    stream_factory_service_id: null

grpc

gRPC transport.

Option Type Default Description
endpoint string - OTLP endpoint URL (required)
timeout integer 30 Request timeout in seconds
insecure boolean false Allow insecure connections
otlp:
  transport:
    type: grpc
    endpoint: 'http://otel-collector:4317'
    timeout: 30
    insecure: true

service

Custom transport service.

Option Type Description
service_id string Symfony service ID (required)
otlp:
  transport:
    type: service
    service_id: 'app.custom_transport'

OTLP Serializer Configuration

Serializer types for OTLP exporters.

json (default)

serializer:
  type: json

protobuf

serializer:
  type: protobuf

service

Custom serializer service.

Option Type Description
service_id string Symfony service ID (required)
serializer:
  type: service
  service_id: 'app.custom_serializer'

Instrumentation

Configure automatic instrumentation for various Symfony components.

All instrumentation is disabled by default. You must explicitly set enabled: true for each component you want to instrument.

HTTP Kernel

Traces HTTP requests and responses.

flow_telemetry:
  instrumentation:
    http_kernel:
      enabled: true
      context_propagation: true  # Extract context from incoming headers
      exclude_paths:
        - path: '/_profiler'
        - path: '/_wdt'
        - path: '/health'
          method: GET
        - path: '/^\/api\/internal\/.*/'  # Regex pattern

Console

Traces console commands.

flow_telemetry:
  instrumentation:
    console:
      enabled: true
      exclude_commands:
        - 'cache:clear'
        - 'assets:install'
        - '/^debug:.*/'  # Regex: exclude all debug commands

Messenger

Traces Symfony Messenger messages with context propagation across message boundaries.

flow_telemetry:
  instrumentation:
    messenger:
      enabled: true
      context_propagation: true  # Propagate context across message boundaries

Twig

Traces Twig template rendering.

flow_telemetry:
  instrumentation:
    twig:
      enabled: true
      trace_templates: true   # Trace template rendering
      trace_blocks: false     # Trace block rendering
      trace_macros: false     # Trace macro execution
      exclude_templates:
        - '@WebProfiler'
        - '/^@Debug\/.*/'

HTTP Client

Traces Symfony HTTP Client requests.

flow_telemetry:
  instrumentation:
    http_client:
      enabled: true
      exclude_clients:
        - 'internal.client'
        - '/^debug\..*/'

PSR-18 Client

Traces PSR-18 HTTP client requests.

flow_telemetry:
  instrumentation:
    psr18_client:
      enabled: true
      exclude_clients:
        - 'app.internal_client'

Doctrine DBAL

Traces database queries.

flow_telemetry:
  instrumentation:
    dbal:
      enabled: true
      log_sql: true           # Include SQL in span attributes
      max_sql_length: 1000    # Max SQL length (0 = no limit)
      exclude_connections:
        - 'legacy'
        - '/^test_.*/'

Cache

Traces Symfony Cache operations.

flow_telemetry:
  instrumentation:
    cache:
      enabled: true
      exclude_pools:
        - 'cache.system'
        - '/^cache\.validator.*/'

Named Instruments

Configure named tracers, meters, and loggers with custom instrumentation scope attributes.

Options:

Option Type Default Description
version string 'unknown' Instrumentation scope version
schema_url string null Schema URL for semantic conventions
attributes object {} Additional scope attributes
flow_telemetry:
  tracers:
    my_tracer:
      version: '1.0.0'  # default: 'unknown'
      schema_url: 'https://opentelemetry.io/schemas/1.21.0'
      attributes:
        custom.attribute: 'value'

  meters:
    my_meter:
      version: '1.0.0'  # default: 'unknown'
      schema_url: null
      attributes: { }

  loggers:
    my_logger:
      version: '1.0.0'  # default: 'unknown'

Pattern Matching

Several configuration options support pattern matching for exclusion lists (paths, commands, templates, etc.).

Exact String Matching

Patterns without regex delimiters match exactly:

exclude_paths:
  - path: '/_profiler'    # Matches exactly /_profiler
  - path: '/health'       # Matches exactly /health

Regex Matching

Patterns enclosed in / delimiters are treated as regular expressions:

exclude_paths:
  - path: '/^\/api\/internal\/.*/'  # Regex: matches /api/internal/*
exclude_commands:
  - '/^debug:.*/'                   # Regex: matches debug:* commands
exclude_templates:
  - '/^@Debug\/.*/'                 # Regex: matches @Debug/* templates

Usage

Accessing Telemetry in Services

Inject the Telemetry service to create custom spans, metrics, and logs:

<?php

namespace App\Service;

use Flow\Telemetry\Telemetry;

final class OrderService
{
    public function __construct(
        private readonly Telemetry $telemetry,
    ) {
    }

    public function processOrder(int $orderId): void
    {
        $tracer = $this->telemetry->tracer('order-service');

        $tracer->trace('process_order', function () use ($orderId) {
            // Your order processing logic
        }, [
            'order.id' => $orderId,
        ]);
    }
}

Creating Custom Spans in Controllers

<?php

namespace App\Controller;

use Flow\Telemetry\Telemetry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

final class CheckoutController extends AbstractController
{
    public function __construct(
        private readonly Telemetry $telemetry,
    ) {
    }

    #[Route('/checkout', name: 'checkout')]
    public function checkout(): Response
    {
        $tracer = $this->telemetry->tracer('checkout');

        return $tracer->trace('checkout_page', function () {
            // Nested span for cart validation
            return $this->telemetry->tracer('checkout')->trace(
                'validate_cart',
                fn () => $this->render('checkout/index.html.twig')
            );
        });
    }
}

Recording Metrics

<?php

$meter = $this->telemetry->meter('business-metrics');

// Counter
$meter->counter('orders_processed')
    ->add(1, ['status' => 'completed']);

// Histogram
$meter->histogram('order_value')
    ->record(99.99, ['currency' => 'USD']);

// Gauge
$meter->gauge('active_users')
    ->record(42);

Logging with Telemetry

<?php

$logger = $this->telemetry->logger('app');

$logger->info('Order processed', [
    'order_id' => 12345,
    'amount' => 99.99,
]);

Complete Production Example

# config/packages/flow_telemetry.yaml
flow_telemetry:
  resource:
    custom:
      service.name: 'my-app'
      service.version: '%env(APP_VERSION)%'

  propagator:
    type: w3c

  tracer_provider:
    sampler:
      type: trace_id_ratio
      ratio: 0.1  # Sample 10% of traces in production
    processor:
      type: batching
      batch_size: 512
      exporter:
        type: otlp
        otlp:
          transport:
            type: curl
            endpoint: '%env(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)%'
            timeout: 30
            headers:
              Authorization: 'Bearer %env(OTEL_AUTH_TOKEN)%'

  meter_provider:
    temporality: cumulative
    processor:
      type: batching
      exporter:
        type: otlp
        otlp:
          transport:
            endpoint: '%env(OTEL_EXPORTER_OTLP_METRICS_ENDPOINT)%'

  logger_provider:
    processor:
      type: severity_filtering
      minimum_severity: info
      inner_processor:
        type: batching
        exporter:
          type: otlp
          otlp:
            transport:
              endpoint: '%env(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT)%'

  instrumentation:
    http_kernel:
      enabled: true
      exclude_paths:
        - path: '/_profiler'
        - path: '/_wdt'
        - path: '/health'
          method: GET
    console:
      enabled: true
      exclude_commands:
        - 'cache:clear'
        - 'cache:warmup'
        - '/^debug:.*/'
    messenger:
      enabled: true
      context_propagation: true
    dbal:
      enabled: true
      log_sql: true
      max_sql_length: 500
    cache:
      enabled: true
      exclude_pools:
        - 'cache.system'

Contributors

Join us on GitHub external resource
scroll back to top