PHP异常和错误监控

Published on: Author: Evan Zhong Leave a comment

监控PHP程序发生错误,一般来说有两种方式。

1、PHP程序内部监控

通过在程序运行环境初始化时,调用set_exception_handler/set_error_handler 设置PHP异常和错误自定义处理函数,在自定义处理函数内,当监控到需要捕捉的异常或错误时,自动发送邮件或者短信给开发人员,从而达到监控的目的。

设置PHP错误自定义处理函数:(详见:http://cn2.php.net/manual/en/function.set-error-handler.php

mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRI
CT ] )

设置PHP异常自定义处理函数:(详见:http://cn2.php.net/manual/en/function.set-exception-handler.php

callable set_exception_handler ( callable $exception_handler )

示例代码:

/**
 * 默认异常处理函数
 * 
 * 通过设置
 * <code>
 * 		set_exception_handler('default_exception_handler');
 * </code>
 * 来处理未被捕捉的异常
 *
 * @param object $exception    错误异常对象
 * @param bool   $prompt_die_error 提示错误消息并终止运行?
 * @return void
 */
function default_exception_handler($exception, $prompt_die_error = true)
{
	global $__SuperClass;
 
	if (SRunEnv::isProd())
	{
		if ($prompt_die_error) Func::promptError($exception-&gt;getCode(), Func::getErrorLiteral($exception-&gt;getCode()));
 
		// 写入日志记录
		Site_Logger::logError($exception-&gt;getFile(), $exception-&gt;getLine(), $exception-&gt;getCode(), $exception-&gt;getMessage() . "\n\n" . $exception-&gt;getTraceAsString());
 
		// 發送通知郵件
		$message = "Dear webmaster: \n\nPHP Exception Ocurred at " . Func::getRequest() . " \n\nDetail as follows:\n\n";
		$message .= Func::formatException($exception);
		$message .= "\n------------------------------\nSpider Engine\n" . date('Y-m-d H:i:s');
		$__SuperClass-&gt;loadInformer()-&gt;informProgramException( $message, Func::getErrorLiteral($exception-&gt;getCode()));
 
		if ($prompt_die_error) exit;
 
	}
}
 
/**
 * 默认错误处理函数
 * 
 * 通过设置
 * <code>
 * 		set_error_handler('default_error_handler');
 * </code>
 * 来处理所有系统运行的错误、警告等
 *
 * @param int    $errno    错误类型
 * @param string $errstr   错误消息
 * @param string $errfile  出错文件
 * @param int    $errline  出错行数
 * @return void
 */
function default_error_handler($errno, $errstr, $errfile, $errline)
{
	global $__SuperClass;
 
	if (SRunEnv::isProd())
	{
		//写入日志记录
		switch ($errno)
		{
			case E_ERROR:
			case E_WARNING:
			case E_PARSE:
				Site_Logger::logError($errfile, $errline, $errno, $errstr);
 
				// 發送通知郵件
				$message = "Dear webmaster: \n\nPHP Error Ocurred at " . Func::getRequest() . " \n\nDetail as follows:\n\n";
				$message .= Func::formatError($errfile, $errline, $errno, $errstr);
				$message .= "\n------------------------------\nSpider Engine\n" . date('Y-m-d H:i:s');
				$__SuperClass-&gt;loadInformer()-&gt;informProgramError($message, Func::getErrorLiteral($errno));
 
				break;
 
			default:
				break;
		}
	}
}
 
// 异常处理函数
set_exception_handler ( 'default_exception_handler' );
 
// 错误处理函数
set_error_handler('default_error_handler');

 

还有另外两种在PHP程序内部监控的方法,也不妨试试。

一种是直接程序内部重定向error_log写到指定的日志文件。

@ini_set ("error_log", "/data1/log/debug/php.err-" . $_SERVER ["HTTP_HOST"] . "-" . $_SERVER ["REMOTE_ADDR"] . "-" . $_SERVER ["REQUEST_METHOD"] . "-" . str_replace ("/", "|", $_SERVER ["REQUEST_URI"]));

另一种是通过注册shutdown函数,记录错误日志。

/**
 * 记录错误日志
 * Array ( [type] =&gt; 1 [message] =&gt; Maximum execution time of 1 second exceeded [file] =&gt; /path/to/file_name.php [line] =&gt; 136 )
 */
function shutdown_log_error(){
	$aError = error_get_last();
	if($aError){
		Site_Logger::logError($aError['file'], $aError['line'], $aError['type'], $aError['message'] . "\n\n" . print_r($aError, true));
	}
}
 
register_shutdown_function('shutdown_log_error');

相较于通过set_exception_handler/set_error_handler,这两种方法相对简单灵活,但对错误异常的监控不够全面完整。

2、PHP错误日志监控

可以在php的配置文件php.ini里面,设置php把程序运行发生的异常和错误记录到错误日志中,然后调用某个外部监控程序,如Nagios,定期去查询错误日志,如发现所需要监控的异常或错误类型,则发送邮件或短信报警。

php.ini配置示例:

error_reporting = E_ALL &amp; ~E_DEPRECATED &amp; ~E_NOTICE
display_errors = Off
log_errors = On
error_log = /var/log/php-error.log

外部监控程序可以自己写一个shell,使用正则匹配错误,加入到crontab里面定期执行。

此处以开源监控程序Nagios为例说明,便于把PHP程序的监控和内存、CPU、带宽、磁盘等服务器监控整合在一块。

使用Nagios监控,需要安装相应的监控插件,这里使用check_logfiles,perl语言写的,通用监控日志文件的Nagios插件,支持正则表达式匹配。

check_logfiles 下载地址及文档说明:http://labs.consol.de/lang/en/nagios/check_logfiles/

Nagios支持通过NRPE插件,实现远程服务器的监控,这样不需要每台服务器都安装Nagios监控程序,通过NRPE远程调用,统一集中到一台中央的监控服务器上。

编辑nrpe.cfg,加入以下监控PHP错误和警告的指令:

# All php warning or error       
command[check_php]=/usr/local/libexec/nagios/check_logfiles --tag=php --logfile=/var/log/php-error.log --warningpattern="^\[[^]]+\] PHP Warning:" --criticalpattern="^\[[^]]+\] PHP (Fatal|Parse) error:" --noprotocol --report=long

然后在Nagios里面设置好发生PHP错误时候,如果通知管理员即可。

 

收到的错误邮件

来自PHP程序内部监控到的

邮件标题:[2013-05-22 10:06] PHP Exception Occurred:DATABASE_ERR_CONNECT

邮件内容:
Dear webmaster:

PHP Exception Ocurred at http://www.himonkey.cn/articles/?_do=view&article_id=15386&catalog_id=1017171

Detail as follows:

[111]DATABASE_ERR_CONNECT
[file] /www/lib/skel_100325/kernel/SuperClassBase.class.php : /www/lib/skel_100325/kernel/SuperClassBase.class.php
[line] 239
[message]
cannot connect to epl_db database at 192.168.49.4
[request uri] http://www.himonkey.cn/articles/?_do=view&article_id=15386&catalog_id=1017171
[request time] 2013-05-22 10:06
[client ip] 1.202.218.122
[server info] Array
(
[SCRIPT_URL] => /articles/
[SCRIPT_URI] => http://www.himonkey.cn/articles/
[HTTP_HOST] => www.himonkey.cn
[HTTP_USER_AGENT] => Mozilla/5.0 (compatible; JikeSpider; +http://shoulu.jike.com/spider.html)
[HTTP_ACCEPT] => text/html;q=0.8, */*;q=0.5
[HTTP_ACCEPT_CHARSET] => utf-8, gbk, gb2312, *;q=0.5
[HTTP_ACCEPT_LANGUAGE] => zh-cn;q=0.8, *;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip
[HTTP_CONNECTION] => close
[PATH] => /sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/root/bin
[SERVER_SIGNATURE] =>
[SERVER_SOFTWARE] => Apache
[SERVER_NAME] => www.himonkey.cn
[SERVER_ADDR] => 8.8.8.8
[SERVER_PORT] => 80
[REMOTE_ADDR] => 1.202.218.122
[DOCUMENT_ROOT] => /www/www.himonkey.cn/data100615
[SERVER_ADMIN] => webmaster@himonkey.cn
[SCRIPT_FILENAME] => /www/www.himonkey.cn/data100615/articles/index.php
[REMOTE_PORT] => 45938
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_METHOD] => GET
[QUERY_STRING] => _do=view&article_id=15386&catalog_id=1017171
[REQUEST_URI] => /articles/?_do=view&article_id=15386&catalog_id=1017171
[SCRIPT_NAME] => /articles/index.php
[PHP_SELF] => /articles/index.php
[REQUEST_TIME] => 1369188408
)

[request info] Array
(
[_do] => view
[article_id] => 15386
[catalog_id] => 1017171
)

[get info] Array
(
[_do] => view
[article_id] => 15386
[catalog_id] => 1017171
)

[post info] Array
(
)
——————————
Spider Engine
2013-05-22 10:06:48

 

Nagios发过来的通知邮件
邮件标题:** PROBLEM Service Alert: spider.himonkey.cn/PHP Warning Error Log is CRITICAL **

邮件内容:
***** Nagios *****

Notification Type: PROBLEM

Service: PHP Warning Error Log
Host: spider.eastfeet.com
Address: spider.eastfeet.com
State: CRITICAL

Date/Time: Tue May 14 22:43:28 CST 2013

Additional Info:

CRITICAL – (1 errors, 1 warnings) – [14-May-2013 22:33:43 Asia/Chongqing] PHP Fatal error: require(): Failed opening required /vhs/www.himonkey.cn/data100615_clone/misc/SLocale.class.php (include_path=.:/usr/local/share/pear) in /vhs/www.himonkey.cn/data100615_clone/includes/bootstrap.inc.php on line 139

发表评论