Logowanie błędów jest kluczowym elementem minitoringu aplikacji. Przekonał się o tym chociażby każdy programista, który pracuje w firmie oferującej dodatkowo dla swoich produktów terminowy support.
Dzięki temu, że błędy są logowane jesteśmy w stanie szybko i czasami transparentnie wyeliminować bugi w aplikacji, tak że klient nawet się nie dowie o ich istnieniu:)
Jeśli Zend Framework jest podstawą twojego projektu oferuję Tobie bardzo wygodny i przejrzysty sposób na logowanie błędów aplikacji.
Potrzebna będzie jedna klasa, ponieważ aż się prosi aby system logowania błędów był ładowany jako resource, przez Zend_Application. Zarządzanie zasobów zaprezentowane w Zend Framework jest moim zdaniem rewelacyjne, ponieważ bardzo łatwo możemy wydzielić zasoby, dzięki czemu mamy wprowadzoną dodatkową logikę i ład w naszej aplikacji, ponadto dowolny zasób można łatwo i sprawnie włączyć/wyłączyć.
Przykładowa klasa mogłaby wygłądać następująco:
class Zextend_Application_Resource_Log extends Zend_Application_Resource_ResourceAbstract { public function init() { /** * Pobranie głównej konfiguracji. */ $config = $this->getBootstrap()->getContainer()->config; /** * Przygotowanie formatu zapisanej informacji. * * @example Postać zmiennej $config->format: * "%timestamp% %priorityName%: %message%" */ $format = new Zend_Log_Formatter_Simple($config->format . PHP_EOL); /** * Sprawdzanie, ktory sposób logowania błędów został włączony. * * @example Postać zmiennej $config->log->stream: * "../temporary/log/error.log" */ $logger = new Zend_Log(); if($config->log->file) { $logger->addWriter( $this->_getStreamWriter($format, $config->log->stream)); } if($config->log->stdoutput) { $logger->addWriter( $this->_getStreamWriter($format, 'php://output')); } if($config->log->firebug) { $logger->addWriter( $this->_getFirebugWriter($format)); } if($config->log->mail) { $logger->addWriter($this->_getMailWriter($config)); } /** * Używamy tego logger wszędzie w aplikacji. */ Zend_Registry::set( 'log', $logger ); return $logger; } /** * Zwraca obiekt zapisania informacja do Firebug. * * @param Zend_Log_Formatter_Simple $format * @return Zend_Log_Writer_Firebug */ private function _getFirebugWriter(Zend_Log_Formatter_Simple $format) { $writer = new Zend_Log_Writer_Firebug(); $writer->setFormatter($format); return $writer; } /** * Zwraca obiekt zapisania informacji w postaci emaila. * * @param Zend_Config_Ini $config * @return Zend_Log_Writer_Mail */ private function _getMailWriter(Zend_Config_Ini $config) { $mail = new Zend_Mail(); $mail->setDefaultTransport(new Zend_Mail_Transport_Smtp()); $mail->setFrom($config->email->from, $config->email->fromAlias); $mail->addTo($config->app->admin->email); $mail->addTo($config->app->webmaster->email); $mail->setSubject($config->app->name . ' - nastapil nieoczekiwany blad!'); $writer = new Zend_Log_Writer_Mail($mail); $writer->addFilter(Zend_Log::WARN); return $writer; } /** * Zwraca obiekt zapisania informacji do PHP stream. * * @param Zend_Log_Formatter_Simple $format * @param string $stream * @return Zend_Log_Writer_Stream */ private function _getStreamWriter(Zend_Log_Formatter_Simple $format, $stream = '') { $writer = new Zend_Log_Writer_Stream($stream); $writer->setFormatter($format); return $writer; } }
Jak widać oferuje ona możliwość logowania błędów na kilka sposobów: streaming do pliku, badź na ekran, JSON’em prosto do firebug’a (warunkiem odczytu jest zainstalowanie wtyczki FirePHP w Firefox) lub powiadomienie na email. W przykładzie część konfiguracji znajduje się w pliku /application/configs/application.ini, ktory ładowany jest poprzez Zend_Config_Ini do rejestru. Odczytany zostaje między innymi email do webmastera oraz do admina, czyli osób odpowiedzialnych za poprawne działanie aplikacji, ponadto zdefiniowane są takie parametry jak scieżka do pliku z blędami (error.log) czy też format komunikatu z błędem.
Oczywiście trzeba tę funkcjonalność dołączyć do projektu jako nowy zasób. Nic prostszego – w pliku konfiguracyjnym /application/configs/application.ini dodajemy kolejny resource do listy:
resources.types = "array()" resources.view = "array()" resources.navigation = "array()" resources.log = "array()"
Dodatkowo musimy zdefniować ustawienia, które załączają odpowiednei przekazanie informacji o błędzie. Czyli znów w /application/configs/application.ini dopisujemy:
log.file = true log.firebug = true log.mail = true log.stdoutput = true
Rzecz jasna korzystamy z odpowiedniego typu logowania w zależności od potrzeb. Bardzo wygodnie jest w trakcie tworzenia kodu, czy też jego testowania, otrzymywać komunikaty do konsoli FF, wykorzystując firePHP, dodatkowo wygodne jest odczytywanie błędów z pliku error.log – otwieramy konsole i dajemy polecenie:
# tail -f error.log
i mamy nasz system monitorujacy, w którym dokładnie zapisane jest gdzie wystąpił nieoczekiwany błąd (kupujemy telewizor LCD, który pokazuje te komunikaty przez cały czas
oczywiście żartuje
). Jeśli aplikacja jest już w wersji produkcyjnej to bardzo fajne jest rozwiązanie z przychodzącym emailem – można wtedy szybko interweniować.
Pamiętajmy jednak, że jeśli aplikacja jest już na produkcji, należy zablokować logowanie błędów do FireBug’a!!
Logowane błędy są tylko dla nas – developerów, adminów, …, i mają stanowić wskazówkę do szybkiego ich rozwiązania. Jeśli te informacje trafią do niepowołanych rąk to niestety możemy wskazać najsłabsze ogniwo naszej aplikacji, a tym samym stworzyć okazję do włamania się do niej np. hackerowi.
Kolejną sprawą jest miejsce, w którym nasz logger, trzymany w rejestrze, może dokonać zapisu błędu. Jednym z lepszym miejsc jest kontroler ErrorController.php i w nim metoda errorAction, na którą domyślnie przekierowany jest błąd. Oczywiście gdzie będzie odbywało się logowanie błędów utożsamiony z tą linijką kodu:
if (Zend_Registry::isRegistered('log')) { $logger = Zend_Registry::get('log'); if (!is_null($this->_error)) { $logger->log( $this->_error->exception->getMessage() . "\n\n" . $this->_error->exception->getTraceAsString(), Zend_Log::ERR ); } }
jest uzależnione od potrzeb aplikacji i zaprojektowania jej przez programistę.
Taki sposób logowania błędów można implementować w każdym projekcie – nie tylko opartym o Zend Framework. Po drobnych modyfikacjach, korzystając tylko z kilku komponentów (w wersji ZF 1.10.6), Log(20 plików), Wildfire (8 plików), Json (14 plików), Config (8 plików) + Exception.php, można stworzyć taki sam system logowania błędów.
Comments
Leave a comment Trackback