Hallo zusammen,
ich denke gerade über einen Exception-Behandlungs-Mechanismus nach, der ein automatisches Logging beinhaltet.
Mal das Grundproblem:
Es geht um eine größere Anwendung, in der Fehler je nach Loglevel in eine Log-Datei geschrieben werden. Um ein bessere Fehleranalyse machen zu können, würde ich gerne eine Basis-Exception entwickeln, die bereits ein integriertes Logging hat und entsprechende Informationen zur Exception in eine "exceptions.log" schreibt, wenn ich den Loglevel auf "Debug" stelle.
Nun stellt sich die Frage: Wie bekomme ich "den Logger" von außen möglichst elegant und ohne Abhängigkeiten zu erzeugen in meine Exception-Klasse bzw. das Objekt?
Ich möchte die Basisfunktionalität der Exception eigentlich komplett erhalten, das heißt keine Parameter in den Konstruktor hinzufügen oder weglassen, aber genauso wenig möchte ich beim Werfen einer Exception erst eine Zwischenvariable nutzen, um diese zu werfen.
Mal ein Beispiel, um zu verdeutlichen, was ich meine:
Der Code ist übrigens nur als Beispiel gedacht, er funktioniert wahrscheinlich nicht.
Macht mein Vorhaben überhaupt Sinn?
Weitere Meinungen?
ich denke gerade über einen Exception-Behandlungs-Mechanismus nach, der ein automatisches Logging beinhaltet.
Mal das Grundproblem:
Es geht um eine größere Anwendung, in der Fehler je nach Loglevel in eine Log-Datei geschrieben werden. Um ein bessere Fehleranalyse machen zu können, würde ich gerne eine Basis-Exception entwickeln, die bereits ein integriertes Logging hat und entsprechende Informationen zur Exception in eine "exceptions.log" schreibt, wenn ich den Loglevel auf "Debug" stelle.
Nun stellt sich die Frage: Wie bekomme ich "den Logger" von außen möglichst elegant und ohne Abhängigkeiten zu erzeugen in meine Exception-Klasse bzw. das Objekt?
Ich möchte die Basisfunktionalität der Exception eigentlich komplett erhalten, das heißt keine Parameter in den Konstruktor hinzufügen oder weglassen, aber genauso wenig möchte ich beim Werfen einer Exception erst eine Zwischenvariable nutzen, um diese zu werfen.
Mal ein Beispiel, um zu verdeutlichen, was ich meine:
PHP-Code:
<?php
namespace Andreas;
// Dummy Logger, eigentlich PSR-3
class Logger {
public function debug($message) {
echo $message;
}
}
// Hilfsklasse zur Behandlung von Exceptions
class ExceptionHandler {
private $logger;
private static $instance;
private function __construct() {
}
public static function singleton() {
if(self::$instance === null) {
self::$instance = new ExceptionHandler();
}
return self::$instance;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
public function handle(\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
}
// Variante 1: Zusätzlicher Konstruktor-Parameter
class ExceptionVariante1 extends \Exception
{
public function __construct($message='', $code=0, Exception $previous = null, ExceptionHandler $handler=null)
{
parent::__construct($message, $code, $previous);
if($handler) {
$handler->handle($this);
}
}
}
// Variante 2: Mit externen Abhängigkeiten
class ExceptionVariante2 extends \Exception
{
public function __construct($message='', $code=0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
ExceptionHandler::singleton()->handle($this);
}
}
$logger = new Logger();
$exceptionHandler = ExceptionHandler::singleton();
$exceptionHandler->setLogger($logger);
// Variante 1: 4. Parameter => möchte ich eigentlich vermeiden, da die Signatur der Standardexception so bleiben soll, wie sie ist
try {
throw new ExceptionVariante1('variante 1', 1, null, $exceptionHandler);
} catch (Exception $e) {
}
// Variante 2: Eine Abhängigkeit für ExceptionHandler innerhalb der Exception-Klasse => auch nicht sehr elegant
try {
throw ExceptionVariante2('variante 2', 2);
} catch (Exception $e) {
}
// Variante 3: Ohne zusätzliche Exception mit Handler-Zeile im Catch, gefällt mir auch nicht richtig
try {
throw new \Exception('variante 3', 3);
} catch (Exception $e) {
$exceptionHandler->handle($e);
}
Macht mein Vorhaben überhaupt Sinn?
Weitere Meinungen?
Kommentar