Creare estensioni per Tracy
Tracy è un ottimo strumento per fare il debug della vostra applicazione. A volte però vorreste avere subito a portata di mano altre informazioni. Vi mostriamo come scrivere estensioni proprie per la Tracy Bar, per rendere lo sviluppo ancora più piacevole.
- Creare un proprio pannello della Tracy Bar
- Creare una propria estensione della Bluescreen
Un repository di estensioni già pronte per Tracy lo trovate su Componette.
Estensioni della Tracy Bar
Creare una nuova estensione per la Tracy Bar è semplice. Create un oggetto che implementa l'interfaccia
Tracy\IBarPanel, che ha due metodi: getTab() e getPanel(). Questi metodi devono restituire
il codice HTML della linguetta (una piccola etichetta mostrata direttamente sulla Bar) e del pannello (una finestra mostrata dopo
aver cliccato la linguetta). Se getPanel() non restituisce nulla, viene mostrata solo la linguetta. Se
getTab() non restituisce nulla, non viene mostrato niente e getPanel() non viene chiamato.
class ExamplePanel implements Tracy\IBarPanel
{
public function getTab()
{
return /* ... */;
}
public function getPanel()
{
return /* ... */;
}
}
Registrazione
La registrazione avviene chiamando Tracy\Debugger::getBar()->addPanel():
Tracy\Debugger::getBar()->addPanel(new ExamplePanel);
In alternativa potete registrare il pannello direttamente nella configurazione dell'applicazione:
tracy:
bar:
- ExamplePanel
Codice HTML della linguetta
Dovrebbe assomigliare a questo:
<span title="Tooltip esplicativo">
<svg>...</svg>
<span class="tracy-label">Titolo</span>
</span>
L'immagine dovrebbe essere in formato SVG. Se il tooltip esplicativo non serve, lo <span> esterno si può
omettere.
Codice HTML del pannello
Dovrebbe assomigliare a questo:
<h1>Titolo</h1>
<div class="tracy-inner">
<div class="tracy-inner-container">
... contenuto ...
</div>
</div>
Il titolo dovrebbe essere uguale a quello della linguetta oppure contenere informazioni aggiuntive.
Tenete presente che una stessa estensione può essere registrata più volte, magari con impostazioni diverse. Per lo stile non
potete quindi usare gli ID CSS, ma solo le classi, preferibilmente nel formato
tracy-addons-<NomeClasse>[-<opzionale>]. Aggiungete questa classe al div insieme alla classe
tracy-inner. Quando scrivete il CSS conviene anteporre ai selettori #tracy-debug .vostra-classe, perché
così la regola ha una specificità maggiore degli stili di reset.
Stili predefiniti
Nel pannello gli elementi <a>, <table>, <pre> e
<code> hanno stili predefiniti. Se volete creare un link che nasconde e mostra un altro elemento, collegateli
con gli attributi href e id e con la classe tracy-toggle:
<a href="#tracy-addons-ClassName-{$counter}" class="tracy-toggle">Dettagli</a>
<div id="tracy-addons-ClassName-{$counter}">...</div>
Se lo stato predefinito è chiuso, aggiungete a entrambi gli elementi la classe tracy-collapsed.
Usate un contatore statico per evitare ID duplicati su una stessa pagina.
Asset personalizzati
Se il vostro pannello ha bisogno di un proprio foglio di stile o di un proprio script, potete far caricare a Tracy dei file aggiuntivi insieme ai suoi:
Tracy\Debugger::$customCssFiles[] = __DIR__ . '/panel.css';
Tracy\Debugger::$customJsFiles[] = __DIR__ . '/panel.js';
Supporto per gli agenti AI
Quando un agente AI comanda il browser, Tracy invia alla console JS un riassunto in markdown della Tracy Bar. I pannelli
personalizzati possono fornire il proprio markdown aggiungendo alla loro implementazione di IBarPanel il metodo
getAgentInfo(): ?string:
class DatabasePanel implements Tracy\IBarPanel
{
public function getTab(): string { /* ... */ }
public function getPanel(): string { /* ... */ }
public function getAgentInfo(): ?string
{
return "## Database\n\n- Query: {$this->count}\n- Tempo totale: {$this->time} ms\n";
}
}
Il markdown restituito viene incluso nel riassunto markdown della bar. Se il metodo manca o restituisce null, il
pannello viene omesso dal riassunto.
Il quadro completo lo trovate in Integrazione di Tracy con gli agenti AI.
Estensioni della Bluescreen
In questo modo potete aggiungere visualizzazioni proprie delle eccezioni oppure pannelli che compariranno sulla bluescreen.
Un'estensione si crea così:
Tracy\Debugger::getBlueScreen()->addPanel(function (?Throwable $e) { // eccezione catturata
return [
'tab' => '...Titolo...',
'panel' => '...contenuto HTML del pannello...',
];
});
La funzione viene chiamata due volte. La prima volta nel parametro $e viene passata l'eccezione stessa (se si è
verificata un'eccezione) e il pannello restituito viene renderizzato all'inizio della pagina. Se restituisce null
o un array vuoto, il pannello non viene renderizzato. Poi viene chiamata con $e = null e il pannello restituito
viene renderizzato sotto lo stack delle chiamate. Se la funzione restituisce nell'array 'bottom' => true, il
pannello viene renderizzato in fondo alla pagina.
Oltre ai pannelli potete aggiungere anche delle azioni con addAction(): link o pulsanti cliccabili che
compaiono nell'intestazione della pagina di errore accanto a quelli integrati (per esempio search):
Tracy\Debugger::getBlueScreen()->addAction(function (Throwable $e): ?array {
if ($e instanceof MyException) {
return [
'link' => 'https://example.com/help?code=' . $e->getCode(),
'label' => 'visualizza aiuto',
];
}
return null;
});
Il callback riceve l'eccezione catturata e restituisce un array con le chiavi link e label, oppure
null se non vuole aggiungere un'azione per quella eccezione.
Azione create file
Quando sulla pagina di errore cliccate un file che ancora non esiste, Tracy propone di crearlo (l'azione create file). Il contenuto iniziale di un file del genere lo potete governare registrando un generatore:
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;
});
Il callback riceve il percorso del file di destinazione e, quando è noto, il nome della classe che vi dovrebbe essere
definita. Restituisce il contenuto iniziale (il token $END$ segna dove verrà messo il cursore e viene rimosso
dall'output), oppure null per lasciare la decisione a un altro generatore. I generatori vengono provati a partire
dall'ultimo registrato; il generatore integrato produce un semplice scheletro PHP.
Fiber e generator
Se un'eccezione viene lanciata mentre una fiber o un generator è sospeso, il suo stack non fa parte del normale stack delle chiamate. Tracy mostra automaticamente lo stack delle fiber e dei generator raggiungibili dall'eccezione, ma uno che gira in modo indipendente sfuggirebbe. Potete aggiungerlo alla BlueScreen a mano:
Tracy\Debugger::getBlueScreen()->addFiber($fiber);