perfbase/slim

Slim integration for the Perfbase profiling tool.

Maintainers

Package info

github.com/perfbaseorg/slim

pkg:composer/perfbase/slim

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-04-08 09:57 UTC

This package is auto-updated.

Last update: 2026-04-08 10:10:08 UTC


README

Perfbase

Perfbase for Slim

Slim framework integration for Perfbase.

Packagist Version License CI PHP Version Slim Version

perfbase/slim is the Slim framework adapter for Perfbase. It is a thin package on top of perfbase/php-sdk that adds:

  • HTTP request profiling for Slim 3
  • HTTP request profiling for Slim 4
  • Manual CLI profiling for non-HTTP entrypoints
  • Per-context include and exclude filters for http and cli
  • Low-cardinality span naming based on route patterns when available
  • Fail-open behavior so profiling issues do not break the host application

Requirements

  • PHP >=7.4 <8.6
  • perfbase/php-sdk ^1.0
  • slim/slim ^3.0 || ^4.0
  • The native Perfbase PHP extension

Installation

Install the package:

composer require perfbase/slim:^1.0

Install the Perfbase PHP extension if it is not already available:

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

What This Package Does

This package does not replace Slim’s container, router, or error handling. It adds middleware and a small CLI helper that profile work with the Perfbase SDK.

Supported public entrypoints:

  • Perfbase\Slim\Slim3\PerfbaseMiddleware
  • Perfbase\Slim\Slim4\PerfbaseMiddleware
  • Perfbase\Slim\Cli\CliTraceRunner

v1 is intentionally scoped to HTTP requests and manual CLI profiling. It does not include queue, worker, or async runtime integrations.

Quick Start

Slim 4

use Perfbase\Slim\Slim4\PerfbaseMiddleware;

$config = [
    'enabled' => true,
    'api_key' => getenv('PERFBASE_API_KEY'),
    'environment' => 'production',
    'app_version' => '1.0.0',
];

$app->add(new PerfbaseMiddleware($config));

Slim 3

use Perfbase\Slim\Slim3\PerfbaseMiddleware;

$config = [
    'enabled' => true,
    'api_key' => getenv('PERFBASE_API_KEY'),
    'environment' => 'production',
    'app_version' => '1.0.0',
];

$app->add(new PerfbaseMiddleware($config));

CLI

use Perfbase\Slim\Cli\CliTraceRunner;

$config = [
    'enabled' => true,
    'api_key' => getenv('PERFBASE_API_KEY'),
    'environment' => 'production',
    'app_version' => '1.0.0',
];

$runner = new CliTraceRunner($config);

$exitCode = $runner->profile('cache:warm', function (): int {
    return 0;
});

Configuration

You can pass either:

  • a plain PHP array
  • a normalized Perfbase\Slim\Support\PerfbaseConfig instance

Example:

use Perfbase\SDK\FeatureFlags;

$config = [
    'enabled' => true,
    'debug' => false,
    'log_errors' => true,
    'api_key' => getenv('PERFBASE_API_KEY'),
    'api_url' => 'https://ingress.perfbase.cloud',
    'sample_rate' => 0.1,
    'timeout' => 10,
    'proxy' => null,
    'flags' => FeatureFlags::DefaultFlags,
    'environment' => 'production',
    'app_version' => '1.0.0',
    'include' => [
        'http' => ['*'],
        'cli' => ['*'],
    ],
    'exclude' => [
        'http' => [],
        'cli' => [],
    ],
    'user_id_resolver' => function ($request): ?string {
        $user = $request->getAttribute('user');

        if (is_object($user) && method_exists($user, 'getId')) {
            return (string) $user->getId();
        }

        return null;
    },
];

Config Reference

Key Type Default Notes
enabled bool false Must be true and paired with a non-empty api_key to profile
debug bool false Rethrows internal profiling errors instead of failing open
log_errors bool true Logs profiling errors with error_log() when not in debug mode
api_key string '' Required when profiling is enabled
api_url string https://ingress.perfbase.cloud Receiver base URL
sample_rate float 0.1 Between 0.0 and 1.0
timeout int 10 Request timeout in seconds
proxy `string null` null
flags int FeatureFlags::DefaultFlags SDK feature flags passed to the extension
environment string production Added to each trace
app_version string '' Added to each trace
include.http string[] ['*'] HTTP allowlist patterns
exclude.http string[] [] HTTP denylist patterns
include.cli string[] ['*'] CLI allowlist patterns
exclude.cli string[] [] CLI denylist patterns
user_id_resolver `callable null` null

Validation rules:

  • api_url must be a valid URL
  • sample_rate must be between 0.0 and 1.0
  • timeout must be at least 1
  • flags must be a non-negative integer
  • user_id_resolver must be callable or null

HTTP Profiling

Both middleware implementations share the same lifecycle behavior:

  • profiling starts before the downstream handler runs
  • response status is captured on success
  • exception messages are captured on failure
  • cleanup and trace submission happen in finally

Recorded HTTP attributes include:

  • source=http
  • action
  • environment
  • app_version
  • hostname
  • php_version
  • http_method
  • http_url
  • http_status_code
  • user_ip
  • user_agent
  • user_id when user_id_resolver returns one

Span Naming

HTTP span naming is intentionally low-cardinality:

  • preferred: METHOD /route/{pattern}
  • fallback: METHOD /raw/path

Examples:

  • http.GET./articles/{id}
  • http.POST./sessions
  • http.GET./health

The action attribute follows the same rule without the http. prefix:

  • GET /articles/{id}
  • POST /sessions

URL Handling

http_url keeps the scheme, authority, and path, but strips the query string.

Example:

  • request URL: https://example.com/articles/42?token=secret
  • recorded http_url: https://example.com/articles/42

This is intentional so tokens and other sensitive query parameters are not emitted in traces.

User Metadata

The middleware resolves:

  • user_ip from CF-Connecting-IP, then X-Forwarded-For, then REMOTE_ADDR
  • user_agent from the PSR-7 request headers, with server param fallback
  • user_id only when you provide user_id_resolver

If user_id_resolver returns:

  • a scalar value, it is cast to string
  • a stringable object, it is cast to string
  • null, no user_id attribute is set

Filters

Filters are evaluated separately for http and cli.

Rules:

  • profiling only runs when at least one include pattern matches
  • any exclude match blocks profiling
  • exclude patterns take precedence over include patterns

Supported pattern styles:

  • match all: * or .*
  • regex: /^GET \\/admin/
  • glob: GET /admin/*

HTTP Filter Components

HTTP filters are matched against these normalized components:

  • METHOD /path
  • /path
  • route pattern, when available
  • METHOD /route-pattern, when available
  • route name, when available

Examples:

'include' => [
    'http' => [
        '*',
        'GET /health',
        'GET /articles/{id}',
        'articles.show',
        '/^POST \\/admin\\//',
    ],
],
'exclude' => [
    'http' => [
        'GET /internal/*',
    ],
],

CLI Filter Components

CLI filters are matched against:

  • the raw command name
  • the normalized action form cli.{command}

Examples:

'include' => [
    'cli' => [
        'cache:*',
        '/^queue:(work|listen)$/',
    ],
],
'exclude' => [
    'cli' => [
        'queue:listen',
    ],
],

Middleware Order

Route-pattern naming depends on route metadata already being attached to the request when Perfbase runs.

If route metadata is available, the middleware uses the route pattern and route name for naming and filtering. If it is not available yet, the middleware falls back to the raw request path.

Operationally, that means:

  • if you want route-pattern naming, register Perfbase in an order where routing has already populated request attributes
  • if you cannot guarantee that, profiling still works, but naming falls back to the path

Slim 4 Setup Example

use Perfbase\Slim\Slim4\PerfbaseMiddleware;
use Slim\Factory\AppFactory;

$app = AppFactory::create();

$config = [
    'enabled' => true,
    'api_key' => getenv('PERFBASE_API_KEY'),
    'environment' => 'production',
    'app_version' => '1.0.0',
    'sample_rate' => 0.2,
];

$app->add(new PerfbaseMiddleware($config));

$app->get('/health', function ($request, $response) {
    $response->getBody()->write('ok');
    return $response;
});

Slim 3 Setup Example

use Perfbase\Slim\Slim3\PerfbaseMiddleware;
use Slim\App;

$app = new App();

$config = [
    'enabled' => true,
    'api_key' => getenv('PERFBASE_API_KEY'),
    'environment' => 'production',
    'app_version' => '1.0.0',
    'sample_rate' => 0.2,
];

$app->add(new PerfbaseMiddleware($config));

$app->get('/health', function ($request, $response) {
    return $response->write('ok');
});

CLI Usage

CliTraceRunner is intended for application-owned scripts and commands. It does not integrate with a specific console framework in v1.

Example with extra attributes:

use Perfbase\Slim\Cli\CliTraceRunner;

$runner = new CliTraceRunner([
    'enabled' => true,
    'api_key' => getenv('PERFBASE_API_KEY'),
    'environment' => 'production',
    'app_version' => '1.0.0',
]);

$exitCode = $runner->profile(
    'cache:warm',
    function (): int {
        return 0;
    },
    [
        'cache_store' => 'redis',
        'trigger' => 'deploy',
    ]
);

CLI behavior:

  • source=cli
  • action=cli.{command}
  • integer callback returns are recorded as exit_code
  • thrown exceptions are recorded as exception and rethrown
  • cleanup still happens in finally

Runtime Behavior

The package is designed to fail open in production.

When debug=false:

  • SDK initialization errors are swallowed
  • profiling submission failures do not break the request
  • middleware and CLI callbacks continue to run normally

When debug=true:

  • internal profiling errors are rethrown so integration issues are obvious during development

Production Notes

  • Keep sample_rate below 1.0 unless you explicitly want full capture.
  • Use route-pattern filters instead of raw-path filters where possible to keep rules stable.
  • Do not rely on query strings for naming or filtering; they are intentionally excluded.
  • Provide user_id_resolver only if your application already has a stable notion of user identity.
  • If you use reverse proxies or CDNs, ensure client IP headers are trustworthy in your environment before relying on user_ip.

Troubleshooting

No traces being sent:

  • confirm enabled is true
  • confirm api_key is present and non-empty
  • confirm the native Perfbase extension is installed and loaded
  • confirm your include and exclude filters allow the current request or command
  • confirm sample_rate is not 0

Unexpected path-based names instead of route patterns:

  • adjust middleware order so route metadata is available before Perfbase executes

Unexpected missing user_id:

  • confirm user_id_resolver returns a scalar or stringable object
  • confirm it does not throw

Development

composer install
composer run test
composer run phpstan
composer run lint

Documentation

Full documentation is available at perfbase.com/docs.

License

Apache-2.0. See LICENSE.txt.