Я делаю файл журнала, который регистрируется следующим образом:
[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";
Файлы журнала могут быть довольно большими. 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);
В зависимости от того, что вы можете разрешить в сообщении об ошибке, ваш подход может дать или не дать больше ошибок / предупреждений, чем фактических строк журнала, потому что вы ищете только совпадение подстроки в каждой строке. Такой что бревно [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";
Вы можете использовать вызов функции PHP substr_count()
чтобы посчитать количество совпадений строк внутри строки.
$logs = file( $complete_filename );
$totalErrors = substr_count($logs, '[Error]');
$totalWarnings = substr_count($logs, '[warning]');
echo $totalWarnings . ' warnings and ' . $totalErrors . ' errors';