本文目录导读:

我来详细介绍PHP日志分析的完整方法:
常见PHP日志类型
错误日志
// php.ini配置 error_reporting = E_ALL display_errors = Off log_errors = On error_log = /var/log/php_errors.log
访问日志
通常由Web服务器(Nginx/Apache)记录
日志分析工具
命令行工具
# 实时查看日志
tail -f /var/log/php_errors.log
# 查找错误
grep "PHP Fatal error" /var/log/php_errors.log
# 统计错误类型
awk -F':' '{print $2}' /var/log/php_errors.log | sort | uniq -c
# 按时间查看
awk '/2024-01-15/ {print}' /var/log/php_errors.log
使用PHP分析日志
<?php
class LogAnalyzer {
private $logFile;
public function __construct($logFile) {
$this->logFile = $logFile;
}
// 分析错误类型统计
public function analyzeErrorTypes() {
$errors = [];
$handle = fopen($this->logFile, 'r');
while (($line = fgets($handle)) !== false) {
if (preg_match('/PHP (.*?):/', $line, $matches)) {
$type = $matches[1];
$errors[$type] = ($errors[$type] ?? 0) + 1;
}
}
fclose($handle);
return $errors;
}
// 按时间范围查询
public function getLogsByDate($startDate, $endDate) {
$logs = [];
$handle = fopen($this->logFile, 'r');
while (($line = fgets($handle)) !== false) {
if (preg_match('/\[(.*?)\]/', $line, $matches)) {
$date = $matches[1];
if ($date >= $startDate && $date <= $endDate) {
$logs[] = $line;
}
}
}
fclose($handle);
return $logs;
}
}
// 使用示例
$analyzer = new LogAnalyzer('/var/log/php_errors.log');
print_r($analyzer->analyzeErrorTypes());
?>
高级分析技术
使用正则表达式提取信息
<?php
function parsePhpLogLine($line) {
$pattern = '/^\[(\d{2}-\w{3}-\d{4} \d{2}:\d{2}:\d{2} UTC)\] PHP (.+?): (.+?) in (.+?) on line (\d+)$/';
if (preg_match($pattern, $line, $matches)) {
return [
'timestamp' => $matches[1],
'error_type' => $matches[2],
'message' => $matches[3],
'file' => $matches[4],
'line' => (int)$matches[5]
];
}
return null;
}
?>
聚合分析
<?php
function aggregateErrors($logFile) {
$errorsByFile = [];
$errorsByType = [];
$handle = fopen($logFile, 'r');
while (($line = fgets($handle)) !== false) {
$parsed = parsePhpLogLine($line);
if (!$parsed) continue;
// 按文件聚合
$file = $parsed['file'];
$errorsByFile[$file] = ($errorsByFile[$file] ?? 0) + 1;
// 按错误类型聚合
$type = $parsed['error_type'];
$errorsByType[$type] = ($errorsByType[$type] ?? 0) + 1;
}
fclose($handle);
return [
'by_file' => $errorsByFile,
'by_type' => $errorsByType
];
}
?>
可视化分析
生成简单报告
<?php
function generateReport($logFile, $outputFile) {
$analyzer = new LogAnalyzer($logFile);
// 获取分析结果
$errorsByType = $analyzer->analyzeErrorTypes();
arsort($errorsByType);
// 生成HTML报告
$html = "<html><head><title>PHP Error Report</title></head><body>";
$html .= "<h1>PHP Error Analysis Report</h1>";
$html .= "<table border='1'>";
$html .= "<tr><th>Error Type</th><th>Count</th></tr>";
foreach ($errorsByType as $type => $count) {
$html .= "<tr><td>$type</td><td>$count</td></tr>";
}
$html .= "</table></body></html>";
file_put_contents($outputFile, $html);
}
?>
实时监控
使用PHP Socket实时监控
<?php
function tailLog($logFile) {
$handle = fopen($logFile, 'r');
// 移动到文件末尾
fseek($handle, 0, SEEK_END);
while (true) {
usleep(100000); // 100ms
clearstatcache();
$currentPos = ftell($handle);
$fileSize = filesize($logFile);
if ($fileSize < $currentPos) {
// 文件被截断或轮转
fclose($handle);
$handle = fopen($logFile, 'r');
continue;
}
while (($line = fgets($handle)) !== false) {
if (strpos($line, 'PHP Fatal error') !== false) {
// 发送警报
sendAlert($line);
}
}
}
}
?>
最佳实践
日志规范化
<?php
// 自定义日志记录
function customLogger($message, $level = 'INFO') {
$logFormat = "[%s] [%s] %s - %s - Line: %d\n";
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$caller = $backtrace[0];
$logEntry = sprintf(
$logFormat,
date('Y-m-d H:i:s'),
$level,
$_SERVER['REMOTE_ADDR'] ?? 'CLI',
$message,
$caller['line'] ?? 'N/A'
);
error_log($logEntry, 3, '/var/log/custom_app.log');
}
?>
日志轮转配置
; php.ini log_rotate_max_files = 10 log_rotate_size = 100M
常用分析命令
# 统计各错误类型数量
awk '{print $4}' /var/log/php_errors.log | sort | uniq -c | sort -rn
# 获取最常出错的10个文件
grep -oP "in \K[^:]+" /var/log/php_errors.log | sort | uniq -c | sort -rn | head -10
# 查看特定日期的错误
grep "15/Jan/2024" /var/log/php_errors.log
# 监控并过滤特定错误
tail -f /var/log/php_errors.log | grep -i "database\|timeout\|fatal"
自动化脚本示例
<?php
// 自动清理和归档旧日志
$logFile = '/var/log/php_errors.log';
$archiveDir = '/var/log/archive/';
$maxSize = 100 * 1024 * 1024; // 100MB
if (file_exists($logFile) && filesize($logFile) > $maxSize) {
$archiveName = $archiveDir . 'php_errors_' . date('Ymd_His') . '.log';
rename($logFile, $archiveName);
// 压缩归档
exec("gzip $archiveName");
// 创建新日志文件
file_put_contents($logFile, '');
chmod($logFile, 0644);
}
?>
通过以上方法,你可以有效地分析PHP日志,快速定位问题,并建立完善的日志监控系统,根据实际需求选择合适的分析工具和方法。