Logging is the key to understanding what your application actually does when you have no chance to debug it. Believe or not, but even if you are 100 percent sure that the application will behave as expected, in production it can do many things you were not aware of. This is OK, as no one can be aware of everything. Therefore, if we are expecting an unusual behavior, we need to know about it as soon as possible and have enough details to reproduce it. This is where logging comes in handy.
Yii allows a developer not only to log messages but also to handle them differently depending on the message level and category. You can, for example, write a message to a database, send an e-mail, or just show it in the browser.
In this recipe, we will handle log messages in a wise manner: The most important message will be sent through an e-mail, less important messages will be saved in files A and B, and the profiling will be routed to Firebug. Additionally, in a development mode, all messages and profiling information will be displayed on the screen.
Set up a fresh Yii application by using yiic webapp
as described in the official guide.
Carry out the following steps:
protected/config/main.php
:array( … 'preload'=>array('log'), 'components'=>array( … 'log'=>array( 'class'=>'CLogRouter', 'routes'=>array( array( 'class' => 'CEmailLogRoute', 'categories' => 'example', 'levels' => CLogger::LEVEL_ERROR, 'emails' => array('[email protected]'), // change to your email 'sentFrom' => '[email protected]', 'subject' => 'Error at example.com', ), array( 'class' => 'CFileLogRoute', 'levels' => CLogger::LEVEL_WARNING, 'logFile' => 'warning.log', ), array( 'class' => 'CFileLogRoute', 'levels' => CLogger::LEVEL_INFO, 'logFile' => 'info.log', ), array( 'class' => 'CWebLogRoute', 'categories' => 'example', 'levels' => CLogger::LEVEL_PROFILE, 'showInFireBug' => true, 'ignoreAjaxInFireBug' => true, ), array( 'class' => 'CWebLogRoute', 'categories' => 'example', ), ), ), ), ),
protected/controllers/LogController.php
as follows:<?php class LogController extends CController { public function actionIndex() { Yii::trace('example trace message', 'example'), Yii::log('info', CLogger::LEVEL_INFO, 'example'), Yii::log('error', CLogger::LEVEL_ERROR, 'example'), Yii::log('trace', CLogger::LEVEL_TRACE, 'example'), Yii::log('warning', CLogger::LEVEL_WARNING, 'example'), Yii::beginProfile('preg_replace', 'example'), for($i=0;$i<10000;$i++){ preg_replace('~^[ a-z]+~', '', 'test it'), } Yii::endProfile('preg_replace', 'example'), echo 'done'; } }
A web log contains all the messages we have logged along with stack traces, timestamps, levels, and categories.
Yii uses Firebug-compatible API, so you can view these messages in Chrome as follows:
Alternatively, in Opera:
protected/runtime/
to find log files named warning.log
and info.log
. Inside, you will find messages as follows:2011/04/17 00:58:53 [warning] [example] warning in W:homeyiicmfwwwprotectedcontrollersLogController.php (11) in W:homeyiicmfwwwindex.php (12) 2011/04/17 00:59:00 [warning] [example] warning in W:homeyiicmfwwwprotectedcontrollersLogController.php (11) in W:homeyiicmfwwwindex.php (12) 2011/04/17 00:59:56 [warning] [example] warning in W:homeyiicmfwwwprotectedcontrollersLogController.php (11) in W:homeyiicmfwwwindex.php (12) 2011/04/17 01:02:07 [warning] [example] warning in W:homeyiicmfwwwprotectedcontrollersLogController.php (11) in W:homeyiicmfwwwindex.php (12) 2011/04/17 01:02:12 [warning] [example] warning in W:homeyiicmfwwwprotectedcontrollersLogController.php (11) in W:homeyiicmfwwwindex.php (12) 2011/04/17 01:03:00 [warning] [example] warning in W:homeyiicmfwwwprotectedcontrollersLogController.php (11) in W:homeyiicmfwwwindex.php (12)
When one logs a message using Yii::log
or Yii::trace
, Yii passes it to the log router. Depending on how it is configured, it passes messages along one or many routes. For example, e-mailing errors, writing debug information in file A
, writing warning information in file B
, and passing profiling results to the Firebug console. This is depicted in the following diagram:
CLogRouter
is typically attached to an application component named log
. Therefore, in order to configure it, we should set its properties in the protected/config/main.php
file's components
section. The only configurable property is routes. It contains an array of log route handlers and their configurations is routes
.
We have defined five log routes. Let's review them as follows:
array( 'class' => 'CEmailLogRoute', 'categories' => 'example', 'levels' => CLogger::LEVEL_ERROR, 'emails' => array('[email protected]'), 'sentFrom' => '[email protected]', 'subject' => 'Error at example.com', ),
CEmailLogRoute
sends log messages through e-mail. We limit category
to example and level
to error. An e-mail will be sent from [email protected]
to [email protected]
and its subject
value will be Error at example.com
.
array( 'class' => 'CFileLogRoute', 'levels' => CLogger::LEVEL_WARNING, 'logFile' => 'warning.log', ),
CFileLogRoute
appends error messages to a file specified. We limit the message level to warning and use a file named warning.log
. We do the same for info level messages by using a file named info.log
.
CWebLogRoute
passes log messages to the browser as follows:
array( 'class' => 'CWebLogRoute', 'categories' => 'example', ),
The same log route can be used to pass log messages to Firebug or another console compatible with it.
array( 'class' => 'CWebLogRoute', 'categories' => 'example', 'levels' => CLogger::LEVEL_PROFILE, 'showInFireBug' => true, 'ignoreAjaxInFireBug' => true, ),
In the preceding code, we limit the category to example
and the log level to profile, and turn on the logging to Firebug. Additionally, we turn the logging off for AJAX-requests, as the JSON response can be spoiled by logging.
There are more interesting things about Yii logging, which are covered in the following subsections:
Yii::trace
is a simple wrapper around Yii::log
.
if(YII_DEBUG) self::log($msg,CLogger::LEVEL_TRACE,$category);
Therefore, Yii::trace
logs a message with a trace level, if Yii is in the debug mode.
These methods are used to measure the execution time of some part of the application's code. In our LogController
, we measured 10,000 executions of preg_replace
as follows:
Yii::beginProfile('preg_replace', 'regex_test'), for($i=0;$i<10000;$i++){ preg_replace('~^[ a-z]+~', '', 'test it'), } Yii::endProfile('preg_replace', 'regex_test'),
By default, Yii keeps all log messages in memory until the application is properly terminated using Yii::app()->end()
. That's done for performance reasons and generally works fine. However, if there is a PHP fatal error or die()
/exit()
in the code, some log messages will not be written at all. To make sure your messages will be logged you can flush them explicitly using Yii::app()->log->flush(true)
.
In order to learn more about logging, refer to the following URLs:
3.140.186.241