Zeta Components - high quality PHP components

eZ Components - EventLog


The EventLog component provides an API to log events and audit trails with log messages. These log messages are written to files or other storage elements. How and where the log messages are written depends on the log writer.

The available log writers are:

Each of these writers can be customized or extended.

An incoming log message can be written with zero or more writers. The writers depend on the variables of the log message itself and the ezcLogMapper implementation. ezcLogMapper checks the severity, source and category from the log message and forwards the message to the appropriate writers.

Class overview

The following classes are most important to use, customize or extend:

The ezcLog class is a singleton, meaning that only one instance of it can exist. This class provides methods to configure and record log messages. The recorded log messages are sent to an implementation of ezcLogMapper, which forwards the messages to the appropriate log writers.
ezcLogMapper provides an interface for log message mapping. Log messages are dispatched from ezcLog to a writer. The particular writer is determined in the class that implements ezcLogMapper and is assigned in ezcLog.
ezcLogFilterSet is an implementation of ezcLogMapper. ezcLogFilterSet contains a set of rules in the form of objects of the class ezcLogFilterRule. These rules are processed sequentially. In other words, the first assigned rule will be processed first. Each rule determines whether the log message matches the filter rule. If the log message matches, it calls the writer and decide whether the filter set stops processing.The ezcLogFilterSet class is inspired by modern mail application filter settings. Normally these mail filter settings sort the incoming mail and store it in the correct mail folder.
ezcLogWriter provides an interface for the writers. An implementation of this interface is a valid writer and can be addressed by ezcLogMapper. The writer itself determines how and where the log message is stored.
ezcLogUnixFileWriter writes the log message to a file.
ezcLogFilter is a structure to specify which log messages are accepted in a filter set.

For more information about these classes, see the class documentation.


Writing a log message to file

This example creates a file writer and assigns it to the default log mapper.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // Get the one and only instance of the ezcLog.
  4. $log ezcLog::getInstance();
  5. // Get an instance to the default log mapper.
  6. $mapper $log->getMapper();
  7. // Create a new Unix file writer, that writes to the file: "default.log".
  8. $writer = new ezcLogUnixFileWriter"/tmp/logs""default.log" );
  9. // Create a filter that accepts every message (default behavior).
  10. $filter = new ezcLogFilter;
  11. // Combine the filter with the writer in a filter rule. 
  12. $rule = new ezcLogFilterRule$filter$writertrue );
  13. // And finally assign the rule to the mapper.
  14. $mapper->appendRule$rule ); 
  15. // Write a message to the log. 
  16. $log->log"Could not connect with the payment server."ezcLog::WARNING );
  17. ?>

First, tutorial_autoload.php is included. This file loads the correct PHP files for the EventLog component.

Then, the log is set up and a message is written to the log file default.log, to be placed in the /tmp/logs directory.

After execution, the file /tmp/logs/default.log contains something like this:

Jan 24 14:39:57 [Warning] [default] [default] Could not connect with the payment server.

The date, severity, source, category and message are shown. The source and category are both set to default, because they were not specified in the message.

Writing a log message to a database

With the optional EventLogDatabaseTiein component it is also possible to write log messages to a database table. See the EventLogDatabaseTiein tutorial on how to use the ezcLogDatabaseWriter as writer instead of the ezcLogUnixFileWriter from this component. You can use both log writers at the same time. See the section Assigning log messages to different files on how to use different writers simultaneously.

Assigning sources and categories

The default source and category from ezcLog can be set via the properties source and category. The next example demonstrates how the default properties can be set and how extra variables can be added to the log.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. date_default_timezone_set"UTC" );
  4. // Same set up as the previous example.
  5. $log ezcLog::getInstance();
  6. $writer = new ezcLogUnixFileWriter"/tmp/logs""default.log" );
  7. $log->getmapper()->appendRule( new ezcLogFilterRule( new ezcLogFilter$writertrue ) );
  8. // Set the source and category.
  9. $log->source "Payment module";
  10. $log->category "Template";
  11. $log->log"Could not find cache file: </var/cache/payment1234.cache>."ezcLog::WARNING );
  12. // ...
  13. // Write a SQL error. The category is set to SQL for this message only. 
  14. $log->log"Cannot execute query: <SELECT * FROM Orders WHERE ID = '123'>."ezcLog::ERROR, array( "category" => "SQL" ) );
  15. // ...
  16. // Write a debug message that includes the current filename and line number.
  17. // The category is left out.
  18. $log->log"Starting shutdown process."ezcLog::DEBUG, array( "category" => """file" => __FILE__"line" => __LINE__ ) );
  19. ?>

After execution, the file /tmp/logs/default.log contains something like this:

Jan 24 15:45:04 [Warning] [Payment module] [Template] Could not find cache file: </var/cache/payment1234.cache>. Jan 24 15:45:04 [Error] [Payment module] [SQL] Cannot execute query: <SELECT * FROM Orders WHERE ID = '123'>. Jan 24 15:45:04 [Debug] [Payment module] Starting shutdown process. (file: /home/rb/php5/ezcomponents/packages/EventLog/trunk/docs/tutorial_sources_categories.php, line: 25)

Adding log attributes automatically

In some cases, it is convenient to automatically add log attributes to the log message. For example:

However, the log attributes appended to the log message are static. The value assigned to the attribute will be the same.

The next example assigns two automatic attributes:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. date_default_timezone_set"UTC" );
  4. // Same set up as the previous examples.
  5. $log ezcLog::getInstance();
  6. $writer = new ezcLogUnixFileWriter"/tmp/logs""default.log" );
  7. $log->getmapper()->appendRule( new ezcLogFilterRule( new ezcLogFilter$writertrue ) );
  8. // ...
  9. $username "John Doe";
  10. $service "Paynet Terminal";
  11. // ... 
  12. // Add automatically the username to the log message, when the log message is either a SUCCESS_AUDIT or a FAILED_AUDIT.
  13. $log->setSeverityAttributesezcLog::SUCCESS_AUDIT ezcLog::FAILED_AUDIT, array( "username" => $username ) );
  14. // Same can be done with the source of the log message.
  15. $log->setSourceAttributes( array( "Payment" ), array( "service" => $service ) );
  16. // Writing some log messages.
  17. $log->log"Authentication failed"ezcLog::FAILED_AUDIT, array( "source" => "security""category" => "login/logoff" ) );
  18. $log->source "Payment"
  19. $log->log"Connecting with the server."ezcLog::DEBUG, array( "category" => "external connections" ) );
  20. $log->log"Paid with credit card."ezcLog::SUCCESS_AUDIT, array( "category" => "shop" ) );
  21. ?>

After execution, the file /tmp/logs/default.log contains this:

Jan 25 10:15:19 [Failed audit] [security] [login/logoff] Authentication failed (username: John Doe) Jan 25 10:15:19 [Debug] [Payment] [external connections] Connecting with the server. (service: Paynet Terminal) Jan 25 10:15:19 [Success audit] [Payment] [shop] Payed with creditcard. (username: John Doe, service: Paynet Terminal)

Assigning log messages to different files

Depending on the incoming log message, the message can be stored with different writers. This example handles the log message as follows:

The code is as follows:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. date_default_timezone_set"UTC" );
  4. // Same set up as the previous examples.
  5. $log ezcLog::getInstance();
  6. // Create the writers
  7. $writeAll = new ezcLogUnixFileWriter"/tmp/logs""general.log" );
  8. $writePayment = new ezcLogUnixFileWriter"/tmp/logs""payment.log" );
  9. $writeAuditTrails = new ezcLogUnixFileWriter"/tmp/logs""audit_trails.log" );
  10. $debugFilter = new ezcLogFilter;
  11. $debugFilter->severity ezcLog::DEBUG;
  12. $log->getmapper()->appendRule( new ezcLogFilterRule$debugFilter, array(), false ) );
  13. $auditFilter = new ezcLogFilter;
  14. $auditFilter->severity ezcLog::SUCCESS_AUDIT ezcLog::FAILED_AUDIT;
  15. $log->getMapper()->appendRule( new ezcLogFilterRule$auditFilter$writeAuditTrailstrue ) );
  16. $paymentFilter = new ezcLogFilter;
  17. $paymentFilter->source = array( "Payment" );
  18. $log->getMapper()->appendRule( new ezcLogFilterRule$paymentFilter$writePaymenttrue ) );
  19. $log->getMapper()->appendRule( new ezcLogFilterRule( new ezcLogFilter$writeAlltrue ) );
  20. // Writing some log messages.
  21. $log->log"Authentication failed"ezcLog::FAILED_AUDIT, array( "source" => "security""category" => "login/logoff" ) );
  22. $log->source "Payment"
  23. $log->log"Connecting with the server."ezcLog::DEBUG, array( "category" => "external connections" ) );
  24. $log->log"Paid with credit card."ezcLog::SUCCESS_AUDIT, array( "category" => "shop" ) );
  25. $log->log"The credit card information is removed."ezcLog::NOTICE, array( "category" => "shop" ) );
  26. ?>

Using trigger_error()

The EventLog component is designed so that it can also be used with the trigger_error PHP method. Instead of calling the ezcLog::getInstance()->log() method, trigger_error() can be called. Using the trigger_error() method makes your code less dependent on the EventLog component and requires less overhead when logging is disabled.

The function set_error_handler should set up a callback function (or method) that, in turn, calls EventLog. For more information, see the API documentation on the ezcLog::logHandler() method.

Lazy initialization

Lazy initialization is a mechanism to load and configure a component, only when it is really used in your application. This mechanism saves time for parsing the classes and configuration, when the component is not used at all during one request. You can find a description how you can use it for your own components and how it works in the ezcBase tutorial. The keyword for the event log component is ezcInitLog.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. class customLazyLogConfiguration implements ezcBaseConfigurationInitializer
  4. {
  5.     public static function configureObject$log )
  6.     {
  7.         $writeAll = new ezcLogUnixFileWriter"/tmp/logs""general.log" );
  8.         $log->getMapper()->appendRule( new ezcLogFilterRule( new ezcLogFilter$writeAlltrue ) );
  9.     }
  10. }
  11. ezcBaseInit::setCallback
  12.     'ezcInitLog'
  13.     'customLazyLogConfiguration'
  14. );
  15. // Use log
  16. $log ezcLog::getInstance();
  17. $log->log"Paid with credit card."ezcLog::SUCCESS_AUDIT, array( "category" => "shop" ) );
  18. $log->log"The credit card information is removed."ezcLog::NOTICE, array( "category" => "shop" ) );
  19. ?>

The example shows a very simple event log setup with only one single logging rule. The main difference compared with earlier examples is, that we roll out the configuration to an own class, and define a callback using ezcBaseInit::setCallback to this class, which will be called with the event log instance on the first request for a yet uninitialized log handler.

ezcBaseInit::setCallback accepts as a first parameter a component specific key, which lets the component later request the right configuration callback. The second parameter is the name of the class to perform the static callback on. This class must implement the ezcBaseConfigurationInitializer class. Each component's lazy initialization calls the static method configureObject() on the referenced class.

When the event log is really required in the application, like shown in line 19 of the example, the event log component will be configured by the code in the configureObject() method in line 6, which just add a general logging rule, writing all log messages to /tmp/logs/general.log.