首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 錯誤捕獲與日誌記錄最佳實踐

     編輯:PHP 綜合知識

生產環境中完善的錯誤監控是系統穩定的基石。本文提供一個開箱即用的 PHP 錯誤處理器,統一捕獲致命錯誤、警告、解析錯誤等,自動記錄詳細上下文到日誌文件。

核心實現代碼

function error_reg() {
    $errorTypes = [
        E_ERROR       => 'ERROR',
        E_WARNING     => 'WARNING',
        E_PARSE       => 'PARSE',
        E_NOTICE      => 'NOTICE',
        E_CORE_ERROR  => 'CORE_ERROR',
        E_CORE_WARNING=> 'CORE_WARNING',
        E_COMPILE_ERROR=> 'COMPILE_ERROR',
        E_COMPILE_WARNING=> 'COMPILE_WARNING',
        E_USER_ERROR  => 'USER_ERROR',
        E_USER_WARNING=> 'USER_WARNING',
        E_USER_NOTICE => 'USER_NOTICE',
        E_STRICT      => 'STRICT',
        E_RECOVERABLE_ERROR => 'RECOVERABLE_ERROR',
        E_DEPRECATED  => 'DEPRECATED',
        E_USER_DEPRECATED => 'USER_DEPRECATED',
    ];

    // 1. 捕獲致命錯誤 (register_shutdown_function)
    register_shutdown_function(function () use ($errorTypes) {
        $error = error_get_last();
        if ($error && !in_array($error['type'], [E_NOTICE, E_STRICT, E_DEPRECATED])) {
            $msg = sprintf(
                "%s [%d]: %s in %s on line %d [%s]\n",
                $errorTypes[$error['type']] ?? 'UNKNOWN',
                $error['type'],
                $error['message'],
                $error['file'],
                $error['line'],
                date('Y-m-d H:i:s')
            );
            error_log($msg, 3, '/var/log/php_errors.log');
        }
    });

    // 2. 捕獲運行時錯誤 (set_error_handler)
    set_error_handler(function ($type, $msg, $file, $line) use ($errorTypes) {
        if (!in_array($type, [E_NOTICE, E_STRICT, E_DEPRECATED])) {
            $logMsg = sprintf(
                "%s [%d]: %s in %s on line %d [%s]\n",
                $errorTypes[$type] ?? 'UNKNOWN',
                $type,
                $msg,
                $file,
                $line,
                date('Y-m-d H:i:s')
            );
            error_log($logMsg, 3, '/var/log/php_errors.log');
        }
        return false; // 繼續執行 PHP 內置處理器
    }, E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
}

// 入口文件調用
error_reg();

關鍵設計解析

雙層捕獲機制

捕獲方式覆蓋範圍特點
register_shutdown_functionE_ERROR, E_PARSE, E_CORE_ERROR 等致命錯誤腳本結束前最後機會捕獲
set_error_handlerE_WARNING, E_NOTICE, E_USER_ERROR 等非致命錯誤實時攔截,可決定是否繼續執行

日誌格式標準化

[ERROR] [1]: Call to undefined function foo() in /var/www/index.php on line 15 [2024-01-15 10:30:45]
[WARNING] [2]: Division by zero in /var/www/calc.php on line 8 [2024-01-15 10:31:12]

包含:錯誤級別、錯誤碼、消息、文件、行號、時間戳,便於日誌分析工具解析。

生產環境增強建議

1. 日誌輪轉

// 使用 logrotate 配置
/var/log/php_errors.log {
    daily
    rotate 30
    compress
    missingok
    notifempty
    create 640 www-data adm
}

2. 錯誤分級告警

function error_reg() {
    // ... 
    $criticalTypes = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
    
    // 在記錄日誌後
    if (in_array($type, $criticalTypes)) {
        // 發送郵件/Slack/鉚釘告警
        alert_oncall($msg);
    }
}

3. 結構化日誌 (JSON)

$logData = [
    'level'     => $errorTypes[$type] ?? 'UNKNOWN',
    'code'      => $type,
    'message'   => $msg,
    'file'      => $file,
    'line'      => $line,
    'timestamp' => date('c'),
    'trace'     => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5),
    'request'   => [
        'uri'    => $_SERVER['REQUEST_URI'] ?? '',
        'method' => $_SERVER['REQUEST_METHOD'] ?? '',
        'ip'     => $_SERVER['REMOTE_ADDR'] ?? '',
    ],
];
error_log(json_encode($logData, JSON_UNESCAPED_UNICODE) . "\n", 3, $logFile);

4. 整合 Monolog (推薦)

use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\LineFormatter;

$log = new Logger('app');
$handler = new RotatingFileHandler('/var/log/app.log', 30, Logger::WARNING);
$handler->setFormatter(new LineFormatter("%datetime% %level_name% %message% %context% %extra%\n"));
$log->pushHandler($handler);

// 統一異常處理
set_exception_handler(function ($e) use ($log) {
    $log->critical($e->getMessage(), ['trace' => $e->getTraceAsString()]);
});

部署檢查清單

  • [ ] php.ini 設置 log_errors = On、error_log = /var/log/php_errors.log
  • [ ] 日誌目錄權限:chown www-data:adm /var/log && chmod 750 /var/log
  • [ ] 關閉顯示錯誤:display_errors = Off
  • [ ] 配置 logrotate 防止磁盤佔滿
  • [ ] 接入日誌分析平台 (ELK、Loki、騰訊云日誌服務等)

建立完善的錯誤監控體系,能將故障發現時間從「用戶投訴」縮短到「秒級告警」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved