19 Logging
Pakete der Kategorie Logging beschäftigen sich mit der Protokollierung von Ereignissen bzw. mit der Analyse und Verarbeitung von Log-Dateien. Leider funktioniert hier momentan nur das Paket Log.
19.1 Log 

Besprochene Version: 1.8.7 | Lizenz: PHP-Lizenz 2.02 |
Klassendatei(en): Log.php |
Das Paket Log ist ein sehr flexibles Paket zum Generieren von Log-Einträgen. Der Begriff »Log-Einträge« wird schnell mit Dateien in Verbindung gebracht. In diesem Fall können die Fehlermeldungen aber nicht nur in Dateien abgelegt, sondern auch per E-Mail verschickt, auf dem Bildschirm ausgegeben oder in einer Datenbank abgelegt werden. Auch die Nutzung eines Syslog-Dämons ist möglich.
Das Paket kennt verschiedene Möglichkeiten, um ein Objekt zu instanziieren. Ich werde hier auf die Methode factory() zurückgreifen. Sie bekommt als ersten Parameter den Namen des Handlers übergeben, der die Log-Meldung verarbeitet. Nur dieser erste Parameter ist obligatorisch. Abhängig von dem verwendeten Log-Handler ist es aber meist sinnvoll, zumindest noch den zweiten Parameter zu nutzen. Hierbei handelt es sich um den Namen der »Log-Ressource«. Das ist zum Beispiel der Name einer Tabelle, in der die Daten abgelegt werden sollen, oder der Name der Datei, die zum Speichern genutzt werden soll. Somit ist diese Information vom Typ des Handlers abhängig. Der dritte Parameter ist ein frei definierbarer String, mit dem jeder Eintrag im Log ergänzt wird, um ihn einer Applikation oder einer Datei zuordnen zu können. Dieser wird auch Ident-String genannt. Mit dem vierten Parameter übergeben Sie der Factory-Methode spezifische Informationen, die benötigt werden, um eine Verbindung zum Speicherplatz aufzubauen. Der fünfte und letzte Parameter bezeichnet schließlich den Log-Level, wozu Sie später noch mehr erfahren werden.
Eine solche Instanziierung könnte beispielsweise so aussehen:
Bevor ich zu den Funktionalitäten komme, möchte ich auf die wichtigsten Handler eingehen.
- Dateien Um die Log-Meldungen in einer Datei abzulegen, nutzen Sie als ersten Parameter der Factory-Methode 'file'. Der zweite Parameter ist der Name der Datei, die genutzt werden soll. Soll die Datei in einem speziellen Pfad abgelegt werden, geben Sie diesen direkt mit an. Existiert das Unterverzeichnis nicht, wird es neu angelegt. Bitte beachten Sie, dass die Applikation natürlich über Schreibrechte auf das Verzeichnis verfügen muss, in dem das Unterverzeichnis bzw. die Datei neu angelegt werden sollen. Übergeben Sie keinen Dateinamen, wird php.log als Name genutzt.
-
- Der vierte Parameter, das Array mit Optionen, darf über die folgenden Schlüssel verfügen: Mit 'append' legen Sie fest, ob die Einträge immer an bestehende Einträge angehängt werden, was sich aus dem Standardwert true ergibt. Mit false würden alte Einträge immer überschrieben, was aber nicht sehr sinnvoll erscheint. Der Schlüssel 'mode' kann die Information enthalten, welche Unix-Rechtemaske für die Datei genutzt werden soll. Der Standard ist 0644. Mit dem Schlüssel 'lineFormat' können Sie definieren, wie ein Eintrag in der Log-Datei aufzubauen ist. Der String, den Sie übergeben, darf dabei aus den Elementen %{timestamp}, %{ident}, %{priority} und %{message} bestehen. Diese werden in der Fehlermeldung dann durch die Zeit, den Ident-String, den Sie an die Factory-Methode übergeben haben, die Priorität und die eigentliche Fehlermeldung ersetzt. Zusätzlich können Sie auch noch freie Texte wie Klammern und Ähnliches in dem String nutzen.
- Datenbank mit PEAR::DB Möchten Sie die Daten in einer Datenbank ablegen, übergeben Sie der Factory-Methode als ersten Parameter den String 'sql'. Der Zugriff auf die Datenbank erfolgt hierbei über PEARs Datenbank-Abstraktionslayer DB. Die Datenbanktabelle, in der die Daten abgelegt werden, könnte mit diesem Befehl angelegt werden:
- SQLite Die Datenbank SQLite, die mit PHP 5 eingeführt wurde, können Sie mit dem String-Literal 'sqlite' als Datenablage einbinden. Dies bietet den Vorteil, das Sie sich keine Gedanken darüber machen müssen, ob eine entsprechende Datenbank vorhanden ist. Allerdings kann es bei Servern mit vielen Besuchern unter Umständen zu Zugriffs- oder Performance-Problemen kommen, da für jeden Log-Eintrag ein SQLite-Prozess gestartet werden muss.
-
- Der vierte Parameter verhält sich in diesem Fall ein wenig anders. Besteht bereits eine Datenbankverbindung, die Sie nutzen wollen, übergeben Sie diese direkt, ohne ein Array zu verwenden. Besteht keine Datenbankverbindung, können Sie die Felder 'mode' und 'persistent' nutzen. Im ersten Element können Sie eine Unix-Rechtemaske übergeben, die für die Datenbankdatei verwendet wird. [Zurzeit wird dieser Parameter noch nicht von SQLite ausgewertet. ] Enthält das zweite Feld den Wert true, so wird eine persistente Verbindung aufgebaut.
- E-Mail Sollen die Fehlermeldungen per E-Mail verschickt werden, können Sie als ersten Parameter 'mail' übergeben. Der zweite Parameter ist die E-Mail-Adresse des Empfängers. Das Array, das an vierter Stelle übergeben wird, sollte mindestens aus den Elementen 'from' und 'subject' bestehen, mit denen der Absender und die Betreffzeile der E-Mail übergeben werden. Des Weiteren können Sie im Feld 'preamble' einen Text übergeben, der dem eigentlichen Inhalt der Mail vorangestellt wird. Eine Beeinflussung der Header ist nicht vorgesehen. Das Paket nutzt die PHP-Funktion mail(), um die Daten zu versenden. Sollte Ihre Angabe des Absenders ignoriert werden, kann das daran liegen, dass der genutzte Mail Transport Agent diese Angabe ignoriert.
- Display Der Display-Handler dient zur direkten Ausgabe von Fehlermeldungen an den Browser. Um ihn zu nutzen, übergeben Sie 'display' als ersten Parameter. Das Array zum Übergeben der Optionen ist in diesem Fall sehr überschaubar, da nur zwei Felder unterstützt werden. Mit 'error_prepend' können Sie einen String übergeben, der vor dem eigentlichen Fehler ausgegeben wird, und der Inhalt von 'error_append' wird hinter der Fehlermeldung ausgegeben. Die Idee ist, dass Sie auf diesem Weg den Fehler mithilfe von entsprechenden HTML-Befehlen farblich hervorheben können, um ihn auf der eigentlichen Seite besser erkennen zu können.
- Window Der Window-Handler ist ideal zur Fehlersuche. Eine direkte Ausgabe einer Fehlermeldung mit Display kann problematisch werden, da der Fehler unter Umständen nicht im Browser zu sehen ist, wenn er an der falschen Stelle des HTML-Codes ausgegeben wird.
-
- Der Window-Handler, für dessen Nutzung Sie an erster Stelle der Parameter-Liste den Text 'win' angeben müssen, gibt die Fehler in einem zusätzlichen Fenster aus. Somit können Sie sicher sein, dass Sie alle Fehler sehen. Allerdings setzt dieser Handler voraus, dass JavaScript eingeschaltet ist. Es besonders interessantes Feature dabei ist, dass alle Fehler immer nur in ein Fenster ausgegeben werden, so dass Sie nicht in einer Flut von Fenstern untergehen.
-
- Der dritte Parameter ist wieder ein frei wählbarer Text und der vierte Parameter das schon bekannte Array mit Optionen. Mit dem Element 'title' können Sie einen Text übergeben, der als Fenstertitel genutzt werden soll. Der Schlüssel 'colors' verweist auf ein Array, mit dem Sie den einzelnen Log-Leveln Farben zuordnen können. Da die Farben nicht immer geschickt gewählt sind, macht es Sinn, hier andere Farben zu nutzen. Den Aufbau des Arrays entnehmen Sie bitte Listing 19.1.
require_once('Log.php'); $farben = array( PEAR_LOG_EMERG => 'red', PEAR_LOG_ALERT => 'orange', PEAR_LOG_CRIT => 'red', PEAR_LOG_ERR => 'green', PEAR_LOG_WARNING => 'blue', PEAR_LOG_NOTICE => 'indigo', PEAR_LOG_INFO => 'violet', PEAR_LOG_DEBUG => 'black' ); $opts = array ( 'title' => 'Fehlermeldungen', 'colors' => $farben ); $log = Log::factory('win','errorlog','SHOP',$opts); $log->log('Nur ein Test',PEAR_LOG_CRIT);
Listing 19.1 Nutzung des Window-Handlers
Abbildung 19.1 Fenster mit Fehlermeldungen
- Composite Der Composite-Handler ist in der Lage, mehrere normale Handler zu kombinieren. Somit ist es kein Problem, eine E-Mail mit der Fehlermeldung zu versenden und gleichzeitig einen Datenbankeintrag zu generieren.
-
- Um den Composite-Handler zu nutzen, leiten Sie zwei oder mehr Log-Objekte mit den gewünschten Handlern ab. Danach leiten Sie dann ein Log-Objekt ab, indem Sie der Factory-Methode den String 'composite' übergeben. Die Factory-Methode akzeptiert in diesem Fall keine weiteren Parameter. Dem so erstellten Log-Objekt fügen Sie die Log-Objekte, die Sie nutzen wollen, mit addChild() hinzu.
// Log-Objekte ableiten $log_sql = Log::factory('sql','errorlog','SHOP',$opts); $log_mail = Log::factory('mail', 'error@example.com','SHOP',$opts); // Composite-Objekt ableiten $log_comp = Log::factory('composite'); // Log-Objekte an das Composite-Objekt uebergeben $log_comp->addChild($log_sql); $log_comp->addChild($log_mail); // Fehlermeldung per E-Mail und als DB-Eintrag $log_comp->log('Fehlermeldung',PEAR_LOG_CRIT);
Wie gesagt sind das nicht alle Handler. Es sind nur die aus meiner Sicht hilfreichsten und wichtigsten. Es ist weiterhin auch möglich, die Meldungen auf einem Syslog-Server zu speichern, sie an einen MCAL-Server zu übergeben oder das Error-Log von PHP zu nutzen. Weitere Informationen zur Nutzung dieser Handler finden Sie auf der externen Homepage des Pakets unter http://www.indelible.org/pear/Log/guide.php.
Die Methode log(), um eine neue Fehlermeldung zu generieren, kennen Sie ja schon. Diese bekommt die Fehlermeldung sowie eine Konstante übergeben, die den Log-Level, also die Schwere des Fehlers definiert. Die acht definierten Level finden Sie in Tabelle 19.1.
Diese verschiedenen Log-Level erlauben Ihnen eine feine Abstufung, um auf Ereignisse zu reagieren. Die Beschreibung soll Ihnen nur ein Anhaltspunkt sein, wie die einzelnen Level einzustufen sind. Innerhalb der Tabelle werden die Fehler also von unten nach oben kritischer.
In der Spalte Methode finden Sie noch Kurzformen, um in der entsprechenden Kategorie einen Eintrag zu generieren. Diese Methoden bekommen dann immer nur die eigentliche Fehlermeldung als Parameter übergeben.
ersetzen. Welche Vorgehensweise Sie nutzen, bleibt Ihnen überlassen. Ein Log-Ereignis mit dem Status PEAR_LOG_DEBUG ist nur für das Debugging gedacht, und auch ein PEAR_LOG_INFO bedroht das System nicht unbedingt. Daher kann es sinnvoll sein, solche Meldungen während der Entwicklung auszugeben. Sie nach der Entwicklung aber alle wieder von Hand zu entfernen wäre sehr aufwändig. Daher können Sie mit so genannten Masken arbeiten. Mit ihnen können Sie definieren, welche Log-Level ignoriert werden sollen und welche wirklich zu einer Aktion führen.
Eine Maske generieren Sie durch Aufruf der statischen Methode MASK() oder UPTO(). Diese Methoden bekommen eine der Log-Level-Konstanten aus Tabelle 19.1 übergeben. MASK() generiert eine Maske, die sich immer nur auf den Level bezieht, der ihr übergeben wird. UPTO() generiert hingegen eine Maske, die alle Level bis zu dem, der übergeben wurde, umfasst. Die beiden Zeilen
sorgen dafür, dass eine Maske berechnet wird, die definiert, dass alle Fehler bis zum Level PEAR_LOG_ERR protokolliert werden. Fehler in darüber liegenden Leveln werden ignoriert. Das würde natürlich wenig Sinn machen, da das dazu führen würde, dass gerade die wichtigen Ereignisse ignoriert würden. Sie können diese Masken aber mithilfe der Bit-Operatoren ^ und | kombinieren. Mit ^ können Sie bestimmte Level ausschließen, und mit | können Sie einzelne Level kombinieren.
In diesem Zusammenhang sind die Konstanten PEAR_LOG_ALL und PEAR_LOG_NONE hilfreich. Hierbei handelt es sich nicht um Log-Level, sondern um fertige Masken. Mit den beiden nachfolgenden Zeilen würden also nur noch alle Fehler oberhalb des Levels Info erfasst.
Möchten Sie nur die beiden höchsten Log-Level erfassen, könnten Sie das so lösen:
$mask = PEAR_LOG_NONE | Log::MASK(PEAR_LOG_ALERT) | Log::MASK(PEAR_LOG_EMERG); $logger->setMask($mask);
Sie können mit der Methode getMask() übrigens auch eine bereits bestehende Maske auslesen und als Grundlage für das Generieren einer neuen Maske nutzen.
Log ist ein sehr hilfreiches Paket, wie ich finde. Gerade die Möglichkeit, Debug-Informationen ausgeben zu lassen, die Sie später wieder durch eine andere Maske unterdrücken können, macht vieles einfacher.