异常报警方案与实施_1

463 阅读4分钟

异常检测&异常处理&报警方案

简介

what

code是人写的,难免会出bug,出bug也就要人修bug。

写code-》出bug/修bug -》写code

why

保证系统稳定性,及时排查与修复。

how

异常处理如下步骤:

1. 检测异常:程序执行过程中,如果发现异常情况,需要检测并识别出异常。
2. 抛出异常:如果检测到异常情况,需要抛出异常并通知调用者。
3. 捕获异常:调用者需要捕获抛出的异常,并进行相应的处理。
4. 处理异常:根据不同的异常情况,进行相应的处理,例如输出错误信息、记录日志、重新尝试等。
5. 报告异常:在处理异常之后,需要向用户或系统管理员报告异常情况,以便进行进一步的处理或修复。

1 ~ 3是检测捕获,4 ~ 5做异常处理。

以下是程序异常处理的一般方案:
1. 日志记录:在程序中添加日志记录功能,记录程序运行时的异常情况,包括异常类型、发生时间、异常代码等信息。
2. 报警机制:设置异常报警机制,当程序发生异常时,自动发送报警通知给相关负责人或团队,比如短信、邮件、微信等方式。
3. 异常监控:使用监控工具对程序运行状态进行持续监控,及时发现异常情况。
4. 人工巡检:定期进行人工巡检,检查程序运行状态和日志,找出异常情况并及时处理。
5. 自动化处理:对于一些已知的异常情况,可以设置自动化处理方案,自动重启程序或进行其他操作,减少对人工干预的依赖。(如超付款,自动退款)
6. 预警机制:在程序达到一定阈值时,设置预警机制,通知相关人员进行处理,避免程序崩溃导致业务中断。(服务器各项参数阀值)

异常处理(包含检测)

种类

PHP的异常

种类

php.ini的error_reporting有多少种

PHP.ini的error_reporting有多种设置选项,以下是一些常见的:

- E_ALL:显示所有错误级别
- E_ERROR:显示严重错误
- E_WARNING:显示警告
- E_PARSE:显示语法解析错误
- E_NOTICE:显示非致命错误
- E_STRICT:显示代码不符合严格标准的警告
- E_DEPRECATED:显示弃用的函数或特性的警告

此外,还可以使用数字组合来设置多个错误级别,如:

- 0:禁用所有错误报告
- 1:显示致命错误
- 2:显示警告和致命错误
- 3:显示所有错误,除了注意事项

总的说来,PHP.ini的error_reporting有许多不同的选项,可以根据需要进行设置。

来自php.ini的建议

; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT

异常类

Predefined Exceptions(提前定义好的类)

www.php.net/manual/en/r…

如何设置

php.ini异常设置相关

php.ini 是 PHP 的配置文件,通过修改它可以设置 PHP 的各种参数,包括异常设置。以下是一些常见的 PHP.ini 异常设置:

1. error_reporting:设置 PHP 报告哪些级别的错误。可以设置为 E_ALL(所有错误)、E_ERROR(致命错误)等。

2. display_errors:设置是否在网页中显示错误信息。可以设置为 OnOff3. log_errors:设置是否将错误信息记录到日志文件中。可以设置为 OnOff4. error_log:设置错误信息记录的日志文件路径。

5. display_startup_errors:设置是否在网页中显示启动时的错误信息。可以设置为 OnOff6. track_errors:设置是否在 $php_errormsg 变量中记录最近一次的错误信息。可以设置为 OnOff7. html_errors:设置是否在网页中以 HTML 格式显示错误信息。可以设置为 OnOff8. ignore_repeated_errors:设置是否忽略重复错误信息。可以设置为 OnOff9. ignore_repeated_source:设置是否忽略重复错误信息的来源。可以设置为 OnOff10. report_memleaks:设置是否报告内存泄漏。可以设置为 OnOff。

这些设置可以通过修改 php.ini 文件来进行配置。修改完成后需要重启 Web 服务器才能生效。

级别

分两大类=》紧急、非紧急。

格式

程序记录日志的格式一般包括以下内容:

1. 时间戳:记录日志的时间,格式一般为年月日时分秒毫秒。
2. 日志级别:记录日志的等级,包括 DEBUG、INFO、WARN、ERROR 等,用于区分日志的重要程度。
3. 日志来源:记录日志的来源,例如程序模块或函数名。
4. 日志内容:记录日志的具体内容,包括异常信息、操作记录、业务数据等。
5. 日志附加信息:记录日志的其他信息,例如线程ID、进程ID、客户端IP等。
6. 日志分隔符:用于分隔不同的日志记录,一般为换行符或特殊字符。

例如,一条典型的程序日志记录格式如下:
2021-10-01 12:00:00.123 INFO [AccountService] User login successfully. UserID: 123456. ClientIP: 192.168.0.1

其中,时间戳为 2021 年 10 月 1 日 12 点 0 分 0 秒 123 毫秒,日志级别为 INFO,日志来源为 AccountService,记录了用户登录成功的信息,包括用户ID和客户端IP。

PHP 的 捕获

thinkphp5.1举例

//thinkphp5.1 thinkphp/library/think/Error.php 32line
    /**
     * 注册异常处理
     * @access public
     * @return void
     */
    public static function register()
    {
        error_reporting(E_ALL);
        set_error_handler([__CLASS__, 'appError']);
        set_exception_handler([__CLASS__, 'appException']);
        register_shutdown_function([__CLASS__, 'appShutdown']);
    }

set_error_handler能捕获E_STRICT的异常: www.php.net/manual/zh/f…

set_exception_handler能捕获除了set_error_handler之外的的异常: www.php.net/manual/zh/f…

**register_shutdown_function顾名思义就是与客户端断开连接都会调用

报警方案

主动推送

程序异常捕获直接推送(钉钉、短信),show code

<?php

namespace app\common\service;

use OneHour\DingDing\Robot;
use think\facade\Cache;

class DingdingService
{
    /**
     * @var null
     */
    private static $instance = null;
    /**
     * @var Robot
     */
    private $robot = null;

    /**
     *
     */
    private function __construct()
    {
        $this->robot = (new Robot(env('DINGDING_ACCESS_TOKEN')));
    }

    /**
     * @return DingdingService|null
     */
    static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * @param string $content
     *
     * @throws \OneHour\DingDing\exception\DingDingParamException
     */
    public function commonSend(string $content)
    {
        if($time = $this->threshold($content)){
            $this->robot->send('[告警]常规异常通知' . $content . ', 出现次数: ' . $time, '');
        }
    }

    /**
     * @param string $content
     * @param int    $noticeGapTime
     *
     * @return bool
     */
    public function threshold(string $content,int $noticeGapTime = 10)
    {
        $key = md5($content);
        $rst = Cache::get($key);
        if($rst){
            Cache::inc($key,1);
            if($rst % $noticeGapTime == 0){
                return $rst;
            }
            return false;
        }else{
            Cache::set($key,1,60 * 10);
            return true;
        }
    }
}

被动推送

有个日志库,第三方数据分析处理,满足条件异常通知。市面上常用的方案有日志存在mongoDB、ELK分析。

基于阿里云的 日志服务SLS 的方案

ELK搭建成本高(Java),低成本易上手选阿里云的日志服务SLS。

记录本地-》采集 -》SLS分析 -》阀值报警 -》钉钉/短信

效果:

课后作业

1、下面程序执行后的输出错误类型分别是?

$i=null;

//1
$i->1111;

//2
$i->a;

//3
$i = [1,2,3];
$i[3];

  • 1、Notice、Notice、Notice
  • 2、Parse error、Notice、Notice
  • 3、Notice、Parse error、Notice
  • 4、Notice、Notice、Parse error

2、下面程序执行后的输出错误类型是?

function test($v,$k){
    //todo test
}
test(1);
  • 1、Error
  • 2、Notice
  • 3、Parse error

3、下面程序执行后输出?

function exception_handler(Throwable $exception) {
    echo "Uncaught exception: " , $exception->getMessage(), "\n";
}
function error_handler($errno, $errstr, $errfile, $errline) {
    echo "Uncaught error: " , $errno, "\n";
}
set_error_handler('error_handler');
set_exception_handler('exception_handler');
  
$a=null;
$a->b;
echo "Not Executed\n";
  • 1、
Uncaught exception: Uncaught Exception
  • 2、
Uncaught error: 8
  • 3、
Uncaught error: 8
Not Executed