Wednesday, 30 July 2008

PHP Logging - logging exceptions

Re-working PHP Exceptions - getLine() vs. getTrace['line'] to use the Logger class (see PHP Logging - Zend_Log) and the Zend Framework, yields something like the following..........

<?php
 
set_include_path('../library'. PATH_SEPARATOR . get_include_path());
require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();
 
require_once "Logger.php";
 
class exceptionContents
{
public function display()
{
try
{
$exception = new Exception('message passed to exception', 5);
throw $exception;
}
catch(Exception $exception)
{
Logger::logMessage('message passed to log object', 1, $exception);
}
 
}
}
 
$exceptionContents = new ExceptionContents();
$exceptionContents->display();
 
?>


.....which produces this sort of information in the log file........

<logEntry>
<timestamp>2008-07-30T21:10:21+01:00</timestamp>
<message>message passed to log object</message>
<priority>1</priority>
<priorityName>ALERT</priorityName>
<exceptionCode>5</exceptionCode>
<file>/path/to/file/containing/line/where/thrown/exception/was/created.php</file>
<line>16</line>
<exceptionMessage>message passed to exception</exceptionMessage>
<exceptionTrace>a:1:{i:0; a:6:{s:4:"file"; s:74:"/path/to/file/containing/method/call/that/throws/exception.php"; s:4:"line"; i:27; s:8:"function"; s:7:"display"; s:5:"class"; s:17:"exceptionContents"; s:4:"type"; s:2:"->"; s:4:"args"; a:0:{}}}</exceptionTrace>
<exceptionTraceAsString>
#0 /path/to/file/containing/method/call/that/throws/exception.php(27): exceptionContents->display()
#1 {main}
</exceptionTraceAsString>
</logEntry>




Monday, 28 July 2008

PHP Logging - Zend_Log

Zend_Log provides a very convenient mechanism for keeping track of particular events when they occur in application code.

I tend to use a singleton pattern-based Logger class and then typically call a static logMessage() method directly.

Alternatively, calling the static instance() method returns the Logger, providing additional flexibility (e.g., customise setEventItem() calls on Zend_Log object).

Zend_Registry is being used to hold some values set during initialization of the application.

<?php
 
class Logger
{
private static $instance;
private $logger;

public static function instance()
{
if(!self::$instance)
{
self::$instance = new self();

$formatter = new Zend_Log_Formatter_Xml();

$filter = new Zend_Log_Filter_Priority(Zend_Registry::get('logFilterLevel'));

$writer = new Zend_Log_Writer_Stream(Zend_Registry::get('logFileLocation'));
$writer->setFormatter($formatter);
$writer->addFilter($filter);

self::$instance->logger = new Zend_Log($writer);
}

return self::$instance;
}

public static function logMessage($message=null, $priorityLevel=null, Exception $exception)
{
$logger = self::instance()->logger;

$logger->setEventItem('exceptionCode', $exception->getCode());
$logger->setEventItem('file', $exception->getFile());
$logger->setEventItem('line', $exception->getLine());
$logger->setEventItem('exceptionMessage', $exception->getMessage());
$logger->setEventItem('exceptionTrace', serialize($exception->getTrace()));
$logger->setEventItem('exceptionTraceAsString', $exception->getTraceAsString());

$logger->log($message, $priorityLevel);
}

}
 
?>



Friday, 25 July 2008

PHP Exceptions - getLine() vs. getTrace()['line']

The getLine() method called on an exception object returns information that differs from the ['line'] entry in the array returned by getTrace().

Using a trivial example (and the bad practice of dumping output to the screen), the following code..........

<?php
 
class exceptionContents
{
public function display()
{
try
{
$exception = new Exception('test exception message', 8);
throw $exception;
}
catch(Exception $exception)
{
echo '$exception->getCode() = '.$exception->getCode().'<br />';
echo '$exception->getFile() = '.$exception->getFile().'<br />';
echo '$exception->getLine() = '.$exception->getLine().'<br />';
echo '$exception->getMessage() = '.$exception->getMessage().'<br /><br />';
echo 'var_dump($exception->getTrace()) = ';
echo var_dump($exception->getTrace()).'<br />'.'<br />';
echo '$exception->getTraceAsString() = '.'<br />'.$exception->getTraceAsString().'<br />';
}
 
}
}
 
$exceptionContents = new ExceptionContents();
$exceptionContents->display();
 
?>


.......returns this sort of output.....


$exception->getCode() = 8
$exception->getFile() = /path/to/phpFile.php
$exception->getLine() = 9
$exception->getMessage() = test exception message

var_dump($exception->getTrace()) =
array
0 =>
array
'file' => string '/path/to/phpFile.php' (length=57)
'line' => int 27
'function' => string 'display' (length=7)
'class' => string 'exceptionContents' (length=17)
'type' => string '->' (length=2)
'args' =>
array
empty


$exception->getTraceAsString() =
#0 /path/to/phpFile.php(27): exceptionContents->display()
#1 {main}



$exception->getLine()
  • returns the line number on which the Exception was created (line 9 in this example).


$exception->getTrace()
$exceptionTrace = $exception->getTrace();
$exceptionTrace[0]['line'];

  • returns the line number for the method/function call that resulted in an exception being thrown (line 27 in this example).


By the same token, $exception->getFile() and $exception->getTrace['file'] also differ and if, for instance, a static method call is made and this call results in an exception being thrown, then getFile() will list the file in which the exception was created and thrown, whereas getTrace()['file'] will list the file in which the static method call was made.