оптимизации методов чтения лог-файлов (logList, List404, ListSql)
This commit is contained in:
@@ -4,9 +4,10 @@
|
||||
* AVE.cms
|
||||
*
|
||||
* Класс, предназначенный для управления журналом системных сообщений
|
||||
* (Оптимизировано чтение для больших файлов логов)
|
||||
*
|
||||
* @package AVE.cms
|
||||
* @version 3.x
|
||||
* @version 4.x
|
||||
* @filesource
|
||||
* @copyright © 2007-2014 AVE.cms, http://www.ave-cms.ru
|
||||
*
|
||||
@@ -32,13 +33,65 @@
|
||||
* Внутренние методы класса
|
||||
*/
|
||||
|
||||
/**
|
||||
* Вспомогательный метод для чтения последних строк файла с конца
|
||||
*
|
||||
* @param string $file_name Путь к файлу
|
||||
* @param int $_count Количество строк, которые нужно прочитать
|
||||
* @param int $chunk_size Размер блока для чтения
|
||||
* @return array Массив строк в прямом хронологическом порядке
|
||||
*/
|
||||
private function readLastLines($file_name, $_count, $chunk_size = 8192)
|
||||
{
|
||||
if (!file_exists($file_name) || !($fp = @fopen($file_name, 'rb'))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$file_size = @filesize($file_name);
|
||||
$pos = $file_size;
|
||||
$buffer = '';
|
||||
$raw_lines = [];
|
||||
|
||||
// Чтение файла блоками с конца
|
||||
while ($pos > 0 && count($raw_lines) < $_count) {
|
||||
$bytes_to_read = min($chunk_size, $pos);
|
||||
$pos -= $bytes_to_read;
|
||||
|
||||
fseek($fp, $pos);
|
||||
$chunk = fread($fp, $bytes_to_read);
|
||||
$buffer = $chunk . $buffer;
|
||||
|
||||
if ($pos == 0) {
|
||||
$lines = explode("\n", $buffer);
|
||||
$buffer = '';
|
||||
} else {
|
||||
$lines = explode("\n", $buffer);
|
||||
$buffer = array_shift($lines);
|
||||
}
|
||||
|
||||
foreach (array_reverse($lines) as $line) {
|
||||
if (trim($line) !== '') {
|
||||
$raw_lines[] = $line;
|
||||
if (count($raw_lines) >= $_count) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
|
||||
// Разворачиваем, чтобы получить правильный хронологический порядок
|
||||
return array_reverse($raw_lines);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Внешние методы класса
|
||||
*/
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для отображения всех записей Журнала событий
|
||||
/**
|
||||
* Метод, предназначенный для отображения всех записей Журнала событий (log.csv)
|
||||
*
|
||||
*/
|
||||
function logList ()
|
||||
@@ -46,49 +99,37 @@
|
||||
global $AVE_Template;
|
||||
|
||||
$file_name = BASE_DIR . $this->_logdir;
|
||||
$_count = 10000;
|
||||
$_lines = [];
|
||||
|
||||
if (file_exists($file_name) && $fp = @fopen($file_name, 'rb'))
|
||||
{
|
||||
$_count = 10000;
|
||||
$raw_lines = $this->readLastLines($file_name, $_count);
|
||||
|
||||
$_size = @filesize($file_name);
|
||||
foreach ($raw_lines as $line) {
|
||||
|
||||
$_slice = 10240;
|
||||
$event = str_getcsv($line, ',', '"', '\\');
|
||||
|
||||
$_size > $_slice && fseek($fp, $_size - $_slice);
|
||||
|
||||
while (!feof($fp))
|
||||
{
|
||||
// ИСПРАВЛЕНИЕ: Добавляем обязательные параметры: разделитель (','), ограничитель ('"'), экранирование ('\')
|
||||
$event = fgetcsv($fp, $_slice, ',', '"', '\\');
|
||||
|
||||
if (empty($event[0]) || count($event) < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$_lines[] = [
|
||||
'log_time' => $event['0'] ?? '',
|
||||
'log_ip' => $event['1'] ?? '',
|
||||
'log_url' => $event['2'] ?? '',
|
||||
'log_user_id' => $event['3'] ?? '',
|
||||
'log_user_name' => $event['4'] ?? '',
|
||||
'log_text' => $event['5'] ?? '',
|
||||
'log_type' => $event['6'] ?? '',
|
||||
'log_rubric' => $event['7'] ?? ''
|
||||
];
|
||||
if (empty($event[0]) || count($event) < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count($_lines) > $_count && $_lines = array_slice($_lines, -$_count);
|
||||
$_lines[] = [
|
||||
'log_time' => $event['0'] ?? '',
|
||||
'log_ip' => $event['1'] ?? '',
|
||||
'log_url' => $event['2'] ?? '',
|
||||
'log_user_id' => $event['3'] ?? '',
|
||||
'log_user_name' => $event['4'] ?? '',
|
||||
'log_text' => $event['5'] ?? '',
|
||||
'log_type' => $event['6'] ?? '',
|
||||
'log_rubric' => $event['7'] ?? ''
|
||||
];
|
||||
}
|
||||
|
||||
// Передаем данные в шаблон для вывода и отображаем страницу
|
||||
$AVE_Template->assign('logs', $_lines);
|
||||
$AVE_Template->assign('content', $AVE_Template->fetch('logs/logs.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для отображения всех записей Журнала событий 404
|
||||
* Метод, предназначенный для отображения всех записей Журнала событий 404 (404.csv)
|
||||
*
|
||||
*/
|
||||
function List404()
|
||||
@@ -96,37 +137,27 @@
|
||||
global $AVE_Template;
|
||||
|
||||
$file_name = BASE_DIR . $this->_404dir;
|
||||
$_count = 10000;
|
||||
$_lines = [];
|
||||
|
||||
if (file_exists($file_name) && $fp = @fopen($file_name, 'rb'))
|
||||
{
|
||||
$_count = 10000;
|
||||
$raw_lines = $this->readLastLines($file_name, $_count);
|
||||
|
||||
$_size = @filesize($file_name);
|
||||
foreach ($raw_lines as $line) {
|
||||
|
||||
$_slice = 10240;
|
||||
$event = str_getcsv($line, ',', '"', '\\');
|
||||
|
||||
$_size > $_slice && fseek($fp, $_size - $_slice);
|
||||
|
||||
while (!feof($fp))
|
||||
{
|
||||
$event = fgetcsv($fp, $_slice, ',', '"', '\\');
|
||||
|
||||
if (empty($event[0]) || count($event) < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$_lines[] = [
|
||||
'log_time' => $event['0'] ?? '',
|
||||
'log_ip' => $event['1'] ?? '',
|
||||
'log_query' => $event['2'] ?? '',
|
||||
'log_user_agent' => $event['3'] ?? '',
|
||||
'log_user_referer' => $event['4'] ?? '',
|
||||
'log_request_uri' => $event['5'] ?? ''
|
||||
];
|
||||
if (empty($event[0]) || count($event) < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count($_lines) > $_count && $_lines = array_slice($_lines, -$_count);
|
||||
$_lines[] = [
|
||||
'log_time' => $event['0'] ?? '',
|
||||
'log_ip' => $event['1'] ?? '',
|
||||
'log_query' => $event['2'] ?? '',
|
||||
'log_user_agent' => $event['3'] ?? '',
|
||||
'log_user_referer' => $event['4'] ?? '',
|
||||
'log_request_uri' => $event['5'] ?? ''
|
||||
];
|
||||
}
|
||||
|
||||
// Передаем данные в шаблон для вывода и отображаем страницу
|
||||
@@ -135,7 +166,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для отображения всех записей Журнала событий 404
|
||||
* Метод, предназначенный для отображения всех записей Журнала событий SQL (sql.csv)
|
||||
*
|
||||
*/
|
||||
function ListSql()
|
||||
@@ -143,42 +174,29 @@
|
||||
global $AVE_Template;
|
||||
|
||||
$file_name = BASE_DIR . $this->_sqldir;
|
||||
$_count = 10000;
|
||||
$_lines = [];
|
||||
|
||||
if (file_exists($file_name) && $fp = @fopen($file_name, 'rb'))
|
||||
{
|
||||
$_count = 10000;
|
||||
$raw_lines = $this->readLastLines($file_name, $_count);
|
||||
|
||||
$_size = @filesize($file_name);
|
||||
foreach ($raw_lines as $line) {
|
||||
|
||||
$_slice = 10240;
|
||||
$event = str_getcsv($line);
|
||||
|
||||
$_size > $_slice && fseek($fp, $_size - $_slice);
|
||||
|
||||
while (!feof($fp))
|
||||
{
|
||||
// Используем разделители по умолчанию, как в оригинале, но добавим безопасное чтение.
|
||||
$event = fgetcsv($fp, $_slice);
|
||||
|
||||
if (empty($event[0]) || count($event) < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$_lines[] = [
|
||||
'log_time' => $event['0'] ?? '',
|
||||
'log_ip' => $event['1'] ?? '',
|
||||
'log_url' => $event['2'] ?? '',
|
||||
'log_user_id' => $event['3'] ?? '',
|
||||
'log_user_name' => $event['4'] ?? '',
|
||||
// Предполагаем, что event[5] всегда должно быть (base64_decode и unserialize)
|
||||
'log_text' => isset($event['5']) ? unserialize(base64_decode($event['5'])) : ''
|
||||
];
|
||||
if (empty($event[0]) || count($event) < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count($_lines) > $_count && $_lines = array_slice($_lines, -$_count);
|
||||
$_lines[] = [
|
||||
'log_time' => $event['0'] ?? '',
|
||||
'log_ip' => $event['1'] ?? '',
|
||||
'log_url' => $event['2'] ?? '',
|
||||
'log_user_id' => $event['3'] ?? '',
|
||||
'log_user_name' => $event['4'] ?? '',
|
||||
'log_text' => isset($event['5']) ? unserialize(base64_decode($event['5'])) : ''
|
||||
];
|
||||
}
|
||||
|
||||
// Передаем данные в шаблон для вывода и отображаем страницу
|
||||
$AVE_Template->assign('logs', $_lines);
|
||||
$AVE_Template->assign('content', $AVE_Template->fetch('logs/sql.tpl'));
|
||||
}
|
||||
@@ -302,7 +320,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для экспорта сообщений 404
|
||||
* Метод, предназначенный для экспорта сообщений MySql
|
||||
*
|
||||
*/
|
||||
function ExportSql()
|
||||
@@ -329,4 +347,5 @@
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user