Symfony integration for Perfbase.
perfbase/symfony is the official Symfony bundle for Perfbase.
It integrates Symfony request and console lifecycles with the Perfbase PHP SDK and native extension so traces are captured and submitted with minimal application code.
Current production scope:
- HTTP request profiling
- Console command profiling
- Configurable sampling
- Include and exclude filters for HTTP and console contexts
- Fail-open runtime behavior when profiling cannot start safely
Out of scope in the current release:
- Messenger worker profiling
- Scheduler-specific instrumentation beyond normal console commands
- Symfony Web Profiler toolbar integration
- an auto-published Symfony Flex recipe
- PHP
7.4to8.4 - Symfony
5.4to7.x perfbase/php-sdk^1.0- The Perfbase native PHP extension installed and enabled
Install the bundle:
composer require perfbase/symfonyInstall the Perfbase PHP extension if it is not already available:
bash -c "$(curl -fsSL https://cdn.perfbase.com/install.sh)"Restart PHP-FPM, Apache, RoadRunner, Swoole, or any other long-lived PHP runtime after installing the extension.
If your application uses Symfony Flex and a published Perfbase recipe is available in your environment, bundle registration can be automated.
If not, register the bundle manually in config/bundles.php:
<?php
return [
// ...
Perfbase\Symfony\PerfbaseBundle::class => ['all' => true],
];Then add config/packages/perfbase.yaml:
perfbase:
enabled: true
api_key: '%env(PERFBASE_API_KEY)%'
sample_rate: 0.1
app_version: '%env(default::PERFBASE_APP_VERSION)%'Recommended environment variables:
PERFBASE_API_KEY=your_api_key_here
PERFBASE_APP_VERSION=1.0.0The bundle exposes configuration under perfbase:.
perfbase:
enabled: false
debug: false
log_errors: true
api_key: ''
api_url: 'https://ingress.perfbase.cloud'
sample_rate: 0.1
timeout: 10
proxy: null
flags: !php/const Perfbase\SDK\FeatureFlags::DefaultFlags
app_version: ''
include:
http: ['*']
console: ['*']
exclude:
http: []
console: []| Key | Type | Default | Purpose |
|---|---|---|---|
enabled |
bool |
false |
Enables or disables profiling globally |
debug |
bool |
false |
Re-throws profiling errors instead of failing open |
log_errors |
bool |
true |
Logs profiling errors when debug=false |
api_key |
string |
'' |
Perfbase project API key |
api_url |
string |
https://ingress.perfbase.cloud |
Receiver base URL |
sample_rate |
float |
0.1 |
Sampling rate from 0.0 to 1.0 |
timeout |
int |
10 |
SDK submission timeout in seconds |
proxy |
`string | null` | null |
flags |
int |
FeatureFlags::DefaultFlags |
Perfbase extension feature flags |
app_version |
string |
'' |
Version string attached to traces |
include.http |
string[] |
['*'] |
HTTP allow-list filters |
exclude.http |
string[] |
[] |
HTTP deny-list filters |
include.console |
string[] |
['*'] |
Console allow-list filters |
exclude.console |
string[] |
[] |
Console deny-list filters |
Invalid configuration fails during Symfony config processing.
The bundle validates:
enabled: truerequires a non-emptyapi_keyapi_urlmust be a valid URLproxymust benullor a valid URLsample_ratemust be between0.0and1.0timeoutmust be at least1flagsmust be non-negative- filter entries cannot be empty strings
environmentis derived from Symfonykernel.environmentapp_versionis configured explicitly underperfbase.app_version
Symfony does not define a single application-version convention, so the bundle does not infer one automatically.
perfbase:
enabled: true
debug: false
log_errors: true
api_key: '%env(PERFBASE_API_KEY)%'
api_url: 'https://ingress.perfbase.cloud'
sample_rate: 0.2
timeout: 10
flags: !php/const Perfbase\SDK\FeatureFlags::DefaultFlags
app_version: '%env(default::PERFBASE_APP_VERSION)%'
include:
http:
- 'GET /api/*'
- 'POST /checkout'
console:
- 'app:*'
exclude:
http:
- 'GET /health'
- '/^GET \\/_profiler/'
console:
- 'cache:clear'The bundle profiles main HTTP requests through:
kernel.requestkernel.responsekernel.exceptionkernel.terminate
Behavior:
- main requests only
- route templates are preferred for stable naming
- response status codes are attached when available
- exception messages are attached on exception paths
- trace submission happens during terminate
HTTP attributes include:
source=httpactionhttp_methodhttp_urlhttp_status_codeuser_ipuser_agentuser_idwhen a Symfony security token exposes oneenvironmentapp_versionhostnamephp_version
The bundle profiles console commands through:
console.commandconsole.errorconsole.terminate
Console attributes include:
source=consoleactionexit_codeexceptionenvironmentapp_versionhostnamephp_version
Span names and action values are intentionally low-cardinality.
HTTP naming preference:
- Route path template such as
GET /articles/{id} - Route name
- Raw request path
Example HTTP span:
http.GET./articles/{id}
Example console span:
console.cache:clear
The bundle excludes query strings from http_url.
Example:
https://example.com/articles/42?token=secret
becomes:
https://example.com/articles/42
This is intentional. It avoids leaking signed URLs, nonces, tokens, and other high-cardinality values into trace metadata.
The bundle supports include and exclude filters for both HTTP and console profiling.
Supported pattern styles:
*or.*to match everything- glob patterns such as
admin/*orapp:* - regex patterns such as
/^GET \/health$/
HTTP matching evaluates these inputs when available:
- route path template
- route name
- request path
METHOD path- controller string
Example:
perfbase:
include:
http:
- 'GET /api/*'
- 'app_api_*'
console:
- 'app:*'
exclude:
http:
- 'GET /health'
- '/^GET \\/_profiler/'
console:
- 'cache:clear'The bundle is designed to fail open.
- In normal production mode, profiling failures do not break requests or commands
- If
log_errors=true, failures are logged - If
debug=true, profiling exceptions are re-thrown
This behavior is implemented by PerfbaseErrorHandler.php
and the lazy client boot path in PerfbaseClientProvider.php.
This package is intentionally thin.
- It does not implement its own transport
- It does not implement local buffering or retries
- It does not build trace payloads itself
- It delegates extension access and submission to
perfbase/php-sdk
Primary runtime pieces:
src/PerfbaseBundle.phpsrc/DependencyInjection/Configuration.phpsrc/DependencyInjection/PerfbaseExtension.phpsrc/Profiling/AbstractProfiler.phpsrc/Lifecycle/HttpRequestLifecycle.phpsrc/Lifecycle/ConsoleCommandLifecycle.phpsrc/EventSubscriber/HttpProfilerSubscriber.phpsrc/EventSubscriber/ConsoleProfilerSubscriber.phpsrc/Support/FilterMatcher.phpsrc/Support/SpanNaming.phpsrc/Support/PerfbaseClientProvider.php
This release does not currently provide:
- Messenger worker instrumentation
- profiling for Symfony subrequests
- request body or response body capture
- local buffering or offline delivery modes
- Symfony Web Profiler toolbar integration
If Messenger support is added later, it should be implemented as a separate lifecycle and subscriber path.
Verification commands:
composer run test
composer run phpstan
composer run lint
php fixture-app/smoke.phpThe package includes:
- unit tests for config, helpers, lifecycles, and error handling
- integration tests for HTTP and console event flows
- an install-level fixture app under
fixture-app/ - GitHub Actions CI for:
- PHP
7.4+ Symfony5.4 - PHP
8.2+ Symfony6.4 - PHP
8.4+ Symfony7.x - fixture-app smoke verification
- PHP
Current coverage:
- methods:
80.00% - lines:
95.27%
The repository includes a recipe source under recipe/ and bundle
metadata in composer.json.
That recipe is not consumed automatically from this repository. Symfony Flex will use it only after it has been published to the Symfony recipes ecosystem or another configured recipe source.
This repository is shaped as a normal publishable library:
perfbase/php-sdkis resolved from Packagistcomposer.lockis not committed- there are no monorepo-only path repositories in the package manifest
Local development:
composer install
composer run test
composer run phpstan
php fixture-app/smoke.phpFull documentation is available at perfbase.com/docs.
- Docs: perfbase.com/docs
- Issues: github.com/perfbaseorg/symfony/issues
- Support: support@perfbase.com
Apache-2.0. See LICENSE.txt.