PHP 怎么PHP 错误日志记录

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 错误日志记录

  1. php.ini 配置
  2. 运行时设置错误日志
  3. 使用 error_log() 函数
  4. 自定义错误处理函数
  5. 使用异常处理记录错误
  6. 完整的日志类示例
  7. 日志文件管理
  8. 最佳实践
  9. 注意事项

我来详细介绍 PHP 错误日志记录的几种方法:

php.ini 配置

基本配置

# 开启错误日志
log_errors = On
# 指定错误日志文件路径
error_log = /var/log/php_errors.log
# 设置错误报告级别
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
# 显示错误(开发环境开启,生产环境关闭)
display_errors = Off
# 记录最大错误数
log_errors_max_len = 1024

常用错误级别

// 所有错误
error_reporting(E_ALL);
// 除了提示信息
error_reporting(E_ALL & ~E_NOTICE);
// 严格模式(推荐)
error_reporting(E_ALL | E_STRICT);

运行时设置错误日志

// 开启错误日志
ini_set('log_errors', 1);
// 设置日志文件路径
ini_set('error_log', '/path/to/error.log');
// 设置错误报告级别
ini_set('error_reporting', E_ALL);

使用 error_log() 函数

// 简单记录
error_log("发生了一个错误");
// 记录到指定文件
error_log("数据库连接失败", 3, "/var/log/db_errors.log");
// 发送到系统日志
error_log("系统错误", 0);
// 发送到邮件(不推荐)
error_log("严重错误", 1, "[email protected]");

自定义错误处理函数

// 自定义错误处理
function customErrorHandler($errno, $errstr, $errfile, $errline) {
    $logMessage = sprintf(
        "[%s] 错误级别: %d - %s 在文件 %s 第 %d 行\n",
        date('Y-m-d H:i:s'),
        $errno,
        $errstr,
        $errfile,
        $errline
    );
    // 写入日志
    error_log($logMessage, 3, '/var/log/custom_errors.log');
    // 返回 true 阻止 PHP 默认错误处理
    return true;
}
// 注册自定义错误处理器
set_error_handler("customErrorHandler");

使用异常处理记录错误

try {
    // 可能出错的代码
    $result = 10 / 0;
} catch (Exception $e) {
    // 记录错误信息
    error_log("捕获异常: " . $e->getMessage());
    error_log("文件: " . $e->getFile() . " 行: " . $e->getLine());
}

完整的日志类示例

class Logger {
    private $logFile;
    private $logLevel;
    const DEBUG = 1;
    const INFO = 2;
    const WARNING = 3;
    const ERROR = 4;
    public function __construct($logFile, $logLevel = self::INFO) {
        $this->logFile = $logFile;
        $this->logLevel = $logLevel;
    }
    public function log($message, $level = self::INFO) {
        if ($level < $this->logLevel) {
            return;
        }
        $levelNames = [
            self::DEBUG => 'DEBUG',
            self::INFO => 'INFO',
            self::WARNING => 'WARNING',
            self::ERROR => 'ERROR'
        ];
        $logMessage = sprintf(
            "[%s] [%s] %s\n",
            date('Y-m-d H:i:s'),
            $levelNames[$level],
            $message
        );
        error_log($logMessage, 3, $this->logFile);
    }
    public function debug($message) {
        $this->log($message, self::DEBUG);
    }
    public function info($message) {
        $this->log($message, self::INFO);
    }
    public function warning($message) {
        $this->log($message, self::WARNING);
    }
    public function error($message) {
        $this->log($message, self::ERROR);
    }
}
// 使用示例
$logger = new Logger('/var/log/app.log', Logger::INFO);
$logger->debug("这条不会被记录");
$logger->info("应用启动成功");
$logger->warning("内存使用过高");
$logger->error("数据库连接失败");

日志文件管理

class LogManager {
    private $logFile;
    private $maxSize;
    private $backupCount;
    public function __construct($logFile, $maxSize = 10485760, $backupCount = 5) {
        $this->logFile = $logFile;
        $this->maxSize = $maxSize;
        $this->backupCount = $backupCount;
    }
    public function write($message) {
        // 检查文件大小并轮转
        $this->rotateIfNeeded();
        return error_log($message, 3, $this->logFile);
    }
    private function rotateIfNeeded() {
        if (!file_exists($this->logFile)) {
            return;
        }
        if (filesize($this->logFile) < $this->maxSize) {
            return;
        }
        // 删除最旧的备份
        $oldestBackup = $this->logFile . '.' . $this->backupCount;
        if (file_exists($oldestBackup)) {
            unlink($oldestBackup);
        }
        // 重命名现有备份
        for ($i = $this->backupCount - 1; $i >= 1; $i--) {
            $oldFile = $this->logFile . '.' . $i;
            $newFile = $this->logFile . '.' . ($i + 1);
            if (file_exists($oldFile)) {
                rename($oldFile, $newFile);
            }
        }
        // 重命名当前日志文件
        rename($this->logFile, $this->logFile . '.1');
    }
}

最佳实践

// 生产环境配置
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_reporting', E_ALL & ~E_NOTICE & ~E_STRICT);
// 记录带上下文的错误
$context = [
    'user_id' => 123,
    'ip' => $_SERVER['REMOTE_ADDR'],
    'url' => $_SERVER['REQUEST_URI']
];
error_log("登录失败,上下文:" . json_encode($context));
// 使用框架的日志系统(如 Monolog)
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$logger = new Logger('app');
$logger->pushHandler(new StreamHandler('/var/log/app.log', Logger::WARNING));
$logger->error('数据库错误', ['exception' => $e]);

注意事项

  1. 确保日志目录可写
  2. 生产环境关闭 display_errors
  3. 定期清理日志文件
  4. 考虑日志分级
  5. 敏感信息不要记录日志
  6. 使用日志轮转避免文件过大

这样就能有效地记录和管理 PHP 错误日志了。

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