Skip to main content
Integrations

Symfony Integration

The Perfbase Symfony bundle provides automatic profiling for main HTTP requests via kernel events and console commands via Symfony Console events. Supports Symfony 5.4, 6.x, and 7.x on PHP 7.4 through 8.5.

Installation

Install the Perfbase PHP extension first. This is what does the actual profiling:

bash -c "$(curl -fsSL https://cdn.perfbase.com/install.sh)"

Then install the Symfony bundle:

composer require perfbase/symfony

If your application consumes a published Symfony Flex recipe for Perfbase, the bundle and starter config can be registered for you. The package repository includes recipe source, but apps should register the bundle manually unless their Flex setup already has a published Perfbase recipe available.

// config/bundles.php
return [
    // ...
    Perfbase\Symfony\PerfbaseBundle::class => ['all' => true],
];

Configuration

Create a starter config with your API key and enable profiling:

# config/packages/perfbase.yaml
perfbase:
    enabled: true
    api_key: '%env(PERFBASE_API_KEY)%'
    sample_rate: 0.1
    app_version: '%env(default::PERFBASE_APP_VERSION)%'

Add the environment values:

PERFBASE_API_KEY=your-project-api-key
PERFBASE_APP_VERSION=1.0.0

All options

KeyTypeDefaultDescription
enabledboolfalseMaster on/off switch. When true, api_key is required.
api_keystring''Your project API key. Required when enabled.
api_urlstringhttps://ingress.perfbase.cloudIngestion endpoint. Must be a valid URL.
sample_ratefloat0.1Fraction of requests to profile (0.0–1.0). 0.1 = 10%.
profile_http_status_codesint[]200..299, 500..599HTTP response status codes that should be submitted.
timeoutint10HTTP timeout in seconds for trace submission.
proxystring|nullnullOptional proxy URL (http, https, socks5, socks5h).
flagsintDefaultFlagsSDK feature flags bitmask. See Feature flags.
app_versionstring''Your application version, recorded on every trace.
debugboolfalseWhen true, profiling errors are thrown instead of silently logged.
log_errorsbooltrueLog profiling errors via error_log().
include.httpstring[]['*']HTTP allow-list filters.
exclude.httpstring[][]HTTP deny-list filters.
include.consolestring[]['*']Console allow-list filters.
exclude.consolestring[][]Console deny-list filters.

Include and exclude filters

Control which routes and commands are profiled:

perfbase:
    include:
        http: ['*']               # All routes (default)
        console: ['*']            # All commands (default)
    exclude:
        http: ['/health', '/_profiler/*']
        console: ['cache:clear']

Pattern types

  • Glob patterns: api/*, /admin/users/* (matched via fnmatch())
  • Regex patterns: /^GET \/api\// (delimited by forward slashes)
  • Catch-all: * or .* matches everything

What’s matched against HTTP filters

Patterns are tested against multiple representations of the request, so you can filter by any of:

  • Request path: /api/users/42
  • Method + path: GET /api/users/42
  • Route template: /api/users/{id}
  • Method + route template: GET /api/users/{id}
  • Route name: app_user_show
  • Controller: App\Controller\UserController::show

HTTP profiling

HTTP requests are profiled automatically via a kernel event subscriber, with no middleware to register. The subscriber hooks into four kernel events:

  1. kernel.request: creates a profiling lifecycle and starts the trace span.
  2. kernel.response: records the HTTP status code.
  3. kernel.exception: records the exception message, and the status code for HTTP exceptions.
  4. kernel.terminate: stops the span and submits the trace. Runs after the response is sent, so submission never delays the response.

Sub-requests are automatically skipped. Only the main request is profiled.

Each request uses the stable span name http. The route template is recorded in the action attribute when available (e.g., GET /api/users/{id} rather than GET /api/users/42).

Automatic attributes

AttributeSource
hostnamegethostname()
environmentkernel.environment
app_versionConfig value
php_versionPHP version
sourcehttp
actione.g., GET /api/users/{id}
http_methodRequest method
http_urlScheme + host + path (no query string)
http_status_codeResponse status code
user_ipClient IP address
user_agentUser agent string
user_idFrom Security token storage, if available

Console command profiling

Symfony console commands are profiled automatically via console event listeners. The subscriber handles ConsoleEvents::COMMAND, ConsoleEvents::ERROR, and ConsoleEvents::TERMINATE.

Each command uses the stable span name cli. The command name is recorded in the action attribute, and the exit code and any exceptions are recorded as attributes.

Use the exclude filter to skip noisy or long-running commands:

perfbase:
    exclude:
        console: ['messenger:consume', 'cache:*', 'server:*']

Messenger profiling

Symfony Messenger worker profiling is not yet supported. Individual messages dispatched during an HTTP request or console command are captured as part of that request’s trace.

Sample rate

The sample rate controls what fraction of HTTP requests and console commands are profiled:

perfbase:
    sample_rate: 1.0    # Profile everything (development)
    sample_rate: 0.1    # 10% of requests (production)
    sample_rate: 0.01   # 1% of requests (high-traffic)

When a unit of work is not sampled, no extension trace span is started.

Error handling

Profiling never crashes your application. The bundle uses a fail-open error handling strategy:

  • debug: true: profiling errors are thrown as exceptions. Use this during development to catch configuration issues.
  • debug: false (default): errors are caught silently. If log_errors: true (default), they are logged via error_log().

Every event handler is wrapped in try/catch, so a profiling bug can never disrupt your application.

Using the SDK directly

For manual profiling beyond what the automatic subscribers capture, inject the client provider and request the SDK client:

use Perfbase\Symfony\Support\PerfbaseClientProvider;

class ImportService
{
    public function __construct(private PerfbaseClientProvider $perfbase) {}

    public function run(): void
    {
        $client = $this->perfbase->getClient();
        if (!$client) {
            return;
        }

        $client->startTraceSpan('import_products');
        // ... do work ...
        $client->stopTraceSpan('import_products');
        $client->submitTrace();
    }
}

See the PHP SDK docs for the full API reference.