Tarifler

Content Security Policy

Siteniz Content Security Policy (CSP) kullanıyorsa, Tracy'nin düzgün çalışması için script-src yönergesine 'nonce-<value>' ve 'strict-dynamic' eklemeniz gerekir. Bazı üçüncü taraf eklentileri ek yönergeler isteyebilir. style-src yönergesinde nonce desteklenmez; bu yönergeyi kullanıyorsanız 'unsafe-inline' eklemeniz gerekir, ama üretim kipinde bundan kaçınılmalıdır.

Nette Framework için yapılandırma örneği:

http:
	csp:
		script-src: [nonce, strict-dynamic]

Saf PHP'de örnek:

$nonce = base64_encode(random_bytes(20));
header("Content-Security-Policy: script-src 'nonce-$nonce' 'strict-dynamic';");

Daha Hızlı Yükleme

Temel tümleştirme dolaysızdır. Ancak web sayfanızda yavaş yüklenen engelleyici betikler varsa, bunlar Tracy'nin yüklenmesini yavaşlatabilir. Çözüm, şablonunuzda <?php Tracy\Debugger::renderLoader() ?> satırını tüm betiklerden önce koymaktır:

<!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>

Çıktının Kaynağını Bulma

Hiç Cannot modify header information – headers already sent hatasıyla karşılaştınız mı? Bu hata, kodunuz bir HTTP header ayarlamadan ya da bir oturum başlatmadan önce tarayıcıya bir şey gönderildiğinde (başıboş bir boşluk, boş bir satır ya da bir dosyanın başındaki BOM) ortaya çıkar. Suçluyu bulmak yorucudur.

Tracy\OutputDebugger yardım eder. Onu programınızın en başında etkinleştirin:

Tracy\OutputDebugger::enable();

Tüm çıktıyı izler ve sayfanın sonunda, çıktının gönderildiği her yerin listesini; dosya, satır ve düzenleyicinizde açan bir bağlantıyla birlikte yazdırır. Bir dosyanın başındaki bayt sırası işareti (BOM) de vurgulanır; çünkü sorunun yaygın ve görünmez bir nedenidir.

AJAX İsteklerinde Hata Ayıklama

Tracy, jQuery ya da yerleşik fetch API'siyle yapılan AJAX isteklerini otomatik olarak yakalar. Bu istekler Tracy çubuğunda ek satırlar olarak görüntülenir ve AJAX'ta kolay ve rahat hata ayıklamayı sağlar.

AJAX isteklerinin otomatik yakalanmasını istemiyorsanız, bu özelliği şu JavaScript değişkenini ayarlayarak kapatabilirsiniz:

window.TracyAutoRefresh = false;

Belirli AJAX isteklerini elle izlemek için, Tracy.getAjaxHeader() metodunun döndürdüğü değere sahip X-Tracy-Ajax HTTP header'ını ekleyin. fetch fonksiyonuyla kullanımına bir örnek:

fetch(url, {
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'X-Tracy-Ajax': Tracy.getAjaxHeader(),
    }
})

Bu yaklaşım, AJAX isteklerinde seçmeli hata ayıklamaya olanak tanır.

Veri Saklama

Tracy, AJAX istekleri ve yönlendirmeler için Tracy çubuğu panellerini ve Bluescreen'leri gösterebilir. Tracy kendi oturumlarını oluşturur, verileri kendi geçici dosyalarında saklar ve bir tracy-session çerezi kullanır.

Tracy, PHP'nin yerleşik oturumunu kullanacak şekilde de yapılandırılabilir; bu oturum, Tracy etkinleştirilmeden önce başlatılmalıdır:

session_start();
Debugger::setSessionStorage(new Tracy\NativeSession);
Debugger::enable();

Oturum başlatmak daha karmaşık bir hazırlık gerektiriyorsa, Tracy'yi hemen başlatabilir (böylece oluşan hataları ele alabilir), sonra oturum işleyicisini hazırlayabilirsiniz. En sonunda dispatch() fonksiyonuyla Tracy'ye oturumun kullanıma hazır olduğunu bildirin:

Debugger::setSessionStorage(new Tracy\NativeSession);
Debugger::enable();

// ardından oturum hazırlığı
// ve oturumu başlat
session_start();

Debugger::dispatch();

setSessionStorage() fonksiyonu 2.9 sürümünden beri vardır; ondan önce Tracy her zaman PHP'nin yerleşik oturumunu kullanıyordu.

Özel Scrubber

Scrubber, parola ya da kimlik bilgileri gibi hassas verilerin dökümlerden sızmasını önleyen bir filtredir. Filtre, dökülen dizinin ya da nesnenin her öğesi için çağrılır ve değer hassassa true döndürür. Bu durumda değer yerine ***** yazdırılır.

// `password`, `password_repeat`, `check_password`, `DATABASE_PASSWORD` gibi
// anahtarların ve özelliklerin değerlerinin dökülmesini önler
$scrubber = function(string $key, $value, ?string $class): bool
{
	return preg_match('#password#i', $key) && $value !== null;
};

// BlueScreen içindeki tüm dökümlerde kullan
Tracy\Debugger::getBlueScreen()->scrubber = $scrubber;

Özel Logger

Hataları ve yakalanmamış istisnaları günlükleyecek, ayrıca Tracy\Debugger::log() metodunca çağrılacak özel bir logger yazabiliriz. Logger, Tracy\ILogger arayüzünü uygulamalıdır.

use Tracy\ILogger;

class SlackLogger implements ILogger
{
	public function log($value, $priority = ILogger::INFO)
	{
		// Slack'e bir istek gönderir
	}
}

Ve sonra onu etkinleştiririz:

Tracy\Debugger::setLogger(new SlackLogger);

Nette Framework'ün tamamını kullanıyorsanız, onu NEON yapılandırma dosyasında ayarlayabilirsiniz:

services:
	tracy.logger: SlackLogger

Monolog Tümleştirmesi

Tracy paketi bir PSR-3 adaptörü sunar; bu da monolog/monolog tümleştirmesine olanak tanır.

$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'); // yazar: [<TIMESTAMP>] main-channel.INFO: info [] []
Debugger::log('warning', Debugger::WARNING); // yazar: [<TIMESTAMP>] main-channel.WARNING: warning [] []

Sentry Tümleştirmesi

Tracy'nin kendi günlüklemesini korurken hataları Sentry gibi bir servise iletebilirsiniz. Fikir, özgün logger'ı sarmalamaktır: yeni logger mesajı Sentry'ye aktarır ve sonra bir öncekine devreder; böylece dosya günlükleri ve e-posta bildirimleri çalışmayı sürdürür.

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)
	{
		// Sentry'ye gönder
		if ($severity = $this->getSeverity($level)) {
			$value instanceof \Throwable
				? \Sentry\captureException($value)
				: \Sentry\captureMessage((string) $value, $severity);
		}

		// Tracy'nin özgün günlüklemesini koru (dosyalar, e-posta)
		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,
		};
	}
}

Onu, başka herhangi bir özel logger gibi etkinleştirin:

Debugger::setLogger(new SentryLogger('https://public@sentry.example.com/1'));

Bir Nette uygulamasında ise onu tracy.logger servisi olarak kaydedin:

services:
	tracy.logger: SentryLogger('https://public@sentry.example.com/1')

nginx

Tracy nginx'te çalışmıyorsa, büyük olasılıkla yanlış yapılandırılmıştır. Şuna benzer bir şey varsa:

try_files $uri $uri/ /index.php;

onu şununla değiştirin:

try_files $uri $uri/ /index.php$is_args$args;