Documentation menu
Drupal Integration
The Perfbase Drupal module provides automatic profiling for HTTP requests, Drush commands, cron runs, and queue workers. Supports Drupal 10.3+ and 11.x on PHP 8.1 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 Drupal module:
composer require perfbase/drupalEnable the module:
drush en perfbaseConfiguration
Configure via the admin UI at Configuration > Development > Perfbase, or override in settings.php for environment-specific values:
// settings.php
$settings['perfbase'] = [
'enabled' => TRUE,
'api_key' => 'your-api-key',
'sample_rate' => 0.1,
'environment' => 'production',
'app_version' => '2026.04.08',
];Configuration is resolved in three layers (later wins): module defaults → admin UI settings → settings.php overrides. The settings.php layer takes priority over the admin form, which is useful for keeping API keys out of config exports.
All options
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Master on/off switch. Requires api_key to be set. |
api_key | string | '' | Your project API key. Required. |
api_url | string | https://ingress.perfbase.cloud | Ingestion endpoint. |
sample_rate | float | 0.1 | Fraction of eligible requests, commands, cron runs, and queue items to profile (0.0–1.0). 0.1 = 10%. |
profile_http_status_codes | int[] | 200..299, 500..599 | HTTP response status codes that should be submitted. |
timeout | int | 10 | HTTP timeout in seconds for trace submission. |
proxy | string | '' | Optional proxy URL (http, https, socks5, socks5h). |
flags | int | 8145 (DefaultFlags) | SDK feature flags bitmask. See Feature flags. |
environment | string | '' | Environment label recorded on traces. |
app_version | string | '' | Your application version, recorded on traces. |
debug | bool | false | When true, profiling errors are thrown instead of silently logged. |
log_errors | bool | true | Log profiling errors via error_log(). |
exclude_admin_routes | bool | true | Skip Drupal admin routes by default. |
Context toggles
| Setting | Default | Description |
|---|---|---|
profile_http | On | Profile page requests. Admin routes are skipped by default unless exclude_admin_routes is disabled. |
profile_console | Off | Profile Drush and console commands. |
profile_cron | On | Profile Drupal cron runs. |
profile_queue | On | Profile queue worker item processing. |
Include and exclude filters
Control what gets profiled per context with include/exclude patterns, configured in the admin UI (one pattern per line):
// settings.php example
$settings['perfbase'] = [
'include' => [
'http' => ['*'], // All routes (default)
'console' => ['*'],
'cron' => ['*'],
'queue' => ['*'],
],
'exclude' => [
'http' => ['/admin/reports/*'],
'console' => ['cache:*'],
],
];Pattern types
- Glob patterns:
/admin/*,/node/*(shell-style matching) - Regex patterns:
/^GET \/api\//(wrapped in forward slashes) - Catch-all:
*or.*matches everything
HTTP patterns are tested against multiple representations of the request: {METHOD} {path}, the raw path, normalized path (with {id} and {uuid} placeholders), route name, and {METHOD} {route_name}.
HTTP profiling
HTTP requests are profiled automatically via a kernel event subscriber. The subscriber hooks into four Symfony kernel events:
kernel.request(priority 1000): creates a profiling lifecycle and starts the trace span.kernel.response(priority -1000): records the HTTP status code.kernel.exception(priority -1000): records the exception message.kernel.terminate(priority -1000): stops the span and submits the trace. Runs after the response is sent.
Sub-requests are automatically skipped. Only the main request is profiled.
Each request uses the stable span name http. The route path template is recorded in the action attribute when available (e.g., GET /node/{node} rather than GET /node/42). Numeric path segments are normalized to {id} and UUIDs to {uuid} for low-cardinality grouping.
Automatic attributes
| Attribute | Source |
|---|---|
hostname | gethostname() |
php_version | PHP version |
environment | Config value |
app_version | Config value |
source | http |
action | e.g., GET /node/{node} |
http_method | Request method |
http_url | Scheme + host + path (no query string) |
http_status_code | Response status code |
user_ip | Client IP address |
user_agent | User agent string |
user_id | Drupal user ID (from request account) |
drupal.route_name | Drupal route name (e.g., entity.node.canonical) |
Drush and console command profiling
Console commands are profiled via Symfony console event listeners when profile_console is enabled (off by default).
Each command uses the stable span name artisan. The command name is recorded in the action attribute, and the exit code and any exceptions are recorded as attributes.
Enable in the admin UI or via settings.php:
$settings['perfbase'] = [
'profile_console' => TRUE,
];Cron profiling
Drupal cron runs are profiled automatically via a service decorator that wraps the core cron service. Each cron execution uses the stable span name cron. Enabled by default.
Queue worker profiling
Queue item processing is profiled by wrapping every queue worker via a custom QueueWorkerManager. Each item processed uses the stable span name queue, with the worker plugin ID recorded in attributes. Enabled by default.
The module decorates the core plugin.manager.queue_worker service, so all queue workers, including contrib module workers, are automatically profiled without any code changes.
Sample rate
The sample rate controls what fraction of eligible HTTP requests, console commands, cron runs, and queue items are profiled:
$settings['perfbase'] = [
'sample_rate' => 1.0, // Profile everything (development)
'sample_rate' => 0.1, // 10% of eligible work (production)
'sample_rate' => 0.01, // 1% of requests (high-traffic)
];The sample rate is checked per request, per command, per cron run, and per queue item independently. When a unit of work isn’t sampled, no extension trace span is started.
Error handling
Profiling never crashes your site. In production (debug: false), all profiling errors are caught and optionally logged via error_log(). In development (debug: true), errors are thrown so you can catch configuration issues early.
If the Perfbase PHP extension is not installed, the module detects this gracefully and silently disables profiling.
Using the SDK directly
Access the SDK via the perfbase.factory service for manual profiling:
/** @var \Perfbase\SDK\Perfbase|null $perfbase */
$perfbase = \Drupal::service('perfbase.factory')->getClient();
if ($perfbase) {
$perfbase->setAttribute('entity_type', $entity->getEntityTypeId());
}See the PHP SDK docs for the full API reference.
Admin settings page
The settings form at Configuration > Development > Perfbase provides:
- API key and profiling toggle
- Sample rate, timeout, and proxy configuration
- Feature flags bitmask
- Context toggles (HTTP, console, cron, queue)
- Include/exclude filter textareas per context
- HTTP status-code allowlist and admin-route exclusion controls
- Environment and app version labels
Requires the administer site configuration permission.
Current scope
The Drupal module does not include dedicated Messenger worker support, Batch API support, install/update hook instrumentation, or Drupal-specific render/entity/cache enrichment beyond what the native PHP extension captures.