本文目录导读:

在PHP项目中实现告警通知,通常需要结合监控数据的采集、告警规则的判断以及多渠道通知的发送,下面我会从简单到复杂,介绍几种常见且实用的实现方案。
最简方案:直接发送通知
适用于小项目或临时监控,当检测到异常时,直接调用通知API。
<?php
class AlertManager {
// 发送飞书/钉钉/企微机器人消息
public function sendWebhook($webhookUrl, $message) {
$data = [
'msgtype' => 'text',
'text' => ['content' => $message]
];
$ch = curl_init($webhookUrl);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5
]);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
// 发送邮件告警
public function sendEmail($to, $subject, $body) {
$headers = [
'MIME-Version: 1.0',
'Content-type: text/html; charset=utf-8',
'From: monitor@yourdomain.com'
];
return mail($to, $subject, $body, implode("\r\n", $headers));
}
// 发送短信(需集成第三方服务:阿里云短信、腾讯云短信等)
public function sendSMS($phone, $message) {
// 集成第三方SDK,
// $sms = new AliyunSmsClient();
// $sms->send($phone, $message);
}
}
// 使用示例
$alert = new AlertManager();
if ($errorRate > 0.05) {
$alert->sendWebhook('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx',
"【告警】错误率过高: {$errorRate}%");
}
结构化方案:告警等级 + 通知策略
适用于需要灵活配置的场景。
<?php
class AlertRule {
public $metric; // 指标名称
public $operator; // 操作符 >, <, >=, <=, ==
public $threshold; // 阈值
public $duration; // 持续时间(秒)
public $level; // critical, warning, info
public $channels; // ['webhook', 'email', 'sms']
}
class AlertManager {
private $rules = [];
private $history = []; // 记录告警历史,避免重复通知
public function addRule(AlertRule $rule) {
$this->rules[] = $rule;
}
public function evaluate($metrics) {
foreach ($this->rules as $rule) {
$value = $metrics[$rule->metric] ?? null;
if ($value === null) continue;
if ($this->compare($value, $rule->operator, $rule->threshold)) {
$this->triggerAlert($rule, $value);
}
}
}
private function compare($actual, $operator, $threshold) {
switch ($operator) {
case '>': return $actual > $threshold;
case '<': return $actual < $threshold;
case '>=': return $actual >= $threshold;
case '<=': return $actual <= $threshold;
case '==': return $actual == $threshold;
}
return false;
}
private function triggerAlert(AlertRule $rule, $value) {
$key = $rule->metric;
$now = time();
// 避免重复告警(例如5分钟内不重复通知)
if (isset($this->history[$key]) &&
($now - $this->history[$key]) < 300) {
return;
}
$message = sprintf(
"[%s] 告警: %s = %s (阈值: %s %s)",
strtoupper($rule->level),
$rule->metric,
$value,
$rule->operator,
$rule->threshold
);
// 根据级别和配置发送通知
if ($rule->level === 'critical') {
$this->sendEmail('admin@company.com', '严重告警', $message);
$this->sendSMS('13800138000', $message);
}
$this->sendWebhook('https://hook.dingtalk.com/...', $message);
$this->history[$key] = $now;
}
}
企业级方案:集成第三方监控平台
对于生产环境,建议直接集成成熟的监控系统,它们提供了完善的数据采集、告警聚合、通知路由等功能。
Prometheus + AlertManager + PHP Exporter
<?php
// 在PHP中暴露监控指标
use Prometheus\CollectorRegistry;
use Prometheus\RenderTextFormat;
$registry = new CollectorRegistry();
// 自定义计数器
$counter = $registry->registerCounter(
'app',
'error_count',
'应用错误计数',
['severity']
);
// 记录错误
$counter->inc(['critical']);
// 暴露指标端点
if ($_GET['route'] === '/metrics') {
$renderer = new RenderTextFormat();
header('Content-Type: ' . RenderTextFormat::MIME_TYPE);
echo $renderer->render($registry->getMetricFamilySamples());
}
然后在AlertManager中配置规则:
# alertmanager.yml
groups:
- name: php-alerts
rules:
- alert: HighErrorRate
expr: rate(app_error_count_total[5m]) > 0.01
for: 5m
labels:
severity: critical
annotations:
summary: "错误率过高 ({{ $value }})"
集成阿里云/腾讯云云监控
<?php
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
class CloudMonitor {
public function sendAlert($metric, $value, $timestamp) {
AlibabaCloud::accessKeyClient('accessKeyId', 'accessKeySecret')
->regionId('cn-hangzhou')
->asDefaultClient();
try {
$result = AlibabaCloud::rpc()
->product('Cms')
->version('2019-01-01')
->action('PutCustomMetric')
->method('POST')
->options([
'query' => [
'MetricList.1.MetricName' => $metric,
'MetricList.1.Type' => '0',
'MetricList.1.Value' => $value,
'MetricList.1.Timestamp' => $timestamp
]
])
->request();
} catch (ClientException $e) {
echo $e->getErrorMessage();
}
}
}
最佳实践建议
告警聚合(避免告警风暴)
- 相同告警合并:5分钟内相同的告警只发送一次
- 告警升级机制:如果告警持续30分钟未恢复,升级通知级别
- 静默期:凌晨2-6点仅发送critical级别告警
多渠道通知策略
<?php
class NotificationRouter {
const CHANNELS = [
'critical' => ['sms', 'phone_call', 'webhook'],
'warning' => ['email', 'webhook'],
'info' => ['webhook']
];
public function notify($level, $message) {
foreach (self::CHANNELS[$level] as $channel) {
// 并行发送
$this->sendAsync($channel, $message);
}
}
private function sendAsync($channel, $message) {
// 使用队列或curl_multi实现异步发送
}
}
集成消息队列(高可用)
<?php
// 生产端:将告警事件推入队列
$redis->lPush('alert:queue', json_encode([
'type' => 'error_rate',
'value' => 0.15,
'timestamp' => time(),
'server' => gethostname()
]));
// 消费端:独立进程处理告警
while ($data = $redis->brPop('alert:queue', 5)) {
$alert = json_decode($data[1], true);
// 发送通知...
}
推荐的工具与库
| 库/工具 | 用途 | 推荐指数 |
|---|---|---|
| Prometheus PHP | 指标采集 | |
| Monolog | 日志告警渠道 | |
| 通知SDK | 阿里云通知 | |
| PHPMailer | 邮件发送 |
选择哪种方案取决于你的项目规模和团队能力:
- 小项目/个人项目:使用最简方案(飞书/钉钉Webhook)
- 中大型项目:使用结构化方案 + 消息队列
- 企业级项目:集成Prometheus + AlertManager或云厂商监控平台
建议先从一个简单的Webhook通知开始,后续根据业务需求逐步完善告警规则和通知渠道。