Extensions für Tracy erstellen

Tracy ist ein großartiges Werkzeug zum Debuggen Ihrer Anwendung. Manchmal möchten Sie jedoch weitere Informationen sofort zur Hand haben. Wir zeigen Ihnen, wie Sie eigene Extensions für die Tracy Bar schreiben, um die Entwicklung noch angenehmer zu machen.

  • Ein eigenes Panel der Tracy Bar erstellen
  • Eine eigene Extension für den Bluescreen erstellen

Ein Repository fertiger Extensions für Tracy finden Sie auf Componette.

Extensions für die Tracy Bar

Eine neue Extension für die Tracy Bar zu erstellen, ist unkompliziert. Erstellen Sie ein Objekt, das das Interface Tracy\IBarPanel implementiert, welches zwei Methoden hat: getTab() und getPanel(). Diese Methoden müssen den HTML-Code für den Tab (ein kleines Label, das direkt auf der Bar angezeigt wird) und für das Panel (ein Popup, das nach dem Klick auf den Tab erscheint) zurückgeben. Gibt getPanel() nichts zurück, wird nur der Tab selbst angezeigt. Gibt getTab() nichts zurück, wird überhaupt nichts angezeigt, und getPanel() wird nicht aufgerufen.

class ExamplePanel implements Tracy\IBarPanel
{
	public function getTab()
	{
		return /* ... */;
	}

	public function getPanel()
	{
		return /* ... */;
	}
}

Registrierung

Die Registrierung erfolgt durch den Aufruf von Tracy\Debugger::getBar()->addPanel():

Tracy\Debugger::getBar()->addPanel(new ExamplePanel);

Alternativ können Sie das Panel direkt in der Konfiguration der Anwendung registrieren:

tracy:
	bar:
		- ExamplePanel

HTML-Code des Tabs

Sollte ungefähr so aussehen:

<span title="Explanatory tooltip">
	<svg>...</svg>
	<span class="tracy-label">Title</span>
</span>

Das Bild sollte im Format SVG vorliegen. Wenn kein erläuternder Tooltip nötig ist, kann das äußere <span> entfallen.

HTML-Code des Panels

Sollte ungefähr so aussehen:

<h1>Title</h1>

<div class="tracy-inner">
<div class="tracy-inner-container">
	... content ...
</div>
</div>

Der Titel sollte entweder derselbe wie der Titel des Tabs sein oder zusätzliche Informationen enthalten.

Denken Sie daran, dass eine einzelne Extension mehrfach registriert werden kann, womöglich mit unterschiedlichen Einstellungen. Deshalb dürfen Sie zum Stylen keine CSS-IDs verwenden, sondern nur Klassen, am besten im Format tracy-addons-<ClassName>[-<optional>]. Fügen Sie diese Klasse zusammen mit der Klasse tracy-inner dem div hinzu. Beim Schreiben von CSS ist es sinnvoll, den Selektoren #tracy-debug .your-class voranzustellen, denn das gibt der Regel eine höhere Spezifität als die Reset-Styles.

Standardstile

Im Panel haben die Elemente <a>, <table>, <pre> und <code> vordefinierte Stile. Wenn Sie einen Link erstellen wollen, der ein anderes Element ein- und ausblendet, verbinden Sie beide über die Attribute href und id sowie die Klasse tracy-toggle:

<a href="#tracy-addons-ClassName-{$counter}" class="tracy-toggle">Details</a>

<div id="tracy-addons-ClassName-{$counter}">...</div>

Ist der Standardzustand eingeklappt, ergänzen Sie bei beiden Elementen die Klasse tracy-collapsed.

Verwenden Sie einen statischen Zähler, um doppelte IDs auf einer Seite zu vermeiden.

Eigene Assets

Wenn Ihr Panel ein eigenes Stylesheet oder Skript braucht, können Sie Tracy weitere Dateien neben seinen eigenen Assets laden lassen:

Tracy\Debugger::$customCssFiles[] = __DIR__ . '/panel.css';
Tracy\Debugger::$customJsFiles[] = __DIR__ . '/panel.js';

Unterstützung für KI-Agenten

Wenn ein KI-Agent den Browser steuert, sendet Tracy eine Markdown-Zusammenfassung der Tracy Bar in die JS-Konsole. Eigene Panels können ihr eigenes Markdown liefern, indem sie ihrer Implementierung von IBarPanel eine Methode getAgentInfo(): ?string hinzufügen:

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";
	}
}

Das zurückgegebene Markdown wird in die Markdown-Zusammenfassung der Bar aufgenommen. Fehlt die Methode oder gibt sie null zurück, wird das Panel in der Zusammenfassung ausgelassen.

Das Gesamtbild finden Sie unter Tracys Integration für KI-Agenten.

Extensions für den Bluescreen

Auf diese Weise können Sie eigene Visualisierungen von Exceptions oder Panels ergänzen, die auf dem Bluescreen erscheinen.

Eine Extension wird so erstellt:

Tracy\Debugger::getBlueScreen()->addPanel(function (?Throwable $e) { // abgefangene Exception
	return [
		'tab' => '...Title...',
		'panel' => '...HTML panel content...',
	];
});

Die Funktion wird zweimal aufgerufen. Zuerst wird im Parameter $e die Exception selbst übergeben (falls eine aufgetreten ist), und das zurückgegebene Panel wird am Anfang der Seite gerendert. Gibt sie null oder ein leeres Array zurück, wird das Panel nicht gerendert. Danach wird sie mit $e = null aufgerufen, und das zurückgegebene Panel wird unter dem Aufrufstack gerendert. Gibt die Funktion im Array 'bottom' => true zurück, wird das Panel ganz unten gerendert.

Außer Panels können Sie mit addAction() auch Aktionen ergänzen – anklickbare Links oder Schaltflächen, die im Kopf der Fehlerseite neben den eingebauten erscheinen (etwa search):

Tracy\Debugger::getBlueScreen()->addAction(function (Throwable $e): ?array {
	if ($e instanceof MyException) {
		return [
			'link' => 'https://example.com/help?code=' . $e->getCode(),
			'label' => 'view help',
		];
	}
	return null;
});

Der Callback erhält die abgefangene Exception und gibt ein Array mit den Schlüsseln link und label zurück oder null, wenn er für die betreffende Exception keine Aktion ergänzen will.

Aktion Create File

Wenn Sie auf der Fehlerseite auf eine Datei klicken, die es noch nicht gibt, bietet Tracy an, sie anzulegen (die Aktion create file). Den anfänglichen Inhalt einer solchen Datei können Sie steuern, indem Sie einen Generator registrieren:

Tracy\Debugger::getBlueScreen()->addFileGenerator(function (string $file, ?string $class): ?string {
	if (str_ends_with($file, 'Test.php')) {
		return "<?php\n\nclass $class extends Tester\\TestCase\n{\n\t\$END\$\n}\n";
	}
	return null;
});

Der Callback erhält den Pfad der Zieldatei und, sofern bekannt, den Namen der Klasse, die darin definiert werden soll. Er gibt den anfänglichen Inhalt zurück (das Token $END$ markiert, wo der Cursor stehen wird, und wird aus der Ausgabe entfernt) oder null, um die Entscheidung einem anderen Generator zu überlassen. Die Generatoren werden vom zuletzt registrierten an durchprobiert; der eingebaute Generator erzeugt ein einfaches PHP-Gerüst.

Fibers und Generatoren

Wird eine Exception geworfen, während eine Fiber oder ein Generator angehalten ist, ist ihr Stack nicht Teil des regulären Aufrufstacks. Tracy zeigt automatisch den Stack der Fibers und Generatoren, die von der Exception aus erreichbar sind, aber einer, der unabhängig läuft, würde übersehen. Sie können ihn dem BlueScreen von Hand hinzufügen:

Tracy\Debugger::getBlueScreen()->addFiber($fiber);