异常检测&异常处理&报警方案
简介
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(提前定义好的类)
如何设置
php.ini异常设置相关
php.ini 是 PHP 的配置文件,通过修改它可以设置 PHP 的各种参数,包括异常设置。以下是一些常见的 PHP.ini 异常设置:
1. error_reporting:设置 PHP 报告哪些级别的错误。可以设置为 E_ALL(所有错误)、E_ERROR(致命错误)等。
2. display_errors:设置是否在网页中显示错误信息。可以设置为 On 或 Off。
3. log_errors:设置是否将错误信息记录到日志文件中。可以设置为 On 或 Off。
4. error_log:设置错误信息记录的日志文件路径。
5. display_startup_errors:设置是否在网页中显示启动时的错误信息。可以设置为 On 或 Off。
6. track_errors:设置是否在 $php_errormsg 变量中记录最近一次的错误信息。可以设置为 On 或 Off。
7. html_errors:设置是否在网页中以 HTML 格式显示错误信息。可以设置为 On 或 Off。
8. ignore_repeated_errors:设置是否忽略重复错误信息。可以设置为 On 或 Off。
9. ignore_repeated_source:设置是否忽略重复错误信息的来源。可以设置为 On 或 Off。
10. report_memleaks:设置是否报告内存泄漏。可以设置为 On 或 Off。
这些设置可以通过修改 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