Creating Tracy Extensions
Tracy is a great tool for debugging your application. However, you sometimes might want additional information readily available. We'll show you how to write your own extensions for the Tracy Bar to make development even more pleasant.
- Creating your own Tracy Bar panel
- Creating your own Bluescreen extension
You can find a repository of ready-made extensions for Tracy on Componette.
Tracy Bar Extensions
Creating a new extension for the Tracy Bar is straightforward. Create an object that implements the
Tracy\IBarPanel interface, which has two methods: getTab() and getPanel(). These methods
must return the HTML code for the tab (a small label displayed directly on the Bar) and the panel (a popup displayed after
clicking the tab). If getPanel() returns nothing, only the tab itself is displayed. If getTab() returns
nothing, nothing is displayed at all, and getPanel() is not called.
class ExamplePanel implements Tracy\IBarPanel
{
public function getTab()
{
return /* ... */;
}
public function getPanel()
{
return /* ... */;
}
}
Registration
Registration is done by calling Tracy\Debugger::getBar()->addPanel():
Tracy\Debugger::getBar()->addPanel(new ExamplePanel);
Alternatively, you can register the panel directly in the application configuration:
tracy:
bar:
- ExamplePanel
Tab HTML Code
Should look something like this:
<span title="Explanatory tooltip">
<svg>...</svg>
<span class="tracy-label">Title</span>
</span>
The image should be in SVG format. If an explanatory tooltip is not needed, the outer <span> can be
omitted.
Panel HTML Code
Should look something like this:
<h1>Title</h1>
<div class="tracy-inner">
<div class="tracy-inner-container">
... content ...
</div>
</div>
The title should either be the same as the tab title or contain additional information.
Keep in mind that a single extension might be registered multiple times, perhaps with different settings. Therefore, for
styling, you cannot use CSS IDs, only classes, preferably in the format
tracy-addons-<ClassName>[-<optional>]. Add this class to the div along with the tracy-inner
class. When writing CSS, it's useful to prefix selectors with #tracy-debug .your-class, as this gives the rule
higher specificity than the reset styles.
Default Styles
In the panel, <a>, <table>, <pre>, and <code>
elements have predefined styles. If you want to create a link that hides and shows another element, connect them using
href and id attributes and the tracy-toggle class:
<a href="#tracy-addons-ClassName-{$counter}" class="tracy-toggle">Details</a>
<div id="tracy-addons-ClassName-{$counter}">...</div>
If the default state is collapsed, add the class tracy-collapsed to both elements.
Use a static counter to prevent duplicate IDs on one page.
AI Agent Support
When an AI agent drives the browser, Tracy sends a markdown summary of the Tracy Bar to the JS console. Custom panels can
supply their own markdown by adding a getAgentInfo(): ?string method to their IBarPanel
implementation:
class DatabasePanel implements Tracy\IBarPanel
{
public function getTab(): string { /* ... */ }
public function getPanel(): string { /* ... */ }
public function getAgentInfo(): ?string
{
return "## Database\n\n- Queries: {$this->count}\n- Total time: {$this->time} ms\n";
}
}
The returned markdown is included in the bar's markdown summary. When the method is missing or returns null, the
panel is omitted from the summary.
See Tracy's AI agent integration for the full picture.
Bluescreen Extensions
This way, you can add custom exception visualizations or panels that will appear on the bluescreen.
An extension is created like this:
Tracy\Debugger::getBlueScreen()->addPanel(function (?Throwable $e) { // caught exception
return [
'tab' => '...Title...',
'panel' => '...HTML panel content...',
];
});
The function is called twice. First, the exception itself is passed in the $e parameter (if an exception
occurred), and the returned panel is rendered at the beginning of the page. If it returns null or an empty array, the
panel is not rendered. Then, it is called with $e = null, and the returned panel is rendered below the call stack. If
the function returns 'bottom' => true in the array, the panel is rendered at the very bottom.