Skip to content
24/48h shipping across Italy
Skip to content
Documentation navigation

Tracy evaluation

Outcome

Do not adopt Tracy. The current stack remains because Tracy would overlap with Whoops and PHPDebugBar, would not replace Clockwork/Monolog/GlitchTip, and registers competing global handlers. ADR 0006 records the decision.

Current responsibility inventory

Component Authoritative responsibility Hook and production state
Symfony ErrorHandler PHP error bootstrap Registered first; debug/production selected by APP_DEBUG
Laminas Stratigility ErrorHandler Outermost PSR-15 HTTP exception boundary Produces safe HTML or Problem+JSON and incident IDs
Whoops Development exception visualization only Called by ErrorResponseGenerator; never registered globally
PHPDebugBar In-page HTML bar and AJAX/JSON debug headers Debug-only middleware; receives sanitized lifecycle snapshots
Clockwork Persisted request timeline, Monolog, DBAL queries, browser tooling Debug-only PSR-15 middleware and bridge
Monolog Persistent structured application/worker logs Active independently from browser tooling
GlitchTip Sanitized remote production error reporting Process-env opt-in; no default PII/request body

Application code writes through DebugLogger and HttpDebugTracer, not through a vendor collector. Header/cookie/body snapshots have bounded depth and length; known authorization, cookie, password, token, API-key, and secret keys are redacted centrally.

Disposable spike

Tracy 2.12.0 was installed only under /tmp with its own lock/vendor directory; the project manifest and lock were not modified. Reproduce with any disposable Tracy autoloader:

php tools/benchmarks/tracy-spike.php /tmp/tracy-spike/vendor/autoload.php

Environment and five-run result on 2026-08-21:

Probe Result
PHP / Tracy 8.5.9 / 2.12.0
Live memory delta after Debugger::enable(Production) 1,302,376 bytes
Peak memory delta 1,413,840 bytes
Registers global error handler Yes (Closure)
Configured keysToHide dump redaction Synthetic secret hidden
Default structured Debugger::log() redaction Synthetic secret remained
Root dependency/bootstrap after spike Absent

The memory number is a narrow initialization measurement, not a full request benchmark, and is not the rejection reason by itself. Handler ownership, feature replacement, and privacy parity are the controlling gates.

Scenario comparison

Scenario Current stack Tracy 2.12.0 Finding
HTML exception Safe production page; Whoops detail in debug; incident correlation BlueScreen/development detail and production strategy Could replace Whoops, but not the PSR-15 incident contract
AJAX/JSON RFC 7807 response plus opt-in DebugBar headers and Clockwork record AJAX-aware diagnostics Needs a new PSR-7/Problem+JSON adapter; no measured gain
Handled exception Laminas listener logs, traces, reports and preserves response semantics Global exception strategy Competes with the authoritative HTTP boundary
CLI exception Symfony Console rendering, Monolog; GlitchTip bootstrap present CLI-friendly text/BlueScreen logging Better local presentation alone does not close the known remote CLI-capture hook gap
database query Clockwork DBAL datasource, including cached test connections Core Tracy has no project DBAL collector; addons/integration required Does not replace current coverage
Sensitive-value redaction Central recursive/bounded HTTP and GlitchTip sanitizers Dump keys configurable; default log spike retained the synthetic value Weaker safe default for current usage
Streaming/async Debug middleware is gated and can be bypassed; workers log without HTML injection Bar/BlueScreen depend on global process/output behavior No improvement; long-lived workers need explicit reset semantics
Production monitoring Monolog + remote GlitchTip release/environment/incident IDs Local production log/error strategy Does not replace remote monitoring
Windows Existing browser tools and Whoops are pure PHP; worker signal caveat documented PHP 8.2–8.5 supported, pure PHP Compatible, no differentiating benefit
CSP Current delivery still needs a complete future policy Tracy documents nonce/strict-dynamic and requires inline styles Not a path to a stricter policy

Validation

The comparison reused the current HTML, AJAX/JSON, exception, lifecycle, redaction, and production reporter unit suites. The architecture contract proves that rejected Tracy code leaves neither a dependency nor a bootstrap reference. There is exactly one global error-handler owner; do not enable Tracy beside it.