Wednesday 13 July 2011

Zend Log: Log to a file, formatting output, logging request details, and all error info

Wham this in your Bootstrap.php (replacing YOUR_WEBSITE):
protected function _initLogger() {
$writer = new Zend_Log_Writer_Stream('/var/log/YOUR_WEBSITE/output.log');
$format = '%timestamp% %priorityName%: %message%' . PHP_EOL;
$formatter = new Zend_Log_Formatter_Simple($format);
$writer->setFormatter($formatter);
$logger = new Zend_Log($writer);
$logger->setTimestampFormat("d-M-Y H:i:s");
Zend_Registry::set('logger', $logger);
}
Functions starting with _init will automatically be run during the bootstrap. This will setup the logger to log to a file in your logs directory, with a slightly clearer format than the default one (inc. simplified date format). It then saves the logger instance in the Zend_Registry, which means we can access it from our controllers!

Now in your Controller:
class IndexController extends Zend_Controller_Action {
private $logger;
public function init() {$this->logger = Zend_Registry::get('logger');}
public function indexAction() {$this->logger->info("Hello");}
}

Next, lets setup our logger to log the details of all requests, as this is really useful for debugging. We do this with a Controller Plugin, by implementing the preDispatch function (create application/plugins/Logger.php):
class Application_Plugin_Logger extends Zend_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$uri = $_SERVER['REQUEST_URI'];
if ($uri != "/favicon.ico") {
$logger = Zend_Registry::get('logger');
$logger->info("* REQUESTED URI ".$_SERVER['REQUEST_URI']
    .", CONTROLLER ".$request->getControllerName()
    .", ACTION ".$request->getActionName());
}
}
}
Note: we don't bother logging browsers requests for favicon.ico, as they are not very interesting

Then we need to register the plugin, which we do back in our bootstrap, at the end of _initLogger():
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Application_Plugin_Logger());

Finally, we setup the ErrorController to log all error information by adding this code to errorAction():
$logger = Zend_Registry::get('logger');
$params = $errors->request->getParams();

$paramsString = "array (\n";
foreach($params as $key=>$value) {
$paramsString .= "'".$key."' => '".$value."'\n";
}
$paramsString .= ")";

$logger->crit("ERROR = ".$this->view->message."\n"
    ."MESSAGE = ".$errors->exception->getMessage()."\n"
    ."STACK TRACE = \n".$errors->exception->getTraceAsString()."\n"
    ."REQUEST PARAMS = ".$paramsString);

2 comments:

  1. should these lines not be added to the plugin? and n ot in bootstrap?$front = Zend_Controller_Front::getInstance();
    $front->registerPlugin(new Application_Plugin_Logger());
     

    ReplyDelete
  2. One good piece of information, thank you!
    Also I want to add the if you want to log via an email you can do that:

    $mail = new Zend_Mail();

    $mail->setFrom('errors@mail.com')
    ->addTo('support@mail.com');

    $writer_mail = new Zend_Log_Writer_Mail($mail);

    $logger->addWriter($writer_mail);

    $logger->crit("ERROR = ".$this->view->message."\n"

    ."MESSAGE = ".$errors->exception->getMessage()."\n"

    ."STACK TRACE = \n".$errors->exception->getTraceAsString()."\n"

    ."REQUEST PARAMS = ".$paramsString, 'errors');

    ReplyDelete