本文目录导读:

为PHP项目设置错误监控是保障应用稳定性的关键步骤,以下是完整的实施指南,涵盖从基础配置到集成专业监控工具的全流程。
PHP 基础错误配置
php.ini 配置
; 开发环境 display_errors = On error_reporting = E_ALL ; 生产环境 display_errors = Off log_errors = On error_log = /var/log/php_errors.log error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
通过代码动态设置
// 生产环境安全配置
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
自定义错误处理函数
基本实现
// 设置自定义错误处理器
set_error_handler(function($severity, $message, $file, $line) {
// 记录错误
error_log("Error [$severity]: $message in $file on line $line");
// 根据错误级别决定是否抛出异常
if (error_reporting() & $severity) {
throw new ErrorException($message, 0, $severity, $file, $line);
}
});
// 设置未捕获异常处理器
set_exception_handler(function($exception) {
$message = "Uncaught Exception: " . $exception->getMessage() .
" in " . $exception->getFile() . " on line " . $exception->getLine();
error_log($message);
// 生产环境显示友好错误页面
if (php_sapi_name() !== 'cli') {
http_response_code(500);
include('error_pages/500.php');
}
exit(1);
});
// 确保脚本结束前错误被记录
register_shutdown_function(function() {
$error = error_get_last();
if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
error_log("Fatal Error: {$error['message']} in {$error['file']} on line {$error['line']}");
}
});
日志分类与管理
按级别分类记录
class AppLogger {
private $logDir;
public function __construct($logDir = '/var/log/app') {
$this->logDir = $logDir;
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
}
public function error($message, array $context = []) {
$this->log('error', $message, $context);
}
public function warning($message, array $context = []) {
$this->log('warning', $message, $context);
}
public function info($message, array $context = []) {
$this->log('info', $message, $context);
}
public function critical($message, array $context = []) {
$this->log('critical', $message, $context);
// 发送紧急通知
$this->sendAlert($message, $context);
}
private function log($level, $message, array $context = []) {
$logFile = $this->logDir . '/' . $level . '_' . date('Y-m-d') . '.log';
$timestamp = date('Y-m-d H:i:s');
$contextStr = !empty($context) ? ' | ' . json_encode($context) : '';
$logEntry = "[$timestamp] [$level] $message $contextStr\n";
file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
}
private function sendAlert($message, $context) {
// 集成邮件、Slack、短信等通知
// ...
}
}
集成专业监控工具
使用 Sentry
安装:
composer require sentry/sentry
配置初始化:
<?php
// config/sentry.php
use Sentry\SentrySdk;
use Sentry\State\Hub;
use Sentry\ClientBuilder;
// 初始化 Sentry
SentrySdk::getCurrentHub()->bindClient(
ClientBuilder::create([
'dsn' => 'https://your-public-key@your-org.ingest.sentry.io/project-id',
'environment' => $_ENV['APP_ENV'] ?? 'production',
'release' => '1.0.0',
'error_types' => E_ALL & ~E_DEPRECATED & ~E_STRICT,
'before_send' => function (\Sentry\Event $event): ?\Sentry\Event {
// 过滤敏感信息
$event->setExtra('ip', $_SERVER['REMOTE_ADDR'] ?? 'unknown');
return $event;
},
])->getClient()
);
捕获错误:
// 捕获所有错误
\Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
$scope->setUser([
'id' => $userId,
'email' => $userEmail,
]);
});
// 手动捕获异常
try {
// risky operation
} catch (\Exception $e) {
\Sentry\captureException($e);
}
// 捕获致命错误
register_shutdown_function(function () {
$error = error_get_last();
if ($error !== null) {
\Sentry\captureLastError();
}
});
使用 Airbrake
// 安装: composer require airbrake/phpbrake
$notifier = new \Airbrake\Notifier([
'projectId' => 12345,
'projectKey' => 'your-api-key',
'environment' => 'production'
]);
// 设置错误和异常处理器
$handler = new \Airbrake\ErrorHandler($notifier);
$handler->register();
使用日志聚合服务(ELK Stack)
// 发送日志到 Logstash
$context = [
'environment' => $_ENV['APP_ENV'],
'server' => gethostname(),
'request_id' => uniqid(),
];
openlog('myapp', LOG_PID | LOG_PERROR, LOG_LOCAL0);
syslog(LOG_ERR, "Database connection failed: " . $e->getMessage() . " " . json_encode($context));
closelog();
环境配置策略
配置文件分离
// config/error.php
class ErrorConfig {
public static function getConfig() {
$env = $_ENV['APP_ENV'] ?? 'production';
$configs = [
'development' => [
'display_errors' => true,
'error_reporting' => E_ALL,
'log_errors' => true,
'log_level' => 'debug'
],
'staging' => [
'display_errors' => false,
'error_reporting' => E_ALL & ~E_DEPRECATED,
'log_errors' => true,
'log_level' => 'info'
],
'production' => [
'display_errors' => false,
'error_reporting' => E_ALL & ~E_DEPRECATED & ~E_STRICT,
'log_errors' => true,
'log_level' => 'warning'
]
];
return $configs[$env] ?? $configs['production'];
}
}
// 应用配置
$config = ErrorConfig::getConfig();
ini_set('display_errors', $config['display_errors']);
error_reporting($config['error_reporting']);
框架集成示例
Laravel
// config/app.php 中的配置
'debug' => env('APP_DEBUG', false),
// app/Exceptions/Handler.php
public function register()
{
$this->reportable(function (Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
$this->renderable(function (NotFoundHttpException $e, $request) {
if ($request->expectsJson()) {
return response()->json(['error' => 'Resource not found'], 404);
}
return response()->view('errors.404', [], 404);
});
}
Symfony
# config/packages/monolog.yaml
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: grouped
grouped:
type: group
members: [streamed, sentry]
streamed:
type: stream
path: '%kernel.logs_dir%/%kernel.environment%.log'
level: debug
sentry:
type: service
id: Sentry\Monolog\Handler
最佳实践总结
| 层次 | 措施 | 优先级 |
|---|---|---|
| 1️⃣ | 合理配置 php.ini 和错误报告级别 |
必须 |
| 2️⃣ | 实现自定义错误与异常处理器 | 强烈建议 |
| 3️⃣ | 使用结构化日志(JSON格式) | 推荐 |
| 4️⃣ | 集成专业监控工具(Sentry/ELK) | 按需 |
| 5️⃣ | 设置实时告警(邮件/Slack) | 生产环境必须 |
| 6️⃣ | 定期审查日志并优化 | 持续维护 |
关键注意事项:
- 生产环境绝不可开启
display_errors - 日志文件必须做日志轮转(
logrotate) - 敏感信息过滤(密码、token、信用卡号等)
- 错误信息要包含上下文(请求ID、用户ID、会话信息)
- 定期测试错误监控系统是否正常工作
通过实施上述方案,你可以有效监控PHP项目的错误,及时发现问题并快速响应。