本文目录导读:

我来为你介绍 PHP 项目异常监控上报的完整方案。
基础异常处理架构
1 自定义异常处理类
<?php
// src/Exception/ExceptionHandler.php
class ExceptionHandler
{
protected $logger;
protected $config;
public function __construct(array $config = [])
{
$this->config = $config;
$this->logger = new Logger($config['log_path'] ?? sys_get_temp_dir());
}
// 注册异常处理
public function register()
{
set_exception_handler([$this, 'handleException']);
set_error_handler([$this, 'handleError']);
register_shutdown_function([$this, 'handleFatalError']);
}
// 处理未捕获异常
public function handleException(Throwable $e)
{
$data = [
'type' => 'exception',
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString(),
'url' => $this->getCurrentUrl(),
'method' => $_SERVER['REQUEST_METHOD'] ?? 'cli',
'params' => $this->getRequestParams(),
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $this->getClientIp(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
];
// 记录日志
$this->logger->error($data['message'], $data);
// 上报监控系统
$this->report($data);
// 处理响应
$this->renderResponse($e);
}
// 处理普通错误
public function handleError($level, $message, $file = '', $line = 0)
{
if (error_reporting() & $level) {
$data = [
'type' => 'error',
'level' => $level,
'message' => $message,
'file' => $file,
'line' => $line,
'url' => $this->getCurrentUrl(),
'method' => $_SERVER['REQUEST_METHOD'] ?? 'cli',
'params' => $this->getRequestParams(),
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $this->getClientIp(),
];
// 记录日志
$this->logger->error($message, $data);
// 上报监控系统
$this->report($data);
}
return false;
}
// 处理致命错误
public function handleFatalError()
{
$error = error_get_last();
if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
$data = [
'type' => 'fatal_error',
'level' => $error['type'],
'message' => $error['message'],
'file' => $error['file'],
'line' => $error['line'],
'url' => $this->getCurrentUrl(),
'method' => $_SERVER['REQUEST_METHOD'] ?? 'cli',
'params' => $this->getRequestParams(),
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $this->getClientIp(),
];
$this->logger->error($error['message'], $data);
$this->report($data);
}
}
// 上报监控系统
protected function report(array $data)
{
// 配置上报
if (isset($this->config['report_enable']) && $this->config['report_enable']) {
$reporter = new ErrorReporter($this->config);
$reporter->send($data);
}
}
// 渲染响应
protected function renderResponse(Throwable $e)
{
if ($this->isApiRequest()) {
header('Content-Type: application/json');
echo json_encode([
'code' => $e->getCode() ?: 500,
'message' => $this->isDebug() ? $e->getMessage() : 'Internal Server Error',
'data' => null
]);
} else {
// 显示错误页面或跳转
http_response_code(500);
echo "An error occurred. Please try again later.";
}
exit;
}
// 辅助方法
protected function getCurrentUrl()
{
return $_SERVER['REQUEST_URI'] ?? 'cli';
}
protected function getRequestParams()
{
return [
'GET' => $_GET,
'POST' => $_POST,
'FILES' => $_FILES
];
}
protected function getClientIp()
{
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
protected function isApiRequest()
{
return isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false;
}
protected function isDebug()
{
return !empty($this->config['debug']);
}
}
2 日志记录类
<?php
// src/Log/Logger.php
class Logger
{
protected $logPath;
protected $levels = [
'DEBUG' => 100,
'INFO' => 200,
'WARNING' => 300,
'ERROR' => 400,
'CRITICAL' => 500
];
public function __construct($logPath)
{
$this->logPath = $logPath;
if (!is_dir($logPath)) {
mkdir($logPath, 0755, true);
}
}
public function error($message, array $context = [])
{
$this->write('ERROR', $message, $context);
}
public function info($message, array $context = [])
{
$this->write('INFO', $message, $context);
}
public function debug($message, array $context = [])
{
if (!empty($this->config['debug'])) {
$this->write('DEBUG', $message, $context);
}
}
protected function write($level, $message, array $context = [])
{
$date = date('Y-m-d');
$time = date('Y-m-d H:i:s');
$logFile = $this->logPath . "/{$date}.log";
$formattedMessage = sprintf(
"[%s] %s: %s %s\n",
$time,
$level,
$message,
$context ? json_encode($context, JSON_UNESCAPED_UNICODE) : ''
);
file_put_contents($logFile, $formattedMessage, FILE_APPEND | LOCK_EX);
}
}
监控上报服务
1 错误上报服务
<?php
// src/Monitoring/ErrorReporter.php
class ErrorReporter
{
protected $config;
protected $chunks = [];
public function __construct(array $config)
{
$this->config = $config;
$this->initChunks();
}
// 上报错误
public function send(array $data)
{
try {
// 根据配置选择上报方式
$transport = $this->config['transport'] ?? 'http';
switch ($transport) {
case 'http':
$this->sendHttp($data);
break;
case 'rabbitmq':
$this->sendRabbitMQ($data);
break;
case 'kafka':
$this->sendKafka($data);
break;
default:
$this->sendHttp($data);
}
} catch (\Exception $e) {
// 上报失败时记录到本地文件
$this->saveToFile($data);
}
}
// HTTP 上报
protected function sendHttp(array $data)
{
$url = $this->config['report_url'] ?? '';
if (empty($url)) {
return;
}
$payload = [
'project' => $this->config['project_name'] ?? 'php_project',
'environment' => $this->config['environment'] ?? 'production',
'version' => $this->config['version'] ?? '1.0.0',
'data' => $data
];
// 使用 cURL 异步上报(不阻塞主流程)
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . ($this->config['api_key'] ?? '')
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 1,
CURLOPT_CONNECTTIMEOUT => 1
]);
// 异步发送
if (function_exists('curl_multi_init')) {
$mh = curl_multi_init();
curl_multi_add_handle($mh, $ch);
curl_multi_exec($mh, $running);
curl_multi_remove_handle($mh, $ch);
curl_multi_close($mh);
} else {
curl_exec($ch);
curl_close($ch);
}
}
// 保存到本地文件(上报失败时的备份)
protected function saveToFile(array $data)
{
$backupPath = $this->config['backup_path'] ?? sys_get_temp_dir() . '/error_reports';
if (!is_dir($backupPath)) {
mkdir($backupPath, 0755, true);
}
$filename = $backupPath . '/error_' . date('Y-m-d_H-i-s') . '_' . uniqid() . '.json';
file_put_contents($filename, json_encode($data, JSON_UNESCAPED_UNICODE), LOCK_EX);
}
protected function initChunks()
{
// 初始化批处理
register_shutdown_function(function() {
$this->flushChunks();
});
}
protected function flushChunks()
{
// 批量发送错误
}
}
2 集成 Sentry 上报
<?php
// src/Monitoring/SentryReporter.php
class SentryReporter
{
protected $dsn;
protected $client;
public function __construct($dsn)
{
$this->dsn = $dsn;
$this->client = \Sentry\init([
'dsn' => $dsn,
'traces_sample_rate' => 0.2,
'environment' => 'production',
'release' => '1.0.0',
]);
}
// 手动上报错误
public function captureException(Throwable $e, array $context = [])
{
\Sentry\withScope(function (\Sentry\State\Scope $scope) use ($context) {
if (!empty($context)) {
$scope->setExtra('parameters', $context);
}
$scope->setTag('app', 'php_project');
$scope->setUser([
'id' => $context['user_id'] ?? null,
'ip' => $_SERVER['REMOTE_ADDR'] ?? null
]);
});
\Sentry\captureException($e);
}
// 上报消息
public function captureMessage($message, array $context = [])
{
\Sentry\withScope(function (\Sentry\State\Scope $scope) use ($context) {
if (!empty($context)) {
$scope->setExtras($context);
}
});
\Sentry\captureMessage($message);
}
// 上报自定义事件
public function captureEvent(array $event)
{
\Sentry\captureEvent($event);
}
}
完整的监控方案
1 项目配置
<?php
// config/monitoring.php
return [
// 异常处理配置
'exception' => [
'debug' => false, // 调试模式显示错误详情
'log_path' => storage_path('logs'),
'report_enable' => true, // 是否启用上报
],
// 日志配置
'log' => [
'path' => storage_path('logs'),
'level' => 'debug',
'max_files' => 30,
'channels' => [
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 14,
],
'error' => [
'driver' => 'single',
'path' => storage_path('logs/error.log'),
'level' => 'error',
],
'monitor' => [
'driver' => 'single',
'path' => storage_path('logs/monitor.log'),
'level' => 'debug',
]
]
],
// 上报配置
'report' => [
'transport' => 'http', // http, rabbitmq, kafka
'report_url' => env('REPORT_URL', 'https://your-monitor-server.com/api/errors'),
'api_key' => env('REPORT_API_KEY', ''),
'project_name' => 'my-php-project',
'environment' => env('APP_ENV', 'production'),
'version' => '1.0.0',
'backup_path' => storage_path('app/report_backup'),
'batch_size' => 100, // 批量上报大小
'interval' => 10, // 上报间隔(秒)
],
// Sentry 配置(可选)
'sentry' => [
'dsn' => env('SENTRY_DSN'),
'traces_sample_rate' => 0.2,
'environment' => env('APP_ENV', 'production'),
'release' => '1.0.0',
],
// 性能监控(可选)
'performance' => [
'slow_query_threshold' => 1000, // 慢查询阈值(毫秒)
'slow_request_threshold' => 2000, // 慢请求阈值(毫秒)
'report_memory_usage' => true,
]
];
2 初始化入口
<?php
// bootstrap.php
// 加载配置
$config = require 'config/monitoring.php';
// 初始化异常处理器
$handler = new ExceptionHandler($config['exception']);
$handler->register();
// 初始化 Sentry(如果配置了)
if (!empty($config['sentry']['dsn'])) {
$sentry = new SentryReporter($config['sentry']['dsn']);
// 将 Sentry 集成到异常处理
$handler->setLogger(function($data) use ($sentry) {
if (isset($data['message'])) {
$sentry->captureException(
new \RuntimeException($data['message'])
);
}
});
}
// 性能监控(可选)
$perfMonitor = new PerformanceMonitor($config['performance']);
$perfMonitor->start();
3 性能监控扩展
<?php
// src/Monitoring/PerformanceMonitor.php
class PerformanceMonitor
{
protected $startTime;
protected $startMemory;
protected $config;
public function __construct(array $config)
{
$this->config = $config;
$this->startTime = microtime(true);
$this->startMemory = memory_get_usage();
// 注册结束时的监控
register_shutdown_function([$this, 'stop']);
}
public function start()
{
$this->startTime = microtime(true);
$this->startMemory = memory_get_usage();
}
public function stop()
{
$duration = microtime(true) - $this->startTime;
$memoryUsed = memory_get_peak_usage() - $this->startMemory;
$data = [
'type' => 'performance',
'duration' => $duration * 1000, // 毫秒
'memory' => $memoryUsed,
'peak_memory' => memory_get_peak_usage(),
'url' => $_SERVER['REQUEST_URI'] ?? 'cli',
'method' => $_SERVER['REQUEST_METHOD'] ?? 'cli',
'timestamp' => date('Y-m-d H:i:s')
];
// 检查是否超过阈值
if ($data['duration'] > $this->config['slow_request_threshold']) {
$this->reportSlowRequest($data);
}
// 检查内存使用
if ($this->config['report_memory_usage'] && $data['memory'] > 100 * 1024 * 1024) {
$this->reportHighMemory($data);
}
}
protected function reportSlowRequest(array $data)
{
// 慢请求上报
$reporter = new ErrorReporter($this->config);
$reporter->send($data);
}
protected function reportHighMemory(array $data)
{
// 内存使用上报
$reporter = new ErrorReporter($this->config);
$reporter->send($data);
}
}
4 使用示例
<?php
// index.php
// 异常处理配置
$config = [
'debug' => false,
'log_path' => __DIR__ . '/logs',
'report_enable' => true,
'report_url' => 'https://monitor.example.com/api/errors',
'api_key' => 'your-api-key',
'project_name' => 'my-project',
'environment' => 'production'
];
// 注册异常处理
$handler = new ExceptionHandler($config);
$handler->register();
// 业务代码
try {
// 你的业务逻辑
$service = new UserService();
$user = $service->getUser(1);
// 手动异常捕获
if (!$user) {
throw new \Exception('User not found');
}
} catch (\Exception $e) {
// 可以手动处理或上报
$handler->handleException($e);
}
最佳实践建议
1 上报数据规范
// 统一错误格式
$errorSchema = [
'project' => 'string',
'environment' => 'production|staging|development',
'timestamp' => '2024-01-01 00:00:00',
'level' => 'DEBUG|INFO|WARNING|ERROR|CRITICAL',
'type' => 'exception|error|fatal_error',
'message' => '错误信息',
'class' => '异常类名',
'file' => '文件路径',
'line' => 123,
'trace' => '堆栈信息',
'url' => '请求URL',
'method' => 'GET|POST|PUT|DELETE',
'params' => [],
'user_id' => 12345,
'ip' => '192.168.1.1',
'user_agent' => '浏览器信息',
'request_id' => '唯一请求ID'
];
2 上报策略
- 分级上报:根据严重级别决定上报方式
- 去重处理:合并相同错误,避免重复上报
- 频率限制:控制上报频率,防止过载
- 失败重试:上报失败后自动重试
- 本地缓存:离线时暂存错误,联网后上报
3 监控指标体系
$metrics = [
'error_rate' => '错误率',
'error_count' => '错误数量',
'response_time' => '响应时间',
'throughput' => '吞吐量',
'memory_usage' => '内存使用',
'cpu_usage' => 'CPU使用',
'slow_queries' => '慢查询数量',
'slow_requests' => '慢请求数量',
'request_count' => '请求次数',
'active_users' => '活跃用户数'
];
这个方案提供了完整的 PHP 异常监控上报体系,你可以根据项目需求选择性地使用各个组件,建议从基础的异常处理和日志记录开始,逐步增加监控上报功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播