- 浏览: 1009608 次
- 性别:
- 来自: 北京
最新评论
-
lizuodu:
非常不错
使用mysql federated引擎构建MySQL分布式数据库访问层 -
u010620626:
除了 libmysql 和 mysqlnd, 在 linux ...
PHP 5.3.0以上推荐使用mysqlnd驱动 -
嵌入式小小鸟:
很不错的!力荐!
集中化Linux日志管理系统 -
wfqwang82:
楼主,你好,我配置了一个负载均衡集群两台服务器,都可以启动ke ...
keepalived配置及典型应用案例 -
xialluyouyue:
完全不经过脑子考虑
ThinkPHP 3.1中的SQL注入漏洞分析----论ThinkPHP 3.1中的半吊子的PDO封装
Yii使用层次的日志处理机制,即日志的收集与日志最终的处理(如显示、保存到文件、保存到数据数)是分离的。
日志信息的收集由CLogger(日志记录器)完成,而日志信息的分发处理,则在CLogRouter的调度(称为日志路由管理器)下,分发给处理对象(如CFileLogRoute以及logging目录下继承自CLogRoute的类, 称为日志处理器),经过反复阅读其源代码,我更是为Yii的设计思想所折服,如此的分层处理,使得其易于灵活扩展。
而日志信息有级别之分,如普通的info, profile, trace, warning, error级别,可以在日志路由中设置过虑条件,如设置CFileRoute的levels属性,即可只处理指定级别的日志信息。
如在程序中调用:
Yii::log($message,CLogger::LEVEL_ERROR,$category);
对应的流程可能如下:
1. 生成CLogger实例
2. 如果YII_DEBUG , YII_TRACE_LEVEL都已经定义为有效值,并且日志级别不是profile, 则产生调用回溯信息, 并追加到日志信息上。
3.
调用CLogger::
log($msg,$level,$category)
收集日志,实际上这时日志并没有写入文件,仅仅是暂存于内存之中。
问题:日志是在何时被写入文件的?
经过反复跟踪,我发现在CLogRouter类的init方法中为Application对象的OnEndRequest事件绑定处理器CLogRouter::processLogs()。
同时也给Yii::$_logger的onFlush事件绑定事件处理器CLogRouter::collectLogs方法,用于在Yii::log()中当日志消息量过多时,及时将日志刷新写入文件。
而在CApplication::run()方法中定义了:
if($this->hasEventHandler('onEndRequest')) {
$this->onEndRequest(new CEvent($this));
}
到这里我们可以理解CLogger, (Yii::$_logger)仅仅是将日志进行收集(记录到内容结构之中),然后在程序结束时,由$app对象调用CLogRouter的processLogs进行日志的处理。Yii支持日志多道路由,比如:同一份日志即可写入至文件,又可显示到页面上,甚至同时以电子邮件发送,更甚至同时记录到数据库中,这是由配置文件中的log:routes配置实现的,为log:routes配置多个元素,实现多个路由分发。日志信息的过滤,记录均是由最终的日志处理器处理。
日志处理器要完成的任务主要包含以下几点:
从CLogger中取得所有日志,并进行过滤(主要是levels, categories两项定义log:routes:levels/categories)
1. 先进行过滤
参考CFileLogRoute::collectLogs()中的逻辑:
$logs=$logger->getLogs($this->levels,$this->categories); //执行过滤,只得到期望信息
日志过滤已经完成接下来就要对日志进行最终处理(如写入到文件,记录至数据库等)
CFileLogRoute::processLogs($logs);
但这个函数之中,有个小bug, 只判断日志目录是否可写,没有判断日志文件本身是否可写.
CFileLogRoute实现了类似Linux的日志轮换功能(LogRoate), 并规定了日志文件的大小,考虑得很周到,很完善! 我也要向其学习并吸收其思想!
protected/config/main.php中的配置:
'preload'=>array('log'),
components => array(
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'error, warning,trace',
),
)
定义log组件需要预先加载(实例化)。配置使用CLogRouter作为日志路由管理器,并设置了其日志路由处理器(routes属性)及其配置属性。
而preload, log属性的定义,均要应用到CWebApplication对象上(请参阅CApplication::__construct中的configure调用, configure从CModule继承而来)。而在CWebApplication的构造函数中执行preloadComponents(),就创建了log对象(即CLogRouter的实例)。
创建并初始化一个组件时,实际上调用的是CModule::getComponent, 这个调用中使用YiiBase::createComponent创建组件对象,并再调用组件的init初始化之。
再阅读CLogRouter::init()过程,在这里有两个关键之处,一是创建日志路由处理器(即决定日志的最终处理方式:写入文件,邮件发送等等),二是给应用程序对象绑定onEndRequest事件处理CLogRouter::processLogs()。而在CApplication::run()确实有相关代码用于运行onEndRequest事件处理句柄:
if($this->hasEventHandler('onEndRequest')) {
$this->onEndRequest(new CEvent($this));
}
也就是说,日志的最终处理(比如写入文件,系统日志,发送邮件)是发生在应用程序运行完毕之后的。Yii使用事件机制,巧妙地实现了事件与处理句柄的关联。
也就是说,当应用程序运行完毕,将执行CLogRouter::processLogs,对日志进行处理,。CLogRouter被称之为日志路由管理器。每个日志路由处理器从CLooger对象中取得相应的日志(使用过滤机制),作最终处理。
具体而言Yii的日志系统,分为以下几个层次:
日志发送者,即程序中调用Yii::log($msg, $level, $category),将日志发送给CLogger对象
CLogger对象负责将日志记录暂存于内存之中
程序运行结束后,log组件(日志路由管理器CLogRoute)的processLogs方法被激活执行,由其逐个调用日志路由器,作日志的最后处理。
大致过程如下:
1. CApplication::__construct()中调用preloadComponents, 这导致log组件(CLogRoute)被实例化,并被调用init方法初始化。
2. log组件(CLogRoute)的init方法中,其是初始化日志路由,并给CApplication对象onEndRequest事件绑定处理流程processLogs。给CLooger组件的onFlush事件绑定处理流程collectLogs。
3. 应用程序的其它部分通过调用Yii::log()向CLogger组件发送日志信息,CLogger组件将日志信息暂存到内存中。
4.
CApplication执行完毕(run方法中),会激活onEndRequest事件,绑定的事件处理器processLogs被执行,日志被写入文件之中。
Yii的日志路由机制,给日志系统扩展带来了无限的灵活。并且其多道路由处理机制,可将同一份日志信息进行多种方式处理。
这里举出一个案例:发生error级别的数据库错误时,及时给相关维护人员发送电子邮件,并同时将这些日志记录到文件之中。
规划思路,发送邮件和手机短信是两个不同的功能,Yii已经带了日志邮件发送组件(logging/CEmailLogRoute.php),但这个组件中却使用了php自带的mail函数,使用mail函数需要配置php.ini中的smtp主机,并且使用非验证发送方式,这种方式在目前的实际情况下已经完全不可使用。代替地我们需要使用带验证功能的smtp发送方式。
1. 在protected/components/目录下定义日志处理器类myEmailLogRoute,并让其继承自CEmailLogRoute,最主要的目的是重写CEmailLogRoute::sendEmail()方法
protected/components/myEmailLogRoute.php的内容
<?php
class myEmailLogRoute extends CEmailLogRoute {
public $host;
public $port;
public $user;
public $password;
public $timeout = 20;
private $_isConnected = false ;
private $_link ;
public function __destruct() {
if(is_resource($this->_link)) {
fclose($this->_link);
}
}
public function setActive($setActive=false) {
if(!$this->_isConnected || $setActive) {
$this->connect();
$this->login();
}
}
public function connect($reConnect = false) {
#if connection is failed,
$this->_link = fsockopen($this->host,$this->port,$errno, $error, $this->timeout);
if(!$this->_link) {
#do not use Yii::log to avoid recursive errors logging.
error_log("$error ($errno) in ".get_class($this));
syslog(LOG_WARNING, "$error ($errno) in".get_class($this));
if(YII_DEBUG) {
throw new Exception($error, $errno);
}
}
Yii::trace("conneted to SMTP Server $host:$port");
return true ;
}
#use $this->user, $this->password to login SMTP Server.
private function login() {
// login process.
$this->_isConnected = true ;
}
public function sendEmail($email,$subject,$message) {
$this->active = true ;
return $this->_sendEmail($email, $subject, $message);
}
public function _sendEmail($receiver, $subject, $message) {
#define you own smtp handler process.
}
}
其中,SMTP的处理细节请自行完善(本文的重点是放在如何处理日志上,而不是发送邮件上)。
接下来,我们就可以定义日志路由处理,编辑protected/config/main.php, 在log组件的routes组件添加新的路由配置:
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'error, warning,trace',
),
array(
'class' => 'myEmailLogRoute',
'levels' => 'error', #所有异常的错误级别均为error,
'categories' => 'exception.CDbException', #数据库产生错误时,均会产生CDbException异常。
'host' => 'mail.163.com',
'port' => 25,
'user' => 'zhangxugg@163.com',
'password' => 'you password',
'timeout' => 30,
'emails' => 'zhangsan@126.com,lisi@qq.com', #日志接收人。
'sentFrom' => ' zhangxugg@163.com ',
),
经过以上处理,即可使之实现我们的目的,当然你可以根据自己的需要进一步扩展之。
发表评论
-
Yii2 log prefix一个有用的设置
2018-08-11 23:10 0配置文件 log组件targets属性中指定: 'pre ... -
深入分析Redis Server went away产生的原因
2017-12-08 15:11 18376目前项目对Redis依赖较重,使用phpredis扩展操作 ... -
PHP中STDIN, STDOUT, STDERR的重定向
2017-04-19 20:41 2089<?php function test(){ ... -
Nginx php upstream sent unexpected FastCGI record: 3 while reading response head
2017-03-16 17:32 3009调用fastcgi_finish_request时,请求数超 ... -
PHP 5.3.0以上推荐使用mysqlnd驱动
2013-06-27 08:56 319721.什么是mysqlnd驱动? PHP手册上的描述 ... -
php json_encode不支持gbk gb2312编码的处理方法
2013-06-07 12:46 3814php json_encode只支持utf-8编码,自定义一 ... -
ThinkPHP 3.1中的SQL注入漏洞分析----论ThinkPHP 3.1中的半吊子的PDO封装
2013-04-19 21:47 15132ThinkPHP 3.1中的SQL注入漏洞分析- ... -
php 5.4 APC invalid pointer报错的解决办法
2013-04-12 15:58 4431为什么要使用APC ? 经过一些压力测试(使用apa ... -
PDO防注入原理分析以及使用PDO的注意事项
2013-03-24 18:09 62232我们都知道,只要合理正确使用PDO,可以基本上防止S ... -
Yii的事件机制原理及应用分析
2013-03-15 18:10 7606Yii中的事件机制原理及应用分析 YII ... -
phpcms v9内容页标题无法显示的解决方法
2012-11-06 09:11 5425说明:仅是gbk版本的phpcms v9存在此问 ... -
大数据量分页(海量数据分页)的高效实现
2012-09-13 09:02 27435海量数据分页,已经无法使用数据库自带的分页机制,比 ... -
Yii组件机制之三:路由组件urlManager
2012-09-10 15:41 14046Yii组件机制之三:路由组件 urlManager ... -
Yii组件机制之二:组件的使用及扩展
2012-09-07 10:35 11821Yii的组件机制详解 ... -
Yii的组件机制之一:组件基础类CComponent分析
2012-09-07 10:34 8570Yii的组件机制 组件机制,是Yii整个体系的思想精 ... -
Yii中的错误及异常处理
2012-09-04 17:54 32150Yii中的错误及异常处理 Yii已经默认已经在 ... -
Yii框架常见问题
2012-08-21 15:40 30431. 如何让默认的程序显示为中文? 修改protecte ... -
Yii框架在代理服务器环境下无法取得用户真实IP的解决方案
2012-03-28 16:57 0仔细查询yii的framework/web/CHttpRequ ...
相关推荐
本书也注重教授Yii2的高级特性,如行为(behaviors)、模块(modules)、和小部件(widgets),以及如何扩展Yii2核心来满足特殊需求。读者将学会如何有效地使用这些组件来构建功能丰富、用户友好的界面。书中对于...
首先,Yii框架的核心特点包括性能优化、安全性高以及强大的缓存机制。它采用了惰性加载策略,减少不必要的资源消耗,同时提供了丰富的预定义组件,如数据库访问对象(DAO)、ActiveRecord模式、MVC结构等,使得开发...
它提供了丰富的特性,包括MVC(模型-视图-控制器)架构模式、活跃记录(Active Record)、I18N和L10N(国际化和本地化)、缓存机制、安全性控制以及测试工具等,使得开发者能够高效地构建复杂、高性能的Web应用。...
最后,在调试、日志和错误处理章节,我们会了解到如何使用不同的日志路由、分析错误堆栈踪迹,以及如何展示自定义错误和为调试扩展创建自定义面板。 以上提到的内容全面覆盖了Yii2框架的核心功能以及在实际开发过程...
- **错误处理与日志记录**:有效的错误捕捉和日志记录机制,便于问题追踪和调试。 - **WEB服务**:支持RESTful API等Web服务的构建,增强应用的网络交互能力。 #### 七、案例研究与进阶主题 - **专题**:深入探讨...
- Yii提供了一套完善的错误处理和日志记录机制,方便开发者调试和维护应用。 - 支持自定义错误处理流程和日志级别。 9. **RESTful Web服务**: - Yii支持构建RESTful风格的Web服务。 - 包括URL路由、资源表示等...
“Yii 1.1 应用程序开发食谱”是一本实用性极强的技术书籍,不仅全面覆盖了 Yii 框架的核心功能和最佳实践,还提供了丰富的实战案例供读者学习参考。无论你是 Yii 新手还是有一定经验的开发者,都能从中获得宝贵的...
PHP提供了错误报告、异常处理和日志记录等机制,案例中会展示如何有效利用这些工具。 8. **安全性**:包括输入验证、防止SQL注入、XSS攻击防护等,是每个PHP开发者必须掌握的知识。案例会体现如何在实践中实施这些...
- 扩展是 Yii 社区开发的可重用组件,它们提供了额外的功能,如用户认证、日志记录、缓存管理等。通过这个列表,你可以找到经过社区验证的高质量扩展,例如: - `yiisoft/yii2-debug`:调试工具栏,用于分析应用...
7. **错误处理和日志记录**:通过try-catch语句和异常处理,以及error_reporting和error_log函数,确保程序的稳定性和问题的追踪。 8. **安全防护**:防止SQL注入、XSS攻击、CSRF攻击等,通过预处理语句、过滤用户...
了解它们的工作机制、如何设置和管理,以及在不同场景下的选择,对构建动态网站至关重要。 8. **错误和日志处理**:良好的错误处理和日志记录能帮助开发者快速定位和解决问题。学会如何优雅地处理错误,记录详细的...
8. **错误调试和性能优化**:学会使用错误报告、日志记录和调试工具,以及如何优化代码和数据库查询,是提高项目稳定性和效率的关键。 9. **源码分析**:通过分析提供的源码,可以学习到实际项目中的最佳实践、代码...
此外,还会讨论错误处理和异常处理机制。 2. OOP(面向对象编程):PHP 5引入了完整的面向对象支持,因此杂志可能深入讲解类、对象、继承、多态性和封装的概念,以及如何构建面向对象的应用程序。 3. PHP框架:...
3. **错误处理与调试**:良好的错误处理和调试技巧是高级开发的关键,书中会介绍如何使用异常处理、日志记录,以及利用Xdebug等工具进行代码调试。 4. **模板引擎与MVC模式**:讨论了如何使用PHP实现Model-View-...
10. **错误处理与日志**:良好的源码会包含错误处理机制和日志系统,便于调试和监控网站运行状态。 理解并掌握以上知识点,将有助于成功地解压、安装、配置并运行这个"小游戏网站源码 php版.zip",同时也能为其他...
”程序,复杂的数据库查询,以及涉及文件操作、表单处理等实际应用场景的案例。 总结来说,这份“PHP教程 ppt 例子”是一份全面且实用的学习资源,它将帮助初学者逐步掌握PHP编程,同时为有经验的开发者提供回顾和...
- **错误处理和调试**:查看如何处理运行时错误,以及如何开启和查看错误日志。 - **安全实践**:注意代码中防止安全漏洞的方法,比如参数过滤和安全输出。 通过深入研究这个项目,初学者可以提升PHP编程技能,了解...
7. **错误处理与日志记录**:良好的错误处理机制和日志记录是保证系统稳定运行的关键,PHP提供了一系列内置函数进行错误处理,并可通过Monolog等库进行日志管理。 8. **安全性**:考虑到数据敏感性,系统可能应用了...