php常见错误报警,拦截PHP各种异常和错误,发生致命错误时进行报警(一)

在日常开发中,大多数人的做法是在开发环境时开启调试模式,在产品环境关闭调试模式。在开发的时候可以查看各种错误、异常,但是在线上就把错误显示的关闭。上面的情形看似很科学,有人解释为这样很安全,别人看不到错误,以免泄露重要信息...但是你有没有遇到这种情况,线下好好的,一上线却运行不起来也找不到原因...一个脚本,跑了好长一段时间,一直没有问题,有一天突然中断了,然后了也没有任何记录都不造啥原因...线上一个付款,别人明明付了款,但是我们却没有记录到,自己亲自去实验,却是好的...种种以上,都是因为大家关闭了错误信息,并且未将错误、异常记录到日志,导致那些随机发生的错误很难追踪。这样矛盾就来了,即不要显示错误,又要追踪错误,这如何实现了?以上问题都可以通过PHP的错误、异常机制及其内建函数'set_exception_handler','set_error_handler','register_shutdown_function' 来实现'set_exception_handler' 函数 用于拦截各种未捕获的异常,然后将这些交给用户自定义的方式进行处理'set_error_handler' 函数可以拦截各种错误,然后交给用户自定义的方式进行处理'register_shutdown_function' 函数是在PHP脚本结束时调用的函数,配合'error_get_last'可以获取最后的致命性错误这个思路大体就是把错误、异常、致命性错误拦截下来,交给我们自定义的方法进行处理,我们辨别这些错误、异常是否致命,如果是则记录的数据库或者文件系统,然后使用脚本不停的扫描这些日志,发现严重错误立即发送邮件或发送短信进行报警首先我们定义错误拦截类,该类用于将错误、异常拦截下来,用我们自己定义的处理方式进行处理,该类放在文件名为'errorHandler.class.php'中,代码如下/*** 文件名称:baseErrorHandler.class.php* 摘    要:错误拦截器父类*/require 'errorHandlerException.class.php';//异常类class errorHandler{    public $argvs = array();    public     $memoryReserveSize = 262144;//备用内存大小    private $_memoryReserve;//备用内存    /**     * 方      法:注册自定义错误、异常拦截器     * 参      数:void     * 返      回:void     */    public function register()    {        ini_set('display_errors', 0);        set_exception_handler(array($this, 'handleException'));//截获未捕获的异常        set_error_handler(array($this, 'handleError'));//截获各种错误 此处切不可掉换位置        //留下备用内存 供后面拦截致命错误使用        $this->memoryReserveSize > 0 && $this->_memoryReserve = str_repeat('x', $this->memoryReserveSize);        register_shutdown_function(array($this, 'handleFatalError'));//截获致命性错误    }    /**     * 方      法:取消自定义错误、异常拦截器     * 参      数:void     * 返      回:void     */    public function unregister()    {        restore_error_handler();        restore_exception_handler();    }    /**     * 方      法:处理截获的未捕获的异常     * 参      数:Exception $exception     * 返      回:void     */    public function handleException($exception)    {        $this->unregister();        try        {            $this->logException($exception);            exit(1);        }        catch(Exception $e)        {            exit(1);        }    }    /**     * 方      法:处理截获的错误     * 参      数:int     $code 错误代码     * 参      数:string $message 错误信息     * 参      数:string $file 错误文件     * 参      数:int     $line 错误的行数     * 返      回:boolean     */    public function handleError($code, $message, $file, $line)    {        //该处思想是将错误变成异常抛出 统一交给异常处理函数进行处理        if((error_reporting() & $code) && !in_array($code, array(E_NOTICE, E_WARNING, E_USER_NOTICE, E_USER_WARNING, E_DEPRECATED)))        {//此处只记录严重的错误 对于各种WARNING NOTICE不作处理            $exception = new errorHandlerException($message, $code, $code, $file, $line);            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);            array_shift($trace);//trace的第一个元素为当前对象 移除            foreach($trace as $frame)            {                if($frame['function'] == '__toString')                {//如果错误出现在 __toString 方法中 不抛出任何异常                    $this->handleException($exception);                    exit(1);                }            }            throw $exception;        }        return false;    }    /**     * 方      法:截获致命性错误     * 参      数:void     * 返      回:void     */    public function handleFatalError()    {        unset($this->_memoryReserve);//释放内存供下面处理程序使用        $error = error_get_last();//最后一条错误信息        if(errorHandlerException::isFatalError($error))        {//如果是致命错误进行处理            $exception = new errorHandlerException($error['message'], $error['type'], $error['type'], $error['file'], $error['line']);            $this->logException($exception);            exit(1);        }    }    /**     * 方      法:获取服务器IP     * 参      数:void     * 返      回:string     */    final public function getServerIp()    {        $serverIp = '';        if(isset($_SERVER['SERVER_ADDR']))        {            $serverIp = $_SERVER['SERVER_ADDR'];        }        elseif(isset($_SERVER['LOCAL_ADDR']))        {            $serverIp = $_SERVER['LOCAL_ADDR'];        }        elseif(isset($_SERVER['HOSTNAME']))        {            $serverIp = gethostbyname($_SERVER['HOSTNAME']);        }        else        {            $serverIp = getenv('SERVER_ADDR');        }                        return $serverIp;    }    /**     * 方      法:获取当前URI信息     * 参      数:void     * 返      回:string $url     */    public function getCurrentUri()    {        $uri = '';        if($_SERVER ["REMOTE_ADDR"])        {//浏览器浏览模式            $uri = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];        }        else        {//命令行模式            $params = $this->argvs;            $uri = $params[0];            array_shift($params);            for($i = 0, $len = count($params); $i < $len; $i++)            {                $uri .= ' ' . $params[$i];            }        }        return $uri;    }    /**     * 方      法:记录异常信息     * 参      数:errorHandlerException $e 错误异常     * 返      回:boolean 是否保存成功     */    final public function logException($e)    {        $error = array(                        'add_time'     =>     time(),                        'title'     =>     errorHandlerException::getName($e->getCode()),//这里获取用户友好型名称                        'message'     =>     array(),                        'server_ip' =>     $this->getServerIp(),                        'code'         =>     errorHandlerException::getLocalCode($e->getCode()),//这里为各种错误定义一个编号以便查找                        'file'         =>  $e->getFile(),                        'line'         =>     $e->getLine(),                        'url'        =>  $this->getCurrentUri(),                    );        do        {            //$e->getFile() . ':' . $e->getLine() . ' ' . $e->getMessage() . '(' . $e->getCode() . ')'            $message = (string)$e;            $error['message'][] = $message;        } while($e = $e->getPrevious());        $error['message'] = implode("\r\n", $error['message']);        $this->logError($error);    }    /**     * 方      法:记录异常信息     * 参      数:array $error = array(     *                                    'time' => int,     *                                    'title' => 'string',     *                                    'message' => 'string',     *                                    'code' => int,     *                                    'server_ip' => 'string'     *                                     'file'     =>  'string',     *                                    'line' => int,     *                                    'url' => 'string',     *                                );     * 返      回:boolean 是否保存成功     */    public function logError($error)    {        /*这里去实现如何将错误信息记录到日志*/    }}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值