我正在制作一个日志文件,该文件以下列方式登录:
[08-12-2016 22:59:38.000000] [Error] Testing
[08-12-2016 22:59:45.000000] [Error] Testing
[08-12-2016 23:03:37.000000] [warning] Testing
我正在尝试创建一个可以读取日志文件中的总警告和总错误的函数。以下代码工作正常。问题是:有更好的方法吗?
$file = file( $complete_filename );
$totalErrors = 0;
$totalWarnings = 0;
foreach($file as $rows) {
if(strpos( $rows, "[warning]")) $totalWarnings ++;
if(strpos( $rows, "[Error]")) $totalErrors ++;
}
echo "$totalWarnings/$totalErrors";
答案 0 :(得分:2)
日志文件可能会变得非常大。 file
函数将整个文件读入内存。如果文件非常大,那么PHP可能会耗尽内存并且您将收到错误。
为避免内存不足,您可以使用fopen
获取文件句柄,然后使用fgets
一次读取一行:
$totalErrors = 0;
$totalWarnings = 0;
$fh = fopen($complete_filename, 'rb');
if ($fh) {
while (($line = fgets($fh, 4096)) !== false) {
if (strpos($line, "[Error]") !== false) {
$totalErrors++;
}
if (strpos($line, "[warning]") !== false) {
$totalWarnings++;
}
}
}
fclose($fh);
答案 1 :(得分:2)
根据您在错误消息中可能允许的内容,您的方法可能会或可能不会产生比实际日志行更多的错误/警告,因为您只在每行中查找子字符串匹配。这样[08-12-2016 22:59:38.000000] [Error] Testing [warning]
的日志行就会产生1行错误和1行警告。
您可以尝试使用正则表达式来更加勤奋。
$logResults = array_map(function($line) {
if (preg_match('/\[.*\]\s\[(Error|warning)\]/', $line, $match)) {
return $match[1];
}
}, file($logFileName));
$errors = array_filter($logResults, function($l) { return $l === 'Error'; });
$warnings = array_filter($logResults, function($l) { return $l === 'warning'; });
echo "Number of errors: $errors\n";
echo "Number of warnings: $warnings\n";
答案 2 :(得分:0)
您可以使用PHP函数调用substr_count()
来计算字符串中字符串匹配的数量。
$logs = file( $complete_filename );
$totalErrors = substr_count($logs, '[Error]');
$totalWarnings = substr_count($logs, '[warning]');
echo $totalWarnings . ' warnings and ' . $totalErrors . ' errors';