Návody
Content Security Policy
Pokud váš web používá Content Security Policy, budete muset přidat stejné 'nonce-<value>' a
'strict-dynamic' do script-src, aby Tracy správně fungovala. Některé doplňky třetích stran mohou
vyžadovat další nastavení. Nonce není podporována v direktivě style-src, pokud tuto direktivu používáte,
musíte přidat 'unsafe-inline', ale v produkčním režimu byste se tomu měli vyhnout.
Příklad konfigurace pro Nette Framework:
http:
csp:
script-src: [nonce, strict-dynamic]
Příklad v čistém PHP:
$nonce = base64_encode(random_bytes(20));
header("Content-Security-Policy: script-src 'nonce-$nonce' 'strict-dynamic';");
Rychlejší načítání
Spuštění je přímočaré, pokud však máte na webové stránce pomalu načítající se blokující skripty, mohou
zpomalit načítání Tracy. Řešením je umístit <?php Tracy\Debugger::renderLoader() ?> do vaší šablony
před všechny skripty:
<!DOCTYPE html>
<html>
<head>
<title>...<title>
<?php Tracy\Debugger::renderLoader() ?>
<link rel="stylesheet" href="assets/style.css">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
Hledání zdroje výstupu
Setkali jste se někdy s hláškou Cannot modify header information – headers already sent? Objeví se, když se do prohlížeče odešle něco (přebytečná mezera, prázdný řádek nebo BOM na začátku souboru) dřív, než váš kód nastaví HTTP hlavičku nebo nastartuje session. Dohledat viníka bývá otrava.
Tracy\OutputDebugger vám pomůže. Zapněte jej jako úplně první věc v programu:
Tracy\OutputDebugger::enable();
Sleduje veškerý výstup a na konci stránky vypíše seznam všech míst, odkud se něco odeslalo, spolu se souborem, řádkem a odkazem, který je otevře ve vašem editoru. Zvýrazní i BOM na začátku souboru, protože je to častá neviditelná příčina problému.
Ladění AJAXový požadavků
Tracy automaticky zachycuje AJAXové požadavky vytvořené pomocí jQuery nebo nativního API fetch. Požadavky
jsou v liště Tracy zobrazeny jako další řádky, což umožňuje snadné a pohodlné ladění AJAXu.
Pokud nechcete AJAXové požadavky zachycovat automaticky, můžete tuto funkci zakázat nastavením JavaScriptové proměnné:
window.TracyAutoRefresh = false;
Pro ruční monitorování specifických AJAX požadavků přidejte HTTP hlavičku X-Tracy-Ajax s hodnotou,
kterou vrátí Tracy.getAjaxHeader(). Zde je příklad použití s funkcí fetch:
fetch(url, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-Tracy-Ajax': Tracy.getAjaxHeader(),
}
})
Tento přístup umožňuje selektivní ladění AJAX požadavků.
Datové úložiště
Tracy umí zobrazit panely v Tracy baru a Bluescreeny pro AJAXové požadavky a přesměrovaní. Tracy si vytváří vlastní
session, data uchovává ve vlastních dočasných souborech a používá cookie tracy-session.
Tracy lze nakonfigurovat také tak, aby používala nativní PHP session, kterou nastartujeme ještě před zapnutím Tracy:
session_start();
Debugger::setSessionStorage(new Tracy\NativeSession);
Debugger::enable();
V případě, že nastartování session vyžaduje složitější inicializaci, můžete Tracy spustit ihned (aby mohla
zpracovat případné vzniklé chyby) a poté inicializovat obsluhu relace a nakonec informovat Tracy, že relace je připravena
k použití pomocí funkce dispatch():
Debugger::setSessionStorage(new Tracy\NativeSession);
Debugger::enable();
// následuje inicializace session
// a spuštění session
session_start();
Debugger::dispatch();
Funkce setSessionStorage() existuje od verze 2.9, předtím používala Tracy nativní PHP session vždy.
Vlastní scrubber
Scrubber je filtr, který zabraňuje úniku citlivých dat při dumpování, jako jsou hesla nebo přístupové údaje. Filtr
se volá pro každý prvek dumpovaného pole nebo objektu a vrací true, pokud je hodnota citlivá. V takovém
případě se místo hodnoty vypíše *****.
// zamezí vypsaní hodnot klíčů a properties jako `password`,
// `password_repeat`, `check_password`, `DATABASE_PASSWORD`, apod.
$scrubber = function(string $key, $value, ?string $class): bool
{
return preg_match('#password#i', $key) && $value !== null;
};
// použijeme jej pro všechny dumpy uvnitř BlueScreen
Tracy\Debugger::getBlueScreen()->scrubber = $scrubber;
Vlastní logger
Můžeme si vytvořit vlastní logger, který bude logovat chyby, nezachycené výjimky a také bude vyvolán metodou
Tracy\Debugger::log(). Logger implementuje rozhraní Tracy\ILogger.
use Tracy\ILogger;
class SlackLogger implements ILogger
{
public function log($value, $priority = ILogger::INFO)
{
// pošle request na Slack
}
}
A následně jej aktivujeme:
Tracy\Debugger::setLogger(new SlackLogger);
Pokud používáme plný Nette Framework, můžete jej nastavit v konfiguračním NEON souboru:
services:
tracy.logger: SlackLogger
Integrace monologu
Balíček Tracy poskytuje adaptér PSR-3, který umožňuje integraci monolog/monolog.
$monolog = new Monolog\Logger('main-channel');
$monolog->pushHandler(new Monolog\Handler\StreamHandler($logFilePath, Monolog\Logger::DEBUG));
$tracyLogger = new Tracy\Bridges\Psr\PsrToTracyLoggerAdapter($monolog);
Debugger::setLogger($tracyLogger);
Debugger::enable();
Debugger::log('info'); // writes: [<TIMESTAMP>] main-channel.INFO: info [] []
Debugger::log('warning', Debugger::WARNING); // writes: [<TIMESTAMP>] main-channel.WARNING: warning [] []
Integrace Sentry
Chyby můžete přeposílat do služby jako Sentry a přitom si ponechat vlastní logování Tracy. Trik spočívá v obalení původního loggeru: nový logger předá zprávu do Sentry a pak ji deleguje na ten předchozí, takže logování do souborů i e-mailové notifikace fungují dál.
use Sentry\Severity;
use Tracy\Debugger;
use Tracy\ILogger;
class SentryLogger implements ILogger
{
private ILogger $originalLogger;
public function __construct(string $dsn)
{
$this->originalLogger = Debugger::getLogger();
\Sentry\init(['dsn' => $dsn]);
}
public function log(mixed $value, string $level = self::INFO)
{
// pošle do Sentry
if ($severity = $this->getSeverity($level)) {
$value instanceof \Throwable
? \Sentry\captureException($value)
: \Sentry\captureMessage((string) $value, $severity);
}
// zachová původní logování Tracy (soubory, e-mail)
return $this->originalLogger->log($value, $level);
}
private function getSeverity(string $level): ?Severity
{
return match ($level) {
ILogger::DEBUG => Severity::debug(),
ILogger::INFO => Severity::info(),
ILogger::WARNING => Severity::warning(),
ILogger::ERROR, ILogger::EXCEPTION => Severity::error(),
ILogger::CRITICAL => Severity::fatal(),
default => null,
};
}
}
Aktivujete jej stejně jako kterýkoli jiný vlastní logger:
Debugger::setLogger(new SentryLogger('https://public@sentry.example.com/1'));
V Nette aplikaci jej místo toho zaregistrujte jako službu tracy.logger:
services:
tracy.logger: SentryLogger('https://public@sentry.example.com/1')
nginx
Pokud vám nefunguje Tracy na serveru nginx, nespíš je špatně nakonfigurovaný. Pokud je v konfiguraci něco jako:
try_files $uri $uri/ /index.php;
změňte to na:
try_files $uri $uri/ /index.php$is_args$args;