0 follower

Protokollierung (Logging)

Yii bietet eine flexibles und erweiterbares Protokollierungsfeature (engl.: logging). Zu loggende (also zu protokollierende) Nachrichten können einer Logstufe (engl.: log level) und einer Nachrichtenkategorie zugeordnet werden. Zusammen mit Logstufen- und Kategoriefiltern können ausgewählte Nachrichten an verschiedene Ziele, wie z.B. Dateien, E-Mails, Browserfenster etc., weitergeleitet werden

1. Loggen von Nachrichten

Nachrichten können geloggt werden, indem man entweder Yii::log oder Yii::trace aufruft. Der Unterschied zwischen beiden besteht darin, dass bei letzterer Nachrichten nur dann protokolliert werden, wenn die Anwendung sich im Debug-Modus befindet.

Yii::log($message, $level, $category);
Yii::trace($message, $category);

Beim Loggen einer Nachricht müssen wir eine Kategorie und eine Stufe angeben. Die Kategorie ist ein String im Format xxx.yyy.zzz was einem Pfad-Alias gleicht. Wenn eine Nachricht zum Beispiel in CController geloggt wird, könnten wir die Kategorie system.web.CController verwenden. Die Logstufe sollte einem der folgenden Werte entpsrechen:

  • trace: Diese Stufe wird von Yii::trace verwendet. Sie dient zum Nachverfolgen (engl.: trace) des Programmablaufs während der Entwicklungsphase.

  • info: dient zum Loggen allgemeiner Informationen.

  • profile: dient zur Leistungsmessung, wie wir sie in Kürze behandeln.

  • warning: dient für Warnhinweise.

  • error: dient für schwerwiegende Fehlermeldungen.

2. Nachrichtenrouting

Mit Yii::log oder Yii::trace geloggte Nachrichten werden im Speicher gehalten. Für gewöhnlich sollen diese im Browserfenster angezeigt oder in einem beständigen Speicher wie Dateien oder E-Mails gespeichert werden. Dies nennt man auch Nachrichtenrouting (engl.: message routing), also das Weiterleiten von Nachrichten an bestimmte Zielorte.

In Yii wird das Nachrichtenrouting von einer CLogRouter-Anwendungskomponente (sinngem.: Nachrichtenweiterleiter) übernommen. Sie verwaltet eine Reihe sogenannter Nachrichtenrouten (engl.: log routes). Jede Nachrichtenroute steht für ein einzelnes Log-Ziel. Nachrichten, die über eine Nachrichtenroute geschickt werden, können nach Stufe und Kategorie gefiltert werden.

Um das Nachrichtenrouting verwenden zu können, müssen wir die CLogRouter-Komponente installieren und frühzeitig laden (engl.: preload). Wir müssen außerdem deren Eigenschaft routes (Routen) mit den von uns gewünschten Nachrichtenrouten konfigurieren. Hier ein Beispiel für die nötige Anwendungskonfiguration:

array(
    ......
    'preload'=>array('log'),
    'components'=>array(
        ......
        'log'=>array(
            'class'=>'CLogRouter',
            'routes'=>array(
                array(
                    'class'=>'CFileLogRoute',
                    'levels'=>'trace, info',
                    'categories'=>'system.*',
                ),
                array(
                    'class'=>'CEmailLogRoute',
                    'levels'=>'error, warning',
                    'emails'=>'admin@example.com',
                ),
            ),
        ),
    ),
)

In obigem Beispiel verwenden wir zwei Nachrichtenrouten. Die erste ist CFileLogRoute, welche Nachrichten in einer Datei im Runtime-Verzeichnis der Anwendung speichert. Nur Nachrichten, die der Stufe trace oder info angehören und deren Kategorie mit system. beginnt, werden gespeichert. Die zweite Route ist CEmailLogRoute, die Nachrichten an die angegebene E-Mail-Adresse verschickt. Nur Nachrichten mit der Stufe error oder warning werden verschickt.

Die folgenden Nachrichtenrouten stehen in Yii zur Verfügung:

  • CDbLogRoute: speichert Nachrichten in einer Datenbanktabelle.
  • CEmailLogRoute: schickt Nachrichetn an die angegebenen E-Mail-Adressen.
  • CFileLogRoute: speichert Nachrichten in eine Datei im Runtime-Verzeichnis der Anwendung.
  • CWebLogRoute: zeigt Nachrichten am Ende der aktuellen Webseite an.
  • CProfileLogRoute: zeigt Nachrichten zur Leistungsermittlung am Ende der aktuellen Webseite an.

Info: Das Nachrichtenrouting wird am Ende des aktuellen Request-Zyklus beim Auslösen des onEndRequest-Events durchgeführt. Um die Bearbeitung des aktuellen Requests explizit zu beenden, rufen Sie CApplication::end() statt die() oder exit() auf, da CApplication::end() das onEndRequest-Event auslöst und somit Nachrichten ordnungsgemäß geloggt werden können.

Nachrichtenfilterung

Wie erwähnt, können Nachrichten nach ihrer Stufe und ihrer Kategorie gefiltert werden, bevor sie auf eine Nachrichtenroute geleitet werden. Dies geschieht, indem man die levels- und categories-Eigenschaften der entsprechenden Route setzt. Mehrere Stufen oder Kategorien sollten mit Kommas verbunden werden.

Da Nachrichtenkategorien im Format xxx.yyy.zzz vorliegen, können wir sie wie eine Hierarchie von Kategorien behandeln. In diesem Fall können wir sagen, xxx ist die Elternkategorie von xxx.yyy, welche wiederum die Elternkategorie von xxx.yyy.zzz bildet. Wir können xxx.* verwenden, um die Kategorie xxx und all ihre Kind- und Enkelkategorien darzustellen.

Loggen von Kontextinformationen

Seit Version 1.0.6 können wir angeben, dass zusätzliche Kontextinformationen wie vordefinierte PHP-Variablen (z.B. $_GET, $_SERVER), die Session-ID oder der Benutzername mit geloggt werden. Dies erreicht man, indem man CLogRoute::filter auf einen passenden Logfilter weisen lässt.

Im Framework ist bereits der nützliche CLogFilter enthalten, der in den meisten Fällen als ein solcher Logfilter verwendet werden kann. Standardmäßig logt CLogFilter eine Nachricht mit Variablen wie $_GET, $_SERVER, die oft wertvolle Informationen zum Systemzustand enthalten. CLogFilter kann auch so konfiguriert werden, dass allen zu loggenden Nachrichten die Session-ID, der Benutzername, etc. vorangestellt wird. Dadurch kann die Suche nach bestimmten Nachrichten bei einer globalen Suche beträchtlich vereinfacht werden.

Die folgende Konfiguration zeigt, wie man das Loggen von Kontextinformationen aktiviert. Beachten Sie, dass jede Logroute ihren eigenen Filter haben kann. Standardmäßig verwendet eine Logroute keinen Filter.

array(
    ......
    'preload'=>array('log'),
    'components'=>array(
        ......
        'log'=>array(
            'class'=>'CLogRouter',
            'routes'=>array(
                array(
                    'class'=>'CFileLogRoute',
                    'levels'=>'error',
                    'filter'=>'CLogFilter',
                ),
                ...andere Logrouten...
            ),
        ),
    ),
)

Seit Version 1.0.7 können mit Yii::trace auch der Informationen aus dem Aufrufstapel geloggt werden. Dieses Feature ist standardmäßig deaktiviert, da es die Leistung negativ beeinflusst. Um dieses Feature zu verwenden, definieren Sie am Anfang Ihres Eingangsscripts einfach die Konstante YII_TRACE_LEVEL mit einem Wert größer als 0 (und zwar bevor Sie yii.php einbinden). Yii hängt dann an jede Trace-Nachricht den Dateinamen und die Zeilennummer des Anwendungscode an. Die Zahl in YII_TRACE_LEVEL gibt an, wie viele Ebenen des Aufrufstapels aufgezeichnet werden sollen. Diese Information kann speziell in der Entwicklungsphase sehr nützlich sein, da es uns hilft, den genauen Ort, an dem die Nachricht geloggt wurde, ausfindig zu machen.

3. Leistungsmessung

Die Leistungsmessung (engl.: performance profiling) ist eine spezielle Art der Nachrichtenprotokollierung. Sie kann verwendet werden, um die Zeit zu messen, die zur Ausführung eines bestimmten Code-Blocks benötigt wird, und so den leistungsmäßigen Flaschenhals herauszufinden.

Für die Leistungsmessung müssen wir die zu messenden Code-Blöcke identifizieren. Wir markieren Anfang und Ende jedes Code-Blocks, indem wir die folgenden Methoden einfügen:

Yii::beginProfile('blockID');
...Zu messender Code-Block...
Yii::endProfile('blockID');

wobei blockID eine eindeutige ID zur Identifizierung des Code-Blocks darstellt.

Beachten Sie, dass Code-Blöcke sauber verschachtelt werden müssen. Das bedeutet, dass sich zwei Blöcke nicht überschneiden dürfen. Sie müssen entweder auf der selben Ebene nebeneinander liegen, oder vollständig von einem anderen Code-Block umschlossen werden.

Um die Ergebnisse der Messung anzuzeigen, müssen wir eine CLogRouter-Komponente mit einer CProfileLogRoute-Logroute installieren. Dies geht genauso wie beim normalen Nachrichtenrouting. Die CProfileLogRoute-Route zeigt das Ergebnis der Messung am Ende der aktuellen Seite an.

Leistungsmessung von SQL-Anweisungen

Im Zusammenhang mit Datenbanken ist eine Leistungsmessung besonders sinnvoll, da SQL-Anweisungen oft den größten leistungsmäßigen Flaschenhals einer Anwendung darstellen. Obwohl wir manuell beginProfile- und endProfile-Ausdrücke an die passenden Stellen setzen könnten, um die Zeit für jede SQL-Anweisung zu messen, bietet Yii seit Version 1.0.6 eine systematischere Herangehensweise, um dieses Problem zu lösen.

Indem CDbConnection::enableProfiling in der Anwendungskonfiguration auf true gesetzt wird, wird jede SQL-Anweisung gemessen. Mit der erwähnten CProfileLogRoute können die Ergebnisse leicht aufgegliedert nach den einzelnen SQL-Anweisungen und den dafür benötigten Zeiten angezeigt werden. Durch Aufruf von CDbConnection::getStats() können wir auch die Gesamtzahl aller SQL-Anweisungen sowie deren gesamte Ausführungszeit abfragen.