Using different log routes

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.

Getting ready

Set up a fresh Yii application by using yiic webapp as described in the official guide.

How to do it...

Carry out the following steps:

  1. Configure logging using 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',
                ),
             ),
          ),
       ),
    ),
  2. Now, we will produce a few log messages in 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';
       }
    }
  3. Now run the preceding action multiple times. On the screen, you should see a web log similar to the one shown in the following screenshot:
    How to do it...

    A web log contains all the messages we have logged along with stack traces, timestamps, levels, and categories.

  4. Now open Firefox's Firebug console. You should see profiler messages as shown in the following screenshot:
    How to do it...

    Yii uses Firebug-compatible API, so you can view these messages in Chrome as follows:

    How to do it...

    Alternatively, in Opera:

    How to do it...
  5. As we just changed the log filenames and not paths, you should look in 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)

How it works...

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:

How it works...

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's more...

There are more interesting things about Yii logging, which are covered in the following subsections:

Yii::trace versus Yii::log

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.

Yii::beginProfile and Yii::endProfile

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'),

Log messages immediately

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).

See also

  • The Logging and using the context information recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.186.241