Skip to Content
Why Treblle
Platform
Trust & Compliance
Pricing
Resources
Company

Treblle Docs

Treblle with PHP

Requirements

DependencyVersion
PHP^8.2
ext-curlany
ext-jsonany
ext-mbstringany
ext-zlibany

Installation

composer require treblle/treblle-php

Setup

Add one line at the top of your entry point (e.g. index.php) before any output:

<?php require_once __DIR__ . '/vendor/autoload.php'; use Treblle\Php\Treblle; Treblle::create( sdkToken: 'your-sdk-token-from-treblle-dashboard', apiKey: 'your-api-key-from-treblle-dashboard', ); // Your application code continues here...

Both credentials are available in your Treblle Dashboard .

That’s it. Treblle will automatically capture request and response data and ship it to the ingress asynchronously after your response has been sent.

Configuration

Pass options as the third argument to Treblle::create():

use Treblle\Php\Treblle; Treblle::create( sdkToken: $_ENV['TREBLLE_SDK_TOKEN'], apiKey: $_ENV['TREBLLE_API_KEY'], options: [ 'debug' => false, 'enabled' => true, 'masked_keywords' => [ 'password', 'pwd', 'secret', 'password_confirmation', 'passwordConfirmation', 'cc', 'card_number', 'cardNumber', 'ccv', 'ssn', 'credit_score', 'creditScore', ], 'excluded_paths' => [], 'custom_ingress' => null, ], );

Or build a config object directly for more control:

use Treblle\Php\Config\TreblleConfig; use Treblle\Php\Treblle; $config = new TreblleConfig( sdkToken: $_ENV['TREBLLE_SDK_TOKEN'], apiKey: $_ENV['TREBLLE_API_KEY'], debug: false, maskedKeywords: TreblleConfig::DEFAULT_MASKED_KEYWORDS, excludedPaths: [], customIngress: null, enabled: true, ); Treblle::start($config);

enabled

Controls whether Treblle is active. Defaults to true. Set to false to disable the SDK in specific environments without removing your credentials.

Treblle::create( sdkToken: $_ENV['TREBLLE_SDK_TOKEN'], apiKey: $_ENV['TREBLLE_API_KEY'], options: [ 'enabled' => $_ENV['APP_ENV'] === 'production', ], );

debug

When true, the SDK writes diagnostic messages to the PHP error log prefixed with [TREBLLE]. All messages are suppressed by default.

Useful for:

  • Verifying your credentials are correct
  • Seeing which requests are skipped and why
  • Diagnosing ingress connectivity issues
'debug' => true,

Example debug output:

[TREBLLE] Async: using fastcgi_finish_request [TREBLLE] Request excluded by path: /health [TREBLLE] Received 4xx from Treblle ingress: 422 [TREBLLE] curl error: Could not resolve host

masked_keywords

Field names to mask in request bodies, response bodies, request headers, and response headers. Masking replaces every character of the value with *, preserving the original length, and is applied recursively to nested objects and arrays.

The SDK ships with a sensible default list. You control the list entirely — extend it, replace it, or set it to [] to disable masking.

use Treblle\Php\Config\TreblleConfig; // Extend the defaults 'masked_keywords' => array_merge( TreblleConfig::DEFAULT_MASKED_KEYWORDS, ['access_token', 'refresh_token', 'api_secret'], ),
// Disable masking entirely 'masked_keywords' => [],

The Authorization header is masked with scheme-preserving formatting (e.g. Bearer ****) when it appears in the keyword list.

excluded_paths

Paths that should not be tracked by Treblle. Supports exact matches, wildcards, and regular expressions.

'excluded_paths' => [ '/health', // exact match '/uptime', // exact match '/status', // exact match 'admin/*', // wildcard: matches /admin/users, /admin/settings, etc. '/^\/debug\//i', // regex: matches any path starting with /debug/ ],

Exact match — the full path must match character for character (case-insensitive):

'/health' // matches /health only

Wildcard — use * (any sequence) or ? (any single character):

'admin/*' // matches admin/users, admin/settings/edit, etc. 'api/v?/*' // matches api/v1/anything, api/v2/anything, etc.

Regex — any string that starts and ends with / is treated as a regex:

'/^\/api\/v\d+\/internal/' // matches /api/v1/internal, /api/v2/internal, etc.

custom_ingress

Override the default ingress endpoint. Useful for EU-hosted or self-hosted Treblle deployments:

'custom_ingress' => 'https://ingress-eu.treblle.com',

Endpoint Detection

In plain PHP, Treblle is unable to automatically determine the parameterised route path for a request. For example, for articles/12345 the endpoint path would be articles/{id}. Supplying the route pattern lets Treblle build a much more accurate API representation.

Option 1 — Treblle::setRoutePath()

Call this after your router has resolved the route, before the request completes:

use Treblle\Php\Treblle; Treblle::setRoutePath('articles/{id}');

Works with any routing library. Example with nikic/fast-route :

$dispatcher = FastRoute\simpleDispatcher(function (FastRoute\RouteCollector $r) { $r->addRoute('GET', '/v1/articles/{id:\d+}', 'ArticleHandler'); }); [$status, $handler, $vars] = $dispatcher->dispatch($method, $path); if ($status === FastRoute\Dispatcher::FOUND) { Treblle::setRoutePath('/v1/articles/{id}'); }

Option 2 — $_SERVER['TREBLLE_ROUTE_PATH']

Set the server variable anywhere before the shutdown handler runs. Useful when Treblle is initialised in a bootstrap file and the route path is resolved in a different layer:

$_SERVER['TREBLLE_ROUTE_PATH'] = 'articles/{id}';

You can also set it from .htaccess for simple setups where a rewrite rule maps to a known pattern:

RewriteRule ^v1/articles/([0-9]+)$ index.php [L,E=TREBLLE_ROUTE_PATH:articles/{id}]

setRoutePath() always takes priority over $_SERVER['TREBLLE_ROUTE_PATH'].

Enrich Requests With Metadata

Attach custom key/value pairs to any request. They appear on the Treblle dashboard and can be used to filter and search requests.

use Treblle\Php\Treblle; Treblle::metadata([ 'user-id' => 'john@acmecorp.com', 'tenant' => 'acme-corp', 'plan' => 'enterprise', ]);

Tip

user-id is a reserved keyword that powers customer dashboards and tracks usage across your API.

Call Treblle::metadata() anywhere during the request lifecycle — in a middleware, after authentication, inside a controller. Multiple calls are merged together:

// In an auth middleware Treblle::metadata(['user-id' => $user->id, 'role' => $user->role]); // Later, in a controller Treblle::metadata(['feature_flag' => 'new-checkout']);

The final payload will contain both sets of keys:

{ "data": { "metadata": { "user-id": 42, "role": "admin", "feature_flag": "new-checkout" } } }

Metadata values can be any JSON-serializable type: strings, integers, booleans, or nested arrays.

In persistent runtimes (Swoole, RoadRunner, FrankenPHP), call Treblle::reset() at the start of each request cycle to clear metadata from the previous request alongside all other request state.

PSR-15 Middleware

If your application uses a PSR-15 compatible framework (Slim, Mezzio, Laravel via league/route, etc.) you can use TreblleMiddleware instead of Treblle::create(). The middleware integrates directly into the PSR-15 stack, reads request and response data from the PSR-7 objects (no output buffering), and ships the payload asynchronously via a shutdown function after the response has been delivered.

use Treblle\Php\Middleware\TreblleMiddleware; $middleware = TreblleMiddleware::create( sdkToken: $_ENV['TREBLLE_SDK_TOKEN'], apiKey: $_ENV['TREBLLE_API_KEY'], ); // Slim 4 $app->add($middleware); // Mezzio / Laminas $app->pipe($middleware);

Register it as the outermost middleware so it wraps the full request/response cycle and captures all headers and the complete response body.

All options from Treblle::create() are supported as the third argument:

$middleware = TreblleMiddleware::create( sdkToken: $_ENV['TREBLLE_SDK_TOKEN'], apiKey: $_ENV['TREBLLE_API_KEY'], options: [ 'enabled' => $_ENV['APP_ENV'] === 'production', 'masked_keywords' => array_merge(TreblleConfig::DEFAULT_MASKED_KEYWORDS, ['access_token']), 'excluded_paths' => ['/health', '/metrics'], ], );

Or construct with a config object directly:

use Treblle\Php\Config\TreblleConfig; use Treblle\Php\Middleware\TreblleMiddleware; $middleware = new TreblleMiddleware(new TreblleConfig( sdkToken: $_ENV['TREBLLE_SDK_TOKEN'], apiKey: $_ENV['TREBLLE_API_KEY'], ));

Route path in PSR-15

Supply the parameterised route pattern via a PSR-7 request attribute named _treblle_route_path:

$request = $request->withAttribute('_treblle_route_path', 'articles/{id}');

Treblle::setRoutePath() also works from inside the handler if you prefer that approach.

Metadata in PSR-15

Treblle::metadata() works the same way — call it anywhere inside the handler or its downstream middleware:

public function handle(ServerRequestInterface $request): ResponseInterface { $user = $this->auth->authenticate($request); Treblle::metadata(['user_id' => $user->id, 'plan' => $user->plan]); // ... handle request ... }

Async Mode

The SDK sends data to Treblle after your response has been delivered, using the first available strategy:

  1. fastcgi_finish_request() (PHP-FPM) — flushes the HTTP response to the client and continues running in the background. The Treblle call is completely invisible to your end users.
  2. pcntl_fork() (Linux/Unix CLI and FPM where pcntl is available) — forks a child process to send the data. The parent process returns immediately.
  3. Sync fallback — if neither of the above is available, the data is sent synchronously after the response is flushed. This adds network latency to your shutdown phase but does not affect the response your users receive.

No configuration is required. The SDK detects the environment at runtime and picks the best available strategy.

Migrating from v5 to v6

1. Update the package

composer require treblle/treblle-php:^6.0

2. Remove the Guzzle dependency

v6 uses native PHP curl — Guzzle is no longer required. If your project only pulled it in for Treblle, you can remove it:

composer remove guzzlehttp/guzzle

3. Replace TreblleFactory::create() with Treblle::create()

The factory class is gone. Initialisation now goes through Treblle::create() directly.

// Before (v5) use Treblle\Php\Factory\TreblleFactory; TreblleFactory::create( apiKey: 'your-api-key', sdkToken: 'your-sdk-token', );
// After (v6) use Treblle\Php\Treblle; Treblle::create( sdkToken: 'your-sdk-token', apiKey: 'your-api-key', );

Note that the parameter order is reversed — sdkToken is now first.

4. Update renamed and moved options

v5v6Notes
$maskedFields (3rd positional arg)options['masked_keywords']Renamed; now controls the full list, not just additions
$excludedHeaders (4th positional arg)(removed)Use masked_keywords to hide header values instead
$config['url']options['custom_ingress']Renamed
$config['fork_process'](removed)Async is now automatic
$config['register_handlers'](removed)Handlers are always registered
(new)options['enabled']Global on/off switch

Full before/after example:

// Before (v5) use Treblle\Php\Factory\TreblleFactory; TreblleFactory::create( apiKey: 'your-api-key', sdkToken: 'your-sdk-token', debug: false, maskedFields: ['access_token', 'refresh_token'], excludedHeaders: ['X-Internal-Header'], config: [ 'url' => 'https://ingress-eu.treblle.com', 'fork_process' => true, ], );
// After (v6) use Treblle\Php\Treblle; Treblle::create( sdkToken: 'your-sdk-token', apiKey: 'your-api-key', options: [ 'debug' => false, 'masked_keywords' => ['password', 'pwd', 'secret', 'access_token', 'refresh_token'], 'custom_ingress' => 'https://ingress-eu.treblle.com', ], );

5. Review maskedFields vs masked_keywords

In v5, $maskedFields was additive — the SDK merged your list with its own defaults.

In v6, masked_keywords is the full list. If you pass a value, it replaces the defaults entirely. To extend the defaults, merge them explicitly:

use Treblle\Php\Config\TreblleConfig; use Treblle\Php\Treblle; Treblle::create( sdkToken: 'your-sdk-token', apiKey: 'your-api-key', options: [ 'masked_keywords' => array_merge( TreblleConfig::DEFAULT_MASKED_KEYWORDS, ['access_token', 'refresh_token'], ), ], );
Last updated on