PHP 怎么PHP 告警规则

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 告警规则

  1. 最基础的:错误报告级别控制(Error Reporting Rules)
  2. 自定义错误处理函数(实现“告警规则引擎”)
  3. 异常处理规则(Try-Catch + 自定义异常类)
  4. 生产环境常用告警规则实现方案
  5. 完整的小型规则引擎示例
  6. 总结:选择哪种方案?

在 PHP 中处理“告警规则”(通常指错误报告、异常处理、日志监控和报警触发),没有一个内置的“告警规则引擎”,但可以通过以下层次化的机制来实现类似效果。

我会从开发调试生产监控,按层级说明最常用的做法。


最基础的:错误报告级别控制(Error Reporting Rules)

这是 PHP 自带的“告警开关”,控制哪些错误应该显示/记录。

常见规则配置(php.ini 或运行时):

// 开发环境:显示所有错误
error_reporting(E_ALL);
// 生产环境:除了通知和弃用警告,其他都记录但不显示
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT);

更严格的规则:

// 只记录致命错误和语法错误
error_reporting(E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR);

控制是否显示到屏幕:

ini_set('display_errors', 0);  // 生产关闭
ini_set('display_errors', 1);  // 开发开启

规则本质:用位运算组合不同的错误级别常量。


自定义错误处理函数(实现“告警规则引擎”)

你可以定义自己的函数,根据错误类型、文件、行号、消息内容等条件,决定是否触发告警。

function customErrorHandler($severity, $message, $file, $line) {
    // 定义规则:只有 E_WARNING 以上才记录
    if ($severity >= E_WARNING) {
        $log = sprintf("[%s] %s in %s:%d\n", 
                       date('Y-m-d H:i:s'), $message, $file, $line);
        // 规则1:如果错误包含 "database" 关键字,立即发邮件
        if (stripos($message, 'database') !== false) {
            mail('[email protected]', 'Database Error', $log);
        }
        // 规则2:如果是 E_ERROR 级别,写入告警表
        if ($severity === E_ERROR) {
            file_put_contents('/var/log/php_critical.log', $log, FILE_APPEND);
            // 可调用 webhook
        }
        // 规则3:同一个文件错误超过 5 次,静默忽略
        // (需要配合计数器和缓存实现)
    }
    // 返回 true 表示已处理,阻止 PHP 默认处理
    return true;
}
set_error_handler('customErrorHandler');

规则类型举例

  • 按严重级别(Fatal / Warning / Notice)
  • 按错误消息关键词(SQL、Timeout、Permission denied)
  • 按文件路径(只监控 /app/controllers/ 目录)
  • 按频率(同一错误 N 次/分钟 才告警)
  • 按用户(仅管理员可见的错误提升告警)

异常处理规则(Try-Catch + 自定义异常类)

现代 PHP 更推荐使用异常(Exception)来处理可预见的“告警”。

class BusinessRuleException extends Exception {}
function processOrder($amount) {
    if ($amount < 0) {
        throw new BusinessRuleException("订单金额不能为负");
    }
    if ($amount > 10000) {
        // 触发告警规则:大额订单需人工审核
        triggerAlert('large_order', ['amount' => $amount]);
    }
}
// 全局异常处理规则
set_exception_handler(function($exception) {
    $ruleMap = [
        BusinessRuleException::class => 'notify_team',
        PDOException::class => 'notify_admin_and_retry',
    ];
    $handler = $ruleMap[get_class($exception)] ?? 'default_handler';
    call_user_func($handler, $exception);
});

生产环境常用告警规则实现方案

日志 + 外部监控(最常用)

PHP 只负责写结构化日志,规则解析交给外部系统。

日志规则示例(Monolog + 自定义处理器):

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\NativeMailerHandler;
$log = new Logger('app');
$log->pushHandler(new StreamHandler('/var/log/app.log', Logger::WARNING));
// 规则:WARNING 级别且包含 "timeout" 就发邮件
$mailHandler = new NativeMailerHandler(
    '[email protected]', 
    'Alert', 
    '[email protected]', 
    Logger::WARNING
);
// 使用处理器装饰器过滤
$mailHandler->pushProcessor(function ($record) {
    if (strpos($record['message'], 'timeout') === false) {
        return false; // 不处理
    }
    return $record;
});
$log->pushHandler($mailHandler);

健康检查端点 + 第三方告警服务

编写一个 /health 接口,返回系统状态码和指标:

// health.php
$checks = [
    'database' => checkDatabaseConnection(),
    'cache'    => pingRedis(),
    'disk'     => disk_free_space('/') > 500*1024*1024,
];
$status = 200;
foreach ($checks as $key => $ok) {
    if (!$ok) {
        $status = 500;
        // 规则:连续 3 次失败才告警(存储在 APCu 中)
        $failures = apcu_inc("health_$key");
        if ($failures >= 3) {
            trigger_external_alert("$key 不可用");
        }
    } else {
        apcu_store("health_$key", 0);
    }
}
http_response_code($status);
echo json_encode($checks);

配合 Prometheus + AlertmanagerUptime Robot 等外部系统,根据 HTTP 状态码触发告警。


完整的小型规则引擎示例

如果你需要灵活的自定义规则,可以这样设计:

class AlertRule {
    public string $name;
    public int $minSeverity;       // 最低错误级别
    public ?string $pattern;       // 消息匹配正则
    public ?int $rateLimitSeconds; // 限流秒数
    public callable $action;       // 触发动作
}
class AlertManager {
    private array $rules = [];
    private array $rateLimitCache = [];
    public function addRule(AlertRule $rule): void {
        $this->rules[] = $rule;
    }
    public function evaluate(\Throwable $e): void {
        $message = $e->getMessage();
        $severity = ($e instanceof \Error) ? E_ERROR : E_WARNING;
        foreach ($this->rules as $rule) {
            if ($severity < $rule->minSeverity) continue;
            if ($rule->pattern && !preg_match($rule->pattern, $message)) continue;
            // 频率限制
            if ($rule->rateLimitSeconds) {
                $key = $rule->name . '_' . md5($message);
                $last = $this->rateLimitCache[$key] ?? 0;
                if (time() - $last < $rule->rateLimitSeconds) continue;
                $this->rateLimitCache[$key] = time();
            }
            call_user_func($rule->action, $e);
        }
    }
}
// 使用
$manager = new AlertManager();
$manager->addRule(new AlertRule(
    name: 'database_alert',
    minSeverity: E_WARNING,
    pattern: '/database.*timeout/i',
    rateLimitSeconds: 300, // 5分钟一次
    action: fn($e) => mail(...),
));

选择哪种方案?

场景 推荐方式
开发阶段调试 error_reporting + display_errors
简单项目告警 自定义错误处理器 + 邮件
大型项目 Monolog 结构化日志 + 外部监控系统
高灵活规则需求 你自己写一个 AlertRule 引擎
无代码侵入 PHP 写 /health 端点 + 外部看门狗

提示:真正的“告警规则”建议交给外部系统(如 Prometheus、Datadog、Sentry),PHP 只负责记录错误信息暴露健康指标,因为规则管理、去重、升级、通知渠道这些功能在专用系统中实现更成熟。

抱歉,评论功能暂时关闭!