prosty logger z obsługą wyjątków

Kategoria: Javascript, HTML i CSS



griwes
27 sierpień 2009 - 15:29
Więc, prosty logger. Niby trywialna rzecz, ale czasem przydatna - funkcja zrzuca wyjątek; dlaczego nie dość, że musimy go obsłużyć, to jeszcze zapisać do logów? Dlaczego fakt zalogowania się użytkownika musimy zapisać, ręcznie wywołując fopen, fwrite i fclose? Tutaj wkracza moja klasa logger.

Uwaga: prawdopodobnie można to było napisać ładniej, krócej, czytelniej i funkcjonalniej - ale chciałem pokazać moją wizję takiej klasy.

Zaczynamy.

Plik logger.class.php
<?php class logger { private $logfolder, $extension, $eventtypes; function __construct($logfolder, $ext) { $this->logfolder = $logfolder; $this->extension = $ext; $this->eventtypes = array(); } Zmienne:
logger::logfolder przechowuje folder, w którym znajdują się pliki logów. Może być inicjowane w konstruktorze np. identyfikatorem sesji.
logger::extension przechowuje rozszerzenie plików logów (bez kropki!).

Konstruktora nie muszę chyba objaśniać.

public function addeventtype($type, $file) { $this->eventtypes[$type] = $file; } public function deleteeventtype($type) { unset($this->eventtypes[$type]); } public function modifyeventtype($type, $newfile) { if (isset($this->eventtypes[$type])) { $this->eventtypes[$type] = $newfile; return true; } return false; }
Coś, co pozwala powiązać tekst do zapisania do logów z plikiem typ zdarzenia. Przechowywane są one w tablicy logger::eventtypes. Powyższe funkcje (chyba są jasne dosyć) służą do dodawania, modyfikacji i usuwania typów zdarzenia.

public function writelog($eventtype, $message) { if (!isset($this->eventtypes[$eventtype]) && $this->eventtypes[$eventtype] == '') { return false; } $file = fopen($this->logfolder."/".$this->eventtypes[$eventtype].".".$this->extension, "a"); fwrite($file, date("d M Y, H:i:s: ").$message."\r\n"); fclose($file); }
Funkcja służąca do zapisania informacji do logów. Pierwszy argument jest identyfikatorem typu, drugi tekstem, który ma być zapisany w pliku. Jak na razie klasa pozwala użyć jednego wywołania zamiast 3, bardziej skomplikowanych. Ale to nie wszystko ;)

public function callfunction($callback, $parameter) { if (!is_callable($callback)) { return null; } try { return call_user_func_array($callback, $parameter); } catch (LoggerException $e) { $this->writelog($e->type(), $e->getmsg()); throw $e; } } } (Tak, to koniec klasy).

Powyższa funkcja pozwala wywołać dowolną funkcję (przekazaną w pierwszym parametrze) przez loggera. Jeżeli funkcja ta zrzuca wyjątek wyprowadzony z pokazanej kawałek dalej klasy, to logger najpierw zapisuje wyjątek do logów (dokładniej to zapisuje wiadomość wygenerowaną przez klasę wyjątku), a potem zrzuca wyjątek dalej. W ten sposób możemy normalnie obsługiwać swoje wyjątki i jednocześnie mieć je w logach.

class LoggerException extends Exception { protected $code, $type; function __construct($code) { $this->code = $code; } public function type() { return $this->type; } public function getmsg() { return $this->formatcode(); } } ?>Ta klasa jest na tyle prosta, że nie będę jej objaśniał; tyle tylko, że funkcja formatcode() musi być zdefiniowana w klasie potomnej. I jeszcze mały przykład działania (z wyjątkiem). Kod:<?php include "logger.class.php"; class Except extends LoggerException { function __construct($code) { parent::__construct($code); $this->type = 'logger'; } protected function formatcode() { return $this->code; } } $logger = new logger("logs", "log"); $logger->addeventtype("logger", "logger"); function s($logger, $callback, $parameter) { return $logger->callfunction($callback, $parameter); } function lolwut($lolwut) { echo $lolwut; throw new Except($lolwut." test"); } echo "<br />".s($logger, "lolwut", array("WOW!")); ?>
Link: http://www.griwes.in.../loggertest.php

I cały kod:<?php class logger { private $logfolder, $extension, $eventtypes; function __construct($logfolder, $ext) { $this->logfolder = $logfolder; $this->extension = $ext; $this->eventtypes = array(); } public function addeventtype($type, $file) { $this->eventtypes[$type] = $file; } public function deleteeventtype($type) { unset($this->eventtypes[$type]); } public function modifyeventtype($type, $newfile) { if (isset($this->eventtypes[$type])) { $this->eventtypes[$type] = $newfile; return true; } return false; } public function writelog($eventtype, $message) { if (!isset($this->eventtypes[$eventtype]) && $this->eventtypes[$eventtype] == '') { return false; } $file = fopen($this->logfolder."/".$this->eventtypes[$eventtype].".".$this->extension, "a"); fwrite($file, date("d M Y, H:i:s: ").$message."\r\n"); fclose($file); } public function callfunction($callback, $parameter) { if (!is_callable($callback)) { return null; } try { return call_user_func_array($callback, $parameter); } catch (LoggerException $e) { $this->writelog($e->type(), $e->getmsg()); throw $e; } } } class LoggerException extends Exception { protected $code, $type; function __construct($code) { $this->code = $code; } public function type() { return $this->type; } public function getmsg() { return $this->formatcode(); } } ?>

Na koniec: wiem, że nie jest to opisane tak, że nowicjusz zrozumie, ale może po prostu użyć :P


Podobne tematy:
Loeb: Ten pojedynek jest wyjątkowy
VB.NET 2.0 Zintegrowana obsługa wyjątków w aplikacji wielowątkowej.
obsluga wyjatkow
Obsługa COM i kilka innych prostych rzeczy
[C++ Builder 6] obsługa wyjątków
Prosty serwer DNS obsługujący maski dladomen.