Tracy Documentation

repository·master·Indexed 23 days ago

https://github.com/nette/tracy

A powerful debugging helper for PHP developers (compatible with PHP 8.2 to 8.5). Tracy provides visual error/exception reporting via BlueScreens, a debug bar for inspecting application state, variable dumping with dump(), and performance timing via Stopwatch. It includes features for development and production mode configuration, custom logging via ILogger or PSR-3 adapters, and a build-time tool called Tracy Latte Convert for compiling .latte templates into .phtml files.

Tokens
10.9K
Snippets
9
Records
72
Agent score
83%

What's inside Tracy

  1. How Tracy's Logger handles exceptions and deduplication

    master

    The Logger::log() method appends text lines to <level>.log files. When a Throwable is logged, Tracy generates an HTML BlueScreen report and a .md companion file.

    To prevent log flooding, Tracy uses hash-based deduplication:

    1. It generates a hash of the exception chain (class, message, code, file, line, and trace without arguments) using xxh128, truncated to 10 characters.
    2. Because arguments are stripped from the trace, identical exceptions thrown with different argument values produce the same hash.
    3. If a report with that hash already exists, Tracy will not overwrite it; it will only append a new line to the <level>.log file. This ensures that recurring errors do not repeatedly generate heavy HTML reports.
  2. Configure Tracy Development and Production modes

    master

    You can manually control the mode or restrict development access to specific IP addresses or via a cookie.

    • Force Development mode: Debugger::enable(Debugger::Development)
    • Force Production mode: Debugger::enable(Debugger::Production)
    • Restrict to specific IP(s): Debugger::enable('23.75.345.200') or Debugger::enable(['127.0.0.1', '192.168.1.1'])
    • Secure access via IP + Cookie: Use the format IP@secret_token. Tracy will only enable development mode if the user accesses from that IP and has a cookie named tracy-debug containing the secret token.
  3. How deferred content works in Tracy

    master

    Tracy uses a DeferredContent mechanism to ensure debug information (like the Tracy Bar or BlueScreen) is displayed even when the initial response cannot contain a body, such as during a Redirect or an AJAX request.

    Instead of rendering directly into the current response, the content is stored in the session and delivered via a second HTTP request made by the browser. This allows debug output to 'survive' redirects and appear on the subsequent page, or be fetched as a separate payload during AJAX operations.

  4. Understand the PHP ↔ JS contract in Tracy

    master

    Tracy's PHP side and client-side JavaScript (bar.js, bluescreen.js, dumper.js, etc.) are coupled via string-based contracts. This means function names, element IDs, attribute names, and storage keys must match exactly between PHP and JS. Renaming a symbol on one side without updating the other will cause silent runtime failures.

    Key areas of coupling include:

    • JS Method Calls: PHP uses DeferredContent::addSetup($method, $argument) to emit literal JS calls that must match symbols on window.Tracy.
    • Data Attributes: The dumper uses specific data-tracy-* attributes to handle lazy loading and snapshots.
    • DOM IDs: Specific IDs like tracy-debug-bar and tracy-bs are expected by the JS logic.
    • Storage Keys: Tracy uses localStorage and sessionStorage with specific keys for persistence (e.g., tracy-debug-bar).
  5. How Tracy handles rendering modes (AJAX, Redirect, and Normal HTML)

    master

    The render() method behaves differently depending on the request type to ensure the toolbar appears correctly:

    • AJAX/Deferred: It adds a setup script Tracy.Debug.loadAjax to render the ajax partial.
    • Redirect: It pushes the partial onto the session redirect queue so the toolbar appears after the destination page loads.
    • Normal HTML:
      • It renders the main partial.
      • It drains the redirect queue (processing items in reverse order) so that bars from previous redirects are displayed.
      • It either adds Tracy.Debug.init via a setup script or requires loader.phtml directly.

    Note on Headers: If a Content-Length header has already been sent, Tracy will log a LogicException and skip injecting the markup to avoid corrupting the response.

  6. Understand how improveException() mutates exceptions

    master
    The improveException() helper function performs mutation on the exception object passed to it. It uses reflection to rewrite the private $message property to append suggestions (e.g., ", did you mean …?"). Additionally, it may set a dynamic $e->tracyAction property (containing {link, label}) which is used by BlueScreen::renderActions() to provide clickable actions. Note that suggestions are generated using a weighted Levenshtein algorithm via getSuggestion() rather than a simple edit distance.
  7. How the Tracy Bar and Panels work

    master

    The Tracy debug toolbar is a collection of IBarPanel objects. These panels are rendered after the response body using DeferredContent.

    Adding Panels

    You can add custom panels to the bar using addPanel(IBarPanel $panel, ?string $id = null). If no ID is provided, one is automatically derived from the class name.

    Panel Lifecycle and Rendering

    • Tabs and Content: Each panel provides a tab name via getTab() and the actual content via getPanel(). The Bar only calls getPanel() if getTab() returns a non-empty string.
    • Error Handling: Rendering is wrapped in a temporary error handler. If a panel throws an error, it is caught and replaced with an "Error in <id>" panel to prevent the entire toolbar from breaking.
    • Agent Info: If a panel implements an optional getAgentInfo() method, this information is included in the bar's agent line (e.g., Tracy Bar | <ms> | <MB>).

    Built-in Panels

    Tracy includes several default panels:

    • info: Provides general information.
    • warnings: Populated by the error handler to show issues.
    • dumps: Registered lazily when barDump() is first called.
  8. How findCallerLocation() determines stack frames

    master

    When determining where a dump originated, findCallerLocation() may silently skip certain frames in the call stack. It ignores frames if:

    • The frame's docblock contains the @tracySkipLocation annotation.
    • The frame is located under paths defined in Debugger::$transparentPaths.
  9. How BlueScreen rendering works

    master

    BlueScreen is the component responsible for generating the HTML error page. It provides several rendering methods depending on the desired output:

    • render(): Builds the standard HTML error page using page.phtml.
    • renderToAjax(...): Defers rendering via an AJAX call (using addSetup('Tracy.BlueScreen.loadAjax', ...)).
    • renderToFile(string $path): Writes the HTML error page to a file using fopen(..., 'x'). This ensures existing files are never overwritten. It also creates a .md companion file.
    • renderAgent(): Produces a markdown variant of the error report.

    All these methods rely on renderTemplate, which assembles the headers, CSS/JS assets, dumpers, and a live shared snapshot used for data capture during the rendering process.

  10. How the Dumper handles objects and references via snapshots

    master

    To avoid redundant serialization and handle large structures efficiently, the Dumper does not serialize objects, resources, or referenced arrays inline. Instead, it uses a snapshot mechanism:

    • Snapshot Storage: Each unique object, resource, or referenced array is placed into a shared snapshot array, keyed by its ID (e.g., spl_object_id, r<id>, or p<refId>).
    • TypeRef: At the point where the object would normally appear, a Value of type TypeRef is emitted. The renderer then uses this reference to look up the data in the snapshot.
    • Memory Safety: The Value->holder property pins the live object to prevent PHP's Garbage Collector from recycling the spl_object_id while the snapshot is being built.
    • Recursion Protection: Infinite recursion is prevented during the Describe phase. If an object or array is re-encountered at an equal or greater depth, a TypeRef is emitted instead of descending further.
  11. Use isHtmlMode() to gate HTML injection

    master

    The isHtmlMode() helper acts as a global gate to determine if Tracy is allowed to inject debug information (like the Tracy Bar) into the current HTTP response. It returns false in the following scenarios:

    • The request is an AJAX request (detected via X-Requested-With or X-Tracy-Ajax headers).
    • The environment is CLI.
    • The HTTP_HOST is missing.
    • The response has already sent a Content-Type header that is not text/html.
  12. Manage Tracy session lifecycle and cleanup

    master

    Tracy manages deferred content in the session with specific cleanup rules:

    • Automatic Cleanup: The clean() method keeps only the last 10 items per key and only those younger than 60 seconds. This runs inside sendAssets() before content is fetched.
    • Data Requirement: Every item stored in the session must carry a time key; otherwise, clean() will silently discard it.
    • Static Assets: The URL ?_tracy_bar=js serves merged static assets (minified CSS and IIFE-wrapped JS) with a long Cache-Control header.

    Session Types:

    • FileSession: Uses a cookie tracy-session and files named tracy-<id>. Warning: This uses blocking flock(LOCK_EX) which can cause concurrent requests (like an AJAX call and a main page load) to serialize/block each other.