当系统发生异常的时候,比如redis连接异常、oss签名异常、数据库连接异常、支付宝或微信支付服务异常等,这些外部服务如果发生故障是非常严重的,所以需要尽快的进行人工干预;而有些业务方面的异常相对来说没有那么急迫,但是也需要查找原因尽快排除,为满足这两种需求,特设计了个告警机制。

类结构设计

\QQ20170118-164216@2x.png

BaseException继承与Exception,包含两个属性: sendEmail:是否发送邮件,sendSms是否发送短信,默认发送邮件,不发送短信


class BaseException extends \Exception
{
    public $sendEmail = false;
    public $sendSms = false;

    public function __construct($message, $code,$sendEmail = true, $sendSms = false,Exception $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->sendEmail = $sendEmail;
        $this->sendSms = $sendSms;
    }

}

SystemException和BusinessException是BaseException的两个子类,SystemException用于catch系统级别的异常,比如数据库、redis、oss连接等,由于支付业务重要性比较高,所以支付业务出现异常的时候也抛出系统异常,默认邮件和短信都发送,BusinessException是业务异常,比如数据不完整、请求参数不正确等,默认只发送邮件。


class SystemException extends BaseException
{

    public function __construct($message, $code = 500, $sendEmail = true, $sendSms = true, Exception $previous = null)
    {
        parent::__construct($message, $code, $sendEmail, $sendSms, $previous);
    }
}
class BusinessException extends BaseException
{
    //业务异常默认发送邮件,如不需要发送,$sendEmail设置为false
    public function __construct($message, $code = 500,$sendEmail = true,$sendSms = false,Exception $previous = null)
    {
        parent::__construct($message, $code,$sendEmail,$sendSms,$previous);
    }
}

Handler类用于异常捕获,项目中所有异常最终都会被Handler类捕获并捕获,可在跳转到错误页面之前通知管理员。


    public function render($request, Exception $e)
    {
        //通知管理员进行人工干预
        $this->noticeAdmin($request,$e);
        $errMsg = $e->getMessage();
        $exception = [
            'code' => $e->getCode(),
            'message' => $errMsg,
            'file' => $e->getFile(),
            'line' => $e->getLine(),
            'request_parameters' => json_encode($request->getQueryString()),
        ];
        //记录异常日志
        BLogger::getLogger(BLogger::LOG_ERROR)->error($exception);
        //跳转到通用错误页面
        return response()->view('errors.error', ['errMsg' => $errMsg]);
    }

    private function noticeAdmin($request, $exception)
    {
        //自定义异常类告警
        if($exception instanceof BaseException){
            $sendEmail = $exception->sendEmail;
            $sendSms = $exception->sendSms;
            //发送邮件通知
            if($sendEmail){
                $content = ExceptionReporter::getMailContent($request, $exception);
                ExceptionReporter::sendEmail($content);
            }
            //发送短信通知
            if($sendSms){
                $smsContent = '系统服务异常,请联系管理员处理。'.$exception->getMessage();
                ExceptionReporter::sendSms($smsContent);
            }
        }
    }

工具类:ExceptionReporter,用于组织邮件和短信内容,发送邮件,发送短信。

使用方法

实际业务中使用的时候根据业务需要判断是系统级异常还是业务级异常,直接抛出即可

throw new BusinessException('缺少XXX参数',500,false);

throw new SystemException("缺少统一支付接口必填参数trade_type!" . "<br>");

End