Запись логов Apache в базу данных

Материал из Lblss.ru
Перейти к: навигация, поиск

Собственно, есть настроить Apache так, чтобы он сразу писал логи в БД. Однако, появилась необходимость разово залить существующий текстовый лог в базу с целью быстренько проанализировать. По-быстрому найти рабочий скрипт не удалось, оказалось проще написать свой велосипед.


<?php
/*
Читает лог Апача и помещает его в таблицу базы данных
*/
 
$log_src = '/path/to/file/access_log'; // Имя файла лога для чтения
 
$sql_host = 'localhost'; // параметры подключения к БД
$sql_user = 'test';
$sql_pass = '';
$sql_db = 'test';
 
$sql_max_counter = 100; // Строк лога на один запрос
$table_name = 'statslog'; // Имя таблицы
 
//////////////////////////////////////////////////////////////////////////////////////////////////
 
error_reporting(E_ALL);
 
// Запросы на удаление/создание таблиц
$sql_drop_table = <<<SQL
DROP TABLE IF EXISTS `{$table_name}`
SQL;
$sql_create_table = <<<SQL
CREATE TABLE `{$table_name}` (
 `ip` varchar(25) DEFAULT NULL,
 `accessdate` date DEFAULT NULL,
 `accesstime` time DEFAULT NULL,
 `themethod` varchar(7) DEFAULT NULL,
 `thepage` varchar(250) DEFAULT NULL,
 `theproto` varchar(10) DEFAULT NULL,
 `thecode` char(3) DEFAULT NULL,
 `thebytes` int(11) DEFAULT NULL,
 `theref` varchar(250) DEFAULT NULL,
 `browser` varchar(250) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
SQL;
 
echo '<pre>';
$fsrc = fopen($log_src, 'r');
 
$month = array();
$month['Jan'] = '01';
$month['Feb'] = '02';
$month['Mar'] = '03';
$month['Apr'] = '04';
$month['May'] = '05';
$month['Jun'] = '06';
$month['Jul'] = '07';
$month['Aug'] = '08';
$month['Sep'] = '09';
$month['Oct'] = '10';
$month['Nov'] = '11';
$month['Dec'] = '12';
 
$sql_counter = 0; // Счет строк для одного запроса
$str_counter = 0; // Счет прочитанных строк
 
mysql_connect($sql_host, $sql_user, $sql_pass) or die(__LINE__.' Error: ' . mysql_error());
mysql_select_db($sql_db) or die(__LINE__.' Error: ' . mysql_error());
mysql_query($sql_drop_table) or die(__LINE__.' Error: ' . mysql_error());
mysql_query($sql_create_table) or die(__LINE__.' Error: ' . mysql_error());
 
while($str = fgets($fsrc)) {
    $str_counter++;
    preg_match(
        '/(\d+\.\d+\.\d+\.\d+)\s+-\s+-\s+\[([^:]+):(.+)\s+.+\]\s\"([^\"]+)\s([^\"]+)\s([^\"]+)\"\s(\d{3})\s(\d+|-)\s\"([^\"]*)\"\s\"([^\"]*)\"/',
        $str, $m
    );
    $mm = explode('/', $m[2]);
    $m[2] = "{$mm[2]}-{$month[$mm[1]]}-{$mm[0]}"; // Правка даты
    unset($m[0]); // Полный шаблон нам не нужен
    echo '.'; // Индикатор строки
    if($sql_counter == 0) { // Начало запроса
        $sql_string = "INSERT INTO `{$table_name}` VALUES ";
    }
    if($sql_counter < $sql_max_counter) { // Дописываем разобранную строку в запрос
        $sql_counter++;
        $sql_string .= "\n" . '("' . implode('","', $m) . '"),';
    }
    if($sql_counter == $sql_max_counter) { // Запись строк в базу и обнуление счетчика
        mysql_query(rtrim($sql_string, ',')) or die(__LINE__.' Error: ' . mysql_error() . "\n$sql_string\n$str_counter");
        echo "| $sql_counter | $str_counter \n"; // Индикатор запроса
        $sql_counter = 0;
    }
}
 
if($sql_counter) { // Последние строки в базу
    mysql_query(rtrim($sql_string, ',')) or die(__LINE__.' Error: ' . mysql_error() . "\n$sql_string\n$str_counter");
}
 
echo ":\n$str_counter"; // Индикатор окончания
 
fclose($fsrc);
?>

За безглючность не ручаюсь. Возможно, придется немного допилить регулярку.

Персональные инструменты