介绍 入门 应用结构 请求处理 关键概念 配合数据库工作 接收用户数据 显示数据 安全 缓存 RESTfulWeb服务 开发工具 测试 高级专题 小部件 助手类 其他

发布于 2015-08-01 11:23:39 | 297 次阅读 | 评论: 0 | 来源: 网络整理

Yii provides a powerful logging framework that is highly customizable and extensible. Using this framework, you can easily log various types of messages, filter them, and gather them at different targets, such as files, databases, emails.

Using the Yii logging framework involves the following steps:

  • Record log messages at various places in your code;
  • Configure log targets in the application configuration to filter and export log messages;
  • Examine the filtered logged messages exported by different targets (e.g. the Yii debugger).

In this section, we will mainly describe the first two steps.

Log Messages

Recording log messages is as simple as calling one of the following logging methods:

  • Yii::trace(): record a message to trace how a piece of code runs. This is mainly for development use.
  • Yii::info(): record a message that conveys some useful information.
  • Yii::warning(): record a warning message that indicates something unexpected has happened.
  • Yii::error(): record a fatal error that should be investigated as soon as possible.

These logging methods record log messages at various severity levels and categories. They share the same function signature function ($message, $category = 'application'), where $message stands for the log message to be recorded, while $category is the category of the log message. The code in the following example records a trace message under the default category application:

Yii::trace('start calculating average revenue');

Info: Log messages can be strings as well as complex data, such as arrays or objects. It is the responsibility of log targets to properly deal with log messages. By default, if a log message is not a string, it will be exported as a string by calling yiihelpersVarDumper::export().

To better organize and filter log messages, it is recommended that you specify an appropriate category for each log message. You may choose a hierarchical naming scheme for categories, which will make it easier for log targets to filter messages based on their categories. A simple yet effective naming scheme is to use the PHP magic constant __METHOD__ for the category names. This is also the approach used in the core Yii framework code. For example,

Yii::trace('start calculating average revenue', __METHOD__);

The __METHOD__ constant evaluates as the name of the method (prefixed with the fully qualified class name) where the constant appears. For example, it is equal to the string 'appcontrollersRevenueController::calculate' if the above line of code is called within this method.

Info: The logging methods described above are actually shortcuts to the yiilogLogger::log() method of the yiilogLogger which is a singleton accessible through the expression Yii::getLogger(). When enough messages are logged or when the application ends, the logger object will call a yiilogDispatcher to send recorded log messages to the registered log targets.

Log Targets

A log target is an instance of the yiilogTarget class or its child class. It filters the log messages by their severity levels and categories and then exports them to some medium. For example, a yiilogDbTarget exports the filtered log messages to a database table, while an yiilogEmailTarget exports the log messages to specified email addresses.

You can register multiple log targets in an application by configuring them through the log application component in the application configuration, like the following:

return [
    // the "log" component must be loaded during bootstrapping time
    'bootstrap' => ['log'],
    
    'components' => [
        'log' => [
            'targets' => [
                [
                    'class' => 'yiilogDbTarget',
                    'levels' => ['error', 'warning'],
                ],
                [
                    'class' => 'yiilogEmailTarget',
                    'levels' => ['error'],
                    'categories' => ['yiidb*'],
                    'message' => [
                       'from' => ['log@example.com'],
                       'to' => ['admin@example.com', 'developer@example.com'],
                       'subject' => 'Database errors at example.com',
                    ],
                ],
            ],
        ],
    ],
];

Note: The log component must be loaded during bootstrapping time so that it can dispatch log messages to targets promptly. That is why it is listed in the bootstrap array as shown above.

In the above code, two log targets are registered in the yiilogDispatcher::targets property:

  • the first target selects error and warning messages and saves them in a database table;
  • the second target selects error messages under the categories whose names start with yiidb, and sends them in an email to both admin@example.com and developer@example.com.

Yii comes with the following built-in log targets. Please refer to the API documentation about these classes to learn how to configure and use them.

  • yiilogDbTarget: stores log messages in a database table.
  • yiilogEmailTarget: sends log messages to pre-specified email addresses.
  • yiilogFileTarget: saves log messages in files.
  • yiilogSyslogTarget: saves log messages to syslog by calling the PHP function syslog().

In the following, we will describe the features common to all log targets.

Message Filtering

For each log target, you can configure its yiilogTarget::levels and yiilogTarget::categories properties to specify which severity levels and categories of the messages the target should process.

The yiilogTarget::levels property takes an array consisting of one or several of the following values:

  • error: corresponding to messages logged by Yii::error().
  • warning: corresponding to messages logged by Yii::warning().
  • info: corresponding to messages logged by Yii::info().
  • trace: corresponding to messages logged by Yii::trace().
  • profile: corresponding to messages logged by Yii::beginProfile() and Yii::endProfile(), which will be explained in more details in the Profiling subsection.

If you do not specify the yiilogTarget::levels property, it means the target will process messages of any severity level.

The yiilogTarget::categories property takes an array consisting of message category names or patterns. A target will only process messages whose category can be found or match one of the patterns in this array. A category pattern is a category name prefix with an asterisk * at its end. A category name matches a category pattern if it starts with the same prefix of the pattern. For example, yiidbCommand::execute and yiidbCommand::query are used as category names for the log messages recorded in the yiidbCommand class. They both match the pattern yiidb*.

If you do not specify the yiilogTarget::categories property, it means the target will process messages of any category.

Besides whitelisting the categories by the yiilogTarget::categories property, you may also blacklist certain categories by the yiilogTarget::except property. If the category of a message is found or matches one of the patterns in this property, it will NOT be processed by the target.

The following target configuration specifies that the target should only process error and warning messages under the categories whose names match either yiidb* or yiiwebHttpException:*, but not yiiwebHttpException:404.

[
    'class' => 'yiilogFileTarget',
    'levels' => ['error', 'warning'],
    'categories' => [
        'yiidb*',
        'yiiwebHttpException:*',
    ],
    'except' => [
        'yiiwebHttpException:404',
    ],
]

Info: When an HTTP exception is caught by the error handler, an error message will be logged with the category name in the format of yiiwebHttpException:ErrorCode. For example, the yiiwebNotFoundHttpException will cause an error message of category yiiwebHttpException:404.

Message Formatting

Log targets export the filtered log messages in a certain format. For example, if you install a log target of the class yiilogFileTarget, you may find a log message similar to the following in the runtime/log/app.log file:

2014-10-04 18:10:15 [::1][][-][trace][yiibaseModule::getModule] Loading module: debug

By default, log messages will be formatted as follows by the yiilogTarget::formatMessage():

Timestamp [IP address][User ID][Session ID][Severity Level][Category] Message Text

You may customize this format by configuring the yiilogTarget::prefix property which takes a PHP callable returning a customized message prefix. For example, the following code configures a log target to prefix each log message with the current user ID (IP address and Session ID are removed for privacy reasons).

[
    'class' => 'yiilogFileTarget',
    'prefix' => function ($message) {
        $user = Yii::$app->has('user', true) ? Yii::$app->get('user') : null;
        $userID = $user ? $user->getId(false) : '-';
        return "[$userID]";
    }
]

Besides message prefixes, log targets also append some context information to each batch of log messages. By default, the values of these global PHP variables are included: $_GET, $_POST, $_FILES, $_COOKIE, $_SESSION and $_SERVER. You may adjust this behavior by configuring the yiilogTarget::logVars property with the names of the global variables that you want to include by the log target. For example, the following log target configuration specifies that only the value of the $_SERVER variable will be appended to the log messages.

[
    'class' => 'yiilogFileTarget',
    'logVars' => ['_SERVER'],
]

You may configure logVars to be an empty array to totally disable the inclusion of context information. Or if you want to implement your own way of providing context information, you may override the yiilogTarget::getContextMessage() method.

Message Trace Level

During development, it is often desirable to see where each log message is coming from. This can be achieved by configuring the yiilogDispatcher::traceLevel property of the log component like the following:

return [
    'bootstrap' => ['log'],
    'components' => [
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [...],
        ],
    ],
];

The above application configuration sets yiilogDispatcher::traceLevel to be 3 if YII_DEBUG is on and 0 if YII_DEBUG is off. This means, if YII_DEBUG is on, each log message will be appended with at most 3 levels of the call stack at which the log message is recorded; and if YII_DEBUG is off, no call stack information will be included.

Info: Getting call stack information is not trivial. Therefore, you should only use this feature during development or when debugging an application.

Message Flushing and Exporting

As aforementioned, log messages are maintained in an array by the yiilogLogger. To limit the memory consumption by this array, the logger will flush the recorded messages to the log targets each time the array accumulates a certain number of log messages. You can customize this number by configuring the yiilogDispatcher::flushInterval property of the log component:

return [
    'bootstrap' => ['log'],
    'components' => [
        'log' => [
            'flushInterval' => 100,   // default is 1000
            'targets' => [...],
        ],
    ],
];

Info: Message flushing also occurs when the application ends, which ensures log targets can receive complete log messages.

When the yiilogLogger flushes log messages to log targets, they do not get exported immediately. Instead, the message exporting only occurs when a log target accumulates certain number of the filtered messages. You can customize this number by configuring the yiilogTarget::exportInterval property of individual log targets, like the following,

[
    'class' => 'yiilogFileTarget',
    'exportInterval' => 100,  // default is 1000
]

Because of the flushing and exporting level setting, by default when you call Yii::trace() or any other logging method, you will NOT see the log message immediately in the log targets. This could be a problem for some long-running console applications. To make each log message appear immediately in the log targets, you should set both yiilogDispatcher::flushInterval and yiilogTarget::exportInterval to be 1, as shown below:

return [
    'bootstrap' => ['log'],
    'components' => [
        'log' => [
            'flushInterval' => 1,
            'targets' => [
                [
                    'class' => 'yiilogFileTarget',
                    'exportInterval' => 1,
                ],
            ],
        ],
    ],
];

Note: Frequent message flushing and exporting will degrade the performance of your application.

Toggling Log Targets

You can enable or disable a log target by configuring its yiilogTarget::enabled property. You may do so via the log target configuration or by the following PHP statement in your code:

Yii::$app->log->targets['file']->enabled = false;

The above code requires you to name a target as file, as shown below by using string keys in the targets array:

return [
    'bootstrap' => ['log'],
    'components' => [
        'log' => [
            'targets' => [
                'file' => [
                    'class' => 'yiilogFileTarget',
                ],
                'db' => [
                    'class' => 'yiilogDbTarget',
                ],
            ],
        ],
    ],
];

Creating New Targets

Creating a new log target class is very simple. You mainly need to implement the yiilogTarget::export() method sending the content of the yiilogTarget::messages array to a designated medium. You may call the yiilogTarget::formatMessage() method to format each message. For more details, you may refer to any of the log target classes included in the Yii release.

Performance Profiling

Performance profiling is a special type of message logging that is used to measure the time taken by certain code blocks and find out what are the performance bottlenecks. For example, the yiidbCommand class uses performance profiling to find out the time taken by each DB query.

To use performance profiling, first identify the code blocks that need to be profiled. Then enclose each code block like the following:

Yii::beginProfile('myBenchmark');

...code block being profiled...

Yii::endProfile('myBenchmark');

where myBenchmark stands for a unique token identifying a code block. Later when you examine the profiling result, you will use this token to locate the time spent by the corresponding code block.

It is important to make sure that the pairs of beginProfile and endProfile are properly nested. For example,

Yii::beginProfile('block1');

    // some code to be profiled

    Yii::beginProfile('block2');
        // some other code to be profiled
    Yii::endProfile('block2');

Yii::endProfile('block1');

If you miss Yii::endProfile('block1') or switch the order of Yii::endProfile('block1') and Yii::endProfile('block2'), the performance profiling will not work.

For each code block being profiled, a log message with the severity level profile is recorded. You can configure a log target to collect such messages and export them. The Yii debugger has a built-in performance profiling panel showing the profiling results.

最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务