Zaczynamy z Tracy

Biblioteka Tracy jest użytecznym codziennym pomocnikiem programisty PHP. Pomoże Ci:

  • szybko wykrywać i naprawiać błędy
  • logować błędy
  • wypisywać zmienne
  • mierzyć czas skryptów i zapytań do bazy danych
  • monitorować zużycie pamięci

PHP jest językiem stworzonym do popełniania trudnych do wykrycia błędów, ponieważ daje programistom znaczną swobodę. Tym cenniejsze jest narzędzie do debugowania Tracy. Wśród narzędzi diagnostycznych dla PHP stanowi absolutną czołówkę.

Jeśli dziś spotykasz się z Tracy po raz pierwszy, uwierz, że Twoje życie zacznie dzielić się na to przed Tracy i to z nią. Witaj w lepszej części!

Instalacja

Najlepszym sposobem na zainstalowanie Tracy jest pobranie najnowszego pakietu lub użycie Composera:

composer require tracy/tracy

Możesz również pobrać cały pakiet jako plik tracy.phar.

Użycie

Aktywujemy Tracy, wywołując metodę Tracy\Debugger::enable() jak najwcześniej na początku programu, przed wysłaniem jakiegokolwiek wyjścia:

use Tracy\Debugger;

require 'vendor/autoload.php'; // ewentualnie tracy.phar

Debugger::enable();

Pierwszą rzeczą, którą zauważysz na stronie, jest Pasek Tracy w prawym dolnym rogu. Jeśli go nie widzisz, może to oznaczać, że Tracy działa w trybie produkcyjnym. Tracy ze względów bezpieczeństwa jest widoczna tylko na localhost. Aby przetestować, czy działa, możesz tymczasowo przełączyć ją w tryb deweloperski za pomocą parametru Debugger::enable(Debugger::Development).

Pasek Tracy

Pasek Tracy to pływający panel, który pojawia się w prawym dolnym rogu strony. Możemy go przesuwać myszą, a po ponownym załadowaniu strony zapamięta swoją pozycję.

Do Paska Tracy można dodawać kolejne przydatne panele. Wiele z nich znajdziesz w dodatkach, a nawet możesz napisać własne.

Jeśli nie chcesz wyświetlać Paska Tracy, ustaw:

Debugger::$showBar = false;

Wizualizacja błędów i wyjątków

Z pewnością dobrze wiesz, jak PHP zgłasza błędy: do kodu źródłowego strony wypisuje coś takiego:

Parse error:  syntax error, unexpected '}' in HomePresenter.php on line 15

lub w przypadku nieprzechwyconego wyjątku:

Fatal error:  Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100
Stack trace:
#0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array)
#1 /sandbox/app/Forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array)
#2 /sandbox/app/Presentation/Sign/SignPresenter.php(21): App\Forms\SignFormFactory->create()
#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presentation\Sign\SignPresenter->createComponentSignInForm('signInForm')
#4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm')
#5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php on line 100

Zorientowanie się w takim wyniku nie jest łatwe. Jeśli włączymy Tracy, błąd lub wyjątek zostanie wyświetlony w zupełnie innej formie:

Komunikat o błędzie dosłownie krzyczy. Widzimy fragment kodu źródłowego z podświetloną linią, w której wystąpił błąd, a informacja Call to undefined method Nette\Http\User::isLogedIn() jasno wyjaśnia, o jaki błąd chodzi. Cała strona jest ponadto interaktywna, możemy klikać, aby uzyskać więcej szczegółów. Spróbuj.

A wiesz co? W ten sposób przechwytuje i wyświetla nawet błędy krytyczne (fatal errors). Bez konieczności instalowania jakichkolwiek rozszerzeń.

Błędy takie jak literówka w nazwie zmiennej lub próba otwarcia nieistniejącego pliku generują komunikaty poziomu E_NOTICE lub E_WARNING. Można je łatwo przeoczyć w grafice strony, a nawet mogą być w ogóle niewidoczne (chyba że spojrzysz w kod strony).

Lub mogą być wyświetlane tak samo jak błędy:

Debugger::$strictMode = true; // wyświetl wszystkie błędy
Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // wszystkie błędy oprócz powiadomień o przestarzałości (deprecate)

Uwaga: Tracy po aktywacji zmienia poziom raportowania błędów na E_ALL. Jeśli chcesz zmienić tę wartość, zrób to po wywołaniu enable().

Tryb deweloperski vs produkcyjny

Jak widzisz, Tracy jest dość gadatliwa, co można docenić w środowisku deweloperskim, podczas gdy na serwerze produkcyjnym spowodowałoby to katastrofę. Tam bowiem żadne informacje debugowania nie mogą być wyświetlane. Dlatego Tracy dysponuje autodetekcją środowiska i jeśli uruchomimy przykład na serwerze produkcyjnym, błąd zamiast wyświetlenia zostanie zalogowany, a odwiedzający zobaczy tylko zrozumiały dla użytkownika komunikat:

Tryb produkcyjny tłumi wyświetlanie wszystkich informacji debugowania, które wysyłamy za pomocą dump(), oraz oczywiście wszystkich komunikatów błędów generowanych przez PHP. Jeśli więc zapomniałeś w kodzie jakiegoś dump($obj), nie musisz się martwić, na serwerze produkcyjnym nic się nie wyświetli.

Jak działa autodetekcja trybu? Tryb jest deweloperski, jeśli aplikacja jest uruchomiona na localhost (tj. adres IP 127.0.0.1 lub ::1) i nie ma obecnego proxy (tj. jego nagłówka HTTP). W przeciwnym razie działa w trybie produkcyjnym.

Jeśli chcemy włączyć tryb deweloperski również w innych przypadkach, na przykład dla programistów uzyskujących dostęp z określonego adresu IP, podajemy go jako parametr metody enable():

Debugger::enable('23.75.345.200'); // można podać również tablicę adresów IP

Zdecydowanie zalecamy łączenie adresu IP z ciasteczkiem (cookie). W ciasteczku tracy-debug zapisujemy tajny token, np. secret1234, i w ten sposób aktywujemy tryb deweloperski tylko dla programistów uzyskujących dostęp z określonego adresu IP, którzy mają w ciasteczku wspomniany token:

Debugger::enable('secret1234@23.75.345.200');

Tryb deweloperski/produkcyjny możemy również ustawić bezpośrednio, używając stałej Debugger::Development lub Debugger::Production jako parametru metody enable().

Jeśli używasz Nette Framework, zobacz, jak ustawić tryb dla niego a ten zostanie następnie użyty również dla Tracy.

Logowanie błędów

W trybie produkcyjnym Tracy automatycznie rejestruje wszystkie błędy i przechwycone wyjątki w logu tekstowym. Aby logowanie mogło się odbywać, musimy ustawić bezwzględną ścieżkę do katalogu logów w zmiennej $logDirectory lub przekazać ją jako drugi parametr metody enable():

Debugger::$logDirectory = __DIR__ . '/log';

Logowanie błędów jest przy tym niezwykle przydatne. Wyobraź sobie, że wszyscy użytkownicy Twojej aplikacji są w rzeczywistości beta testerami, którzy za darmo wykonują doskonałą pracę w znajdowaniu błędów, a Ty popełniłbyś głupstwo, gdybyś ich cenne raporty wyrzucił bez uwagi do kosza.

Jeśli potrzebujemy zalogować własną wiadomość lub przechwycony przez nas wyjątek, użyjemy do tego metody log():

Debugger::log('Wystąpił nieoczekiwany błąd'); // wiadomość tekstowa

try {
	kritickaOperace();
} catch (Exception $e) {
	Debugger::log($e); // można logować również wyjątek
	// lub
	Debugger::log($e, Debugger::ERROR); // wyśle również powiadomienie e-mail
}

Jeśli chcesz, aby Tracy logowała błędy PHP takie jak E_NOTICE lub E_WARNING ze szczegółowymi informacjami (raport HTML), ustaw Debugger::$logSeverity:

Debugger::$logSeverity = E_NOTICE | E_WARNING;

Dla prawdziwego profesjonalisty log błędów jest kluczowym źródłem informacji i chce on być natychmiast informowany o każdym nowym błędzie. Tracy wychodzi mu naprzeciw, potrafi bowiem informować o nowym wpisie w logu za pomocą e-maila. Dokąd wysyłać e-maile, określamy zmienną $email:

Debugger::$email = 'admin@example.com';

Jeśli używasz całego Nette Framework, można to i inne ustawienia skonfigurować w pliku konfiguracyjnym.

Aby jednak nie zalała Ci skrzynki e-mailowej, zawsze wysyła tylko jedną wiadomość i tworzy plik email-sent. Programista po otrzymaniu powiadomienia e-mail sprawdza log, naprawia aplikację i usuwa plik monitorujący, co ponownie aktywuje wysyłanie e-maili.

Otwieranie w edytorze

Podczas wyświetlania strony błędu można kliknąć na nazwy plików, a otworzą się one w Twoim edytorze z kursorem na odpowiedniej linii. Można również tworzyć pliki (akcja create file) lub naprawiać w nich błędy (akcja fix it). Aby to działało, wystarczy skonfigurować przeglądarkę i system.

Obsługiwane wersje PHP

Tracy kompatybilne z PHP
Tracy 2.10 – 3.0 PHP 8.0 – 8.4
Tracy 2.9 PHP 7.2 – 8.2
Tracy 2.8 PHP 7.2 – 8.1
Tracy 2.6 – 2.7 PHP 7.1 – 8.0
Tracy 2.5 PHP 5.4 – 7.4
Tracy 2.4 PHP 5.4 – 7.2

Dotyczy ostatniej wersji poprawkowej (patch).

Porty

To jest lista nieoficjalnych portów dla innych frameworków i CMS: