kutny/tracy-bundle
Symfony bundle that integrates the Tracy debugger into your application, adding a rich debug bar, clearer exception pages, and detailed logging. It simplifies everyday debugging and gives developers fast, readable insight into requests, queries, and errors.
First, a reality check: kutny/tracy-bundle is a Symfony bundle, not a Laravel package. It was last released in January 2018, is archived, and its job is to wire Nette Tracy into a Symfony kernel (register Debugger::enable(), map bundle config onto Tracy's static properties, and route kernel exceptions through Tracy's blue screen). It requires symfony/framework-bundle/symfony/http-kernel, so composer require kutny/tracy-bundle in a modern Laravel app will not resolve. Read it as a reference implementation for Tracy integration, not as a dependency.
What you actually want from it is Tracy itself:
composer require --dev tracy/tracy
Minimal step one is a service provider that enables Tracy only outside production:
// app/Providers/TracyServiceProvider.php
use Tracy\Debugger;
public function register(): void
{
if (! $this->app->environment(['local', 'staging'])) {
return;
}
Debugger::enable(Debugger::DEVELOPMENT, storage_path('logs/tracy'));
Debugger::setLogger(new Tracy\Logger(storage_path('logs/tracy')));
}
Look first at Tracy\Debugger (all the knobs: $logDirectory, $email, $strictMode, $showBar, $maxLen) and Tracy\Dumper — that is 90% of the day-to-day value. The bundle itself is a thin DI extension plus an exception listener; skim its DependencyInjection/Configuration.php and listener to see the config→static-property mapping pattern, then close the tab.
Your first real use case: instead of dd(), use Tracy's bdump($order) / barDump($payload) to push structured dumps into the debug bar, and Tracy\Debugger::timer('checkout') … Debugger::timer('checkout') to time a block without leaving the page. The blue screen with source context and $container/$request locals is the genuine upgrade over a stack-trace-only page.
Don't fight Laravel's exception handler — complement it. Tracy's Debugger::enable() installs global error/exception handlers, and Illuminate\Foundation\Bootstrap\HandleExceptions already did. The kernel catches Throwable around sendRequestThroughRouter, so framework exceptions never reach Tracy; Tracy only sees fatals, boot-time errors and console. That is fine — accept it, and render blue screens manually where you want them:
// in App\Exceptions\Handler::render(), local only
if (app()->environment('local') && $request->expectsJson() === false) {
return response(
Debugger::getBlueScreen()->render($e),
500
);
}
Inject the bar with middleware, not with output buffering hacks. Sketch:
public function handle($request, Closure $next)
{
$response = $next($request);
if (Debugger::$showBar
&& $response instanceof \Illuminate\Http\Response
&& str_contains($response->headers->get('Content-Type', ''), 'text/html')
) {
$bar = Debugger::getBar()->render(); // panel HTML
$html = str_replace('</body>', $bar . '</body>', $response->getContent());
$response->setContent($html);
}
return $response;
}
This is the same shape as the bundle's listener — condition on HTML, mutate the response, do nothing else.
Avoid the dump() collision. Laravel already defines global dump()/dd() via Symfony VarDumper. Tracy also ships a dump() shortcut. Either namespace everything through Tracy\Dumper::dump($var, $return = true) or add a tracy() helper and never load Tracy's shortcut file. bdump(), barDump(), Debugger::log() do not collide and are the ones you want in Blade and jobs anyway.
Log to files for staging. Tracy\Logger writes an .html blue-screen artifact plus a .log line per error into storage/logs/tracy. That is a much better staging debugging loop than scrolling laravel.log, especially for the "it broke at 2am" case. Wire it in App\Exceptions\Handler::report() for non-production:
Debugger::log($e, Debugger::ERROR);
Config-to-static mapping (the bundle's only real idea). Keep Tracy's global statics in one place — a provider or config/tracy.php read at boot — because Debugger::$logDirectory, $showBar, $strictMode are process globals that nothing scopes for you.
Debugger::$showBar, $strictMode, $email are static. Under Laravel Octane, a worker outlives the request; anything you set per-request leaks into the next one. Set statics once at boot, never in middleware.ErrorException with different error_reporting semantics than Laravel's handler, and any Debugger::$strictMode = true turns deprecations into noise from vendor code. If things suddenly throw where they used to log, this is why.Debugger::$email will happily email full stack traces with locals to whoever is configured. Gate on APP_ENV and re-check Debugger::$productionMode.*.html artifacts include local variable snapshots — add storage/logs/tracy to .gitignore, rotate it, and never ship it in a deploy artifact.204s and anything with Content-Length already set will corrupt or fail. Tests asserting exact bodies will fail while the bar is on; disable it in phpunit.xml or force Debugger::$showBar = false when runningUnitTests().Debugger::enable() with an unwritable $logDirectory degrades silently or throws depending on version — check is_writable(storage_path('logs/tracy')) on first boot.Tracy\Dumper::$maxDepth, ::$maxItems, ::$maxLength default low enough that large Eloquent results look truncated. Bump them locally; the "it dumped an empty array" complaint is almost always truncation, not an empty value.Tracy\IBarPanel (one getTab() + one getPanel() method) and Debugger::getBar()->addPanel(new YourPanel) for domain-specific panels (queue depth, current tenant, feature flags); Debugger::getBlueScreen()->addPanel(...) for extra context on error pages; Helpers::capture(fn() => ...) to render a view to string for a panel.dump()/dd() with dump-server for AJAX). Tracy's differentiators are the persistent bar, the blue screen's source context, and file/email logging — if you only want the last one, Debugger::log() alone, without Debugger::enable(), gets you most of the value with none of the handler conflicts.How can I help you explore Laravel packages today?