From LifeType Wiki
LifeType provides a lightweight logging framework that allows PHP code to send information to for example log files or other, based on a given format and using the given priority. For those familiar with Log4J, the LifeType logging framework was built taking many concepts from it.
The LifeType framework does not provide some advanced features such as log file rotating and archiving, as these loggers are only meant to be used for development puprposes.
Contents |
[edit] Logging in LifeType
Logging in LifeType is based on two parts, a configuration file that defines the so called "loggers" and the actual PHP code that makes use of these loggers.
A logger definition includes the following things:
- Where messages are sent, based on the concept of "appenders"
- How log messages are formatted and what information is included in each one of them.
- Which messages should be logged, based on their priority
- Some extra parameters that depend on the appender. For example in case of the file logger, there should be an extra parameter specifying to which file to write the messages.
There can be as many loggers as needed, as long as each one of them has a unique identifier.
Once a logger has been defined, all that needs to be done at the PHP level is use the LoggerManager to obtain a reference to the logger, and then call any of the methods to log information such as debug(), info(), warn() or error(), depending on the priority of the message.
[edit] How to configure logging
Loggers are defined in the file config/logging.properties.php. The file is nothing more than a native PHP file which defines an associative array called $config. The key of the array is the name of the logger and the value is another associative array which contains the properties of the logger being defines.
By default, the following loggers are defined:
- default
- sqlerr
- trackback
These loggers are all disabled by default in a vanilla installation of LifeType because they are not needed in production instances.
When configuring logging, please do not remove these loggers as they are all needed by the code in LifeType. The default logger is used as the default logger when no other logger is specified when calling the logger manager. sqlerror is actively used by LifeType to log SQL queries that caused an error, while the trackback logger is used in case we need to debug trackbacks.
In order to define a logger, we must add a new item to the $config array:
$config["test_logger"] = Array(
"appender" => "file",
"layout" => "%d %N - [%f:%l] %m%n",
"file" => "test_logger.txt",
"prio" => "debug"
);
[edit] Appenders
The first parameter of our new logger called test_logger, is an appender. The appender defines where messages are being logged and in a default installation of LifeType, there are three appenders that can be used:
- null
- file
- stdout
The null appender is an appender that does nothing. It receives a log message and it does not write or send it anywhere so this logger is useful to disable logging completely in our application.
The file appender sends messages to a file. As such, it requires another parameter called file, as in the example below, that defines the name of the file. The name of the file can either include an absolute or relative path, and the folder must be writable by the web server.
The stdout appender sends messages directly to the browser and it needs no extra parameters. Messages logged via this logger are not buffered, so they are output to the client as soon as they come.
[edit] Layouts
Each logger must define a layout, which informs the logging framework about the format that log messages should have. Layouts are defined based on certain parameters that will include information in the logged message:
- %c: the class where message was logged. This information may not be avilable if we are logging from code which is not part of a class.
- %d: current date.
- %f: the file where the message was logged.
- %F: the function where the message was logged.
- %l: the line where the message was logged.
- %m: the log message.
- %n: a newline character.
- %N: the level name.
- %p: the level of priority.
- %r: a carriage return.
- %t: a horizontal tab.
- %T: a unix timestamp (seconds since January 1st, 1970)
- %S: the full stack trace, if available.
According to the layout defined in our example above, logged messages will look like:
01-02-2006 19:48:02 DEBUG - [model.class.php:175] This is a test log message
There can only be one layour per logger but any of the parameters above can be used in the definition of a layout.
[edit] Priorities
When logging messages, there are four possible priorities (in order of importance):
- error
- warn
- info
- debug
The error priority would log only error messages (as defined by our application), warn log warning messages and error messages, info would log error, warning and informative messages, while debug would log every message attempted to be logged by our code.
In the example above, our default logger is configured to log everything because it is meant to be a logger used for debugging purposes.
[edit] Logging messages from PHP code
When logging messages from LifeType code, all we need to do is ask the LoggerManager class to give us a reference to our logger. If no logger is given as a parameter, the default logger will be returned (hence the importance of not removing the definition of this default logger from the configuration file!)
The following code is enough to get a reference to a logger and log a test message to the test_logger logger:
include_once( PLOG_CLASS_PATH."class/logger/loggermanager.class.php" ); $testLogger =& LoggerManager::getLogger( "test_logger" ); $testLogger->debug( "this is a test debug message" );
The LoggerManager::getLogger($loggerId) method returns a reference to a Logger object. Amongst other methods, it defines four methods to log a message with a different priority:
- Logger::debug( $message )
- Logger::warn( $message )
- Logger::info( $message )
- Logger::error( $message )
These methods are all shortcuts to Logger::log( $message, $prio ), please take a look at the file class/logger/logger/logger.class.php for more details on the implementation.
Since it may be a bit troublesome to get a reference to a logger from each one of the classes where we want log, there is a special class in LifeType called Loggable that automatically provides a reference to the default logger upon creation via the Loggable::log attribute (of type Logger):
include_once( PLOG_CLASS_PATH."class/object/loggable.class.php" );
class TestClass extends Loggable
{
function TestClass()
{
$this->Loggable();
...
$this->log->debug( "this is a log message" );
}
}
[edit] Creating custom appenders
LifeType provides only 3 appenders and by extending the Appender class is it possible to create custom appenders that log messages to other destinations such as a databases, Windows event loggers, etc. The appender class can be found in class/logger/appender/appender.class.php.
The Appender class needs a basic method to be implemented, and that is Appender::write( $message ). This method receives a message that has already been processed by the layout formatter. It is advisable to implement a constructor for our custom appender so that we can access extra parameters as required by our custom appender.
Custom appenders must be called xxxappender, where xxx will be the identifier used in the configuration file to identify the appender, and should be placed under the class/logger/appender/ folder.
As an example, we can write a custom appender that sends information to a MySQL database.
include_once( PLOG_CLASS_PATH."class/logger/appender.class.php" );
class MySQLAppender extends Appender
{
var $user;
var $db;
var $password;
var $host;
function MySQLAppender( $layout, $properties )
{
$this->Appender( $layout, $properties );
// the $properties array contains all the logger parameters
$this->user = $properties[ "user" ];
$this->db = $properties[ "db" ];
$this->host = $properties[ "host" ];
$this->password = $properties[ "password" ];
// connect to the database
$this->con = mysql_connect( $this->host, $this->user, $this->password );
if( !$this->con ) {
die( mysql_error );
}
// and select the database where to write
mysql_select_db( $this->db, $this->con );
}
function write( $message )
{
// build the SQL query and execute it (but error checking is needed!)
$sql = "INSERT INTO log_messages (message) VALUES ('{$message}')";
mysql_query( $sql, $this->db );
}
}
This appender needs a database with at least one table which defines at least a field called message, where the actual log message will be logged.
The configuration for this logger would be as follows:
$config["db_logger"] = Array(
"layout" => "%d %N - %m%n",
"appender" => "mysql",
"prio" => "error",
"db" => "logs",
"user" => "your_db_user",
"password" => "your_password",
"host" => "localhost"
);
Now in order to get access to our database logger, all we need to do is query the LoggerManager and request a logger called db_logger.
