Журналирование Apache2 в mysql

HTML, CSS, DOM, XML, AJAX, (LW)AMP и т.д. CMS и веб-форумы, веб-дизайн и веб-программирование, специализированные языки и технологии.

Модератор: xdsl

Журналирование Apache2 в mysql

Сообщение xdsl 10 июн 2009, 08:35

Решил тут сделать для нашего портала shgpi.edu.ru нормальную статистику. Давно, в принципе, пора было, но руки не доходили.
Определил исходные требования:
1. Возможность получения информации в режиме реального времени
2. Возможность быстро формировать статистику по разным, пока неизвестным, параметрам
3. Независимость от ограничений формата журнала Apache2 или других приложений

По заявленным параметрам сразу отпадают все существующие анализаторы журналов. Обрабатывать файлы журналов какими-то своими методами противоречит пп.1 и 2. Единственный выход - сразу заставить Apache сохранять журнал в базе данных. Поиски в Сети дали mod_log_sql, который на заявленные параметры тоже не подходил, а именно - по пункту 3.

Выход, тем не менее, нашелся. Оказывается apache2 умеет журналировать через конвеер (http://httpd.apache.org/docs/2.0/mod/mod_log_config.html#customlog). То есть, на стандартный вход заявленной программы он посылает журнал строка за строкой в заданном формате, а уж что дальше будет делать с журналом программа - проблемы самой программы. После загрузки веб-сервер стартует такую программу, перед окончанием работы - уничтожает. Получается, достаточно создать программу, которая при старте соединяется с сервером БД, держит это соединение, приходящие на стандартный вход строки журнала конвертирует по заданным требованиями и сохраняет в базу.

Среди замеченных проблем - безусловное завершение работы программы веб-сервером по окончанию его работы, что может привести к недозаписи одной или нескольких строк в базу данных. Т.к. все это мне нужно только для статистики, которая, как известно, наука неточная, то решил оставить данную проблему как есть, особенно с учетом того, что веб-сервер перестартую дай Бог раз в месяц, а то и реже. Еще одна проблема - головной процесс апача запускается под рутом, следовательно и программу он запускает под рутом. Значит писать ее надо очень аккуратно.

Сделал, проверил, работает. За 5 дней накидало в базу ... щас посмотрю ... 74703 коннекта

Теперь, как это все было сделано.

Продолжение следует...
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Журналирование Apache2 в mysql

Сообщение xdsl 11 июн 2009, 08:27

... день 6-й, 93667 коннектов
Итак, сначала надо решить, какие данные будем журналировать. Варианты, предлагаемые апачем, можно найти здесь: http://httpd.apache.org/docs/2.0/mod/mod_log_config.html#formats. Я остановился на следующем варианте, который разместил в httpd.conf:
Код: Выделить всё
logFormat "%h\t%{%Y%m%d%H%M%S}t\t%m\t%v\t%p\t%U\t%q\t%>s\t%T\t%b\t%{User-agent}i" usefull
При этом разделителем полей использовал табуляцию для удобства распознавания полей при последующей обработке.
Соответствующая формату журнала таблица у меня выглядит так:
Код: Выделить всё
CREATE TABLE IF NOT EXISTS `shgpi_edu_ru` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `remote_host` varchar(100) NOT NULL,
  `date_time` datetime NOT NULL,
  `method` varchar(20) NOT NULL,
  `server_name` varchar(100) NOT NULL,
  `port` varchar(20) NOT NULL,
  `directory` varchar(300) NOT NULL,
  `file_name` varchar(300) NOT NULL,
  `query` varchar(300) NOT NULL,
  `status` bigint(20) NOT NULL,
  `recv_seconds` bigint(20) NOT NULL,
  `recv_bytes` bigint(20) NOT NULL,
  `user_agent` varchar(500) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `remote_host` (`remote_host`),
  KEY `date_time` (`date_time`),
  KEY `method` (`method`),
  KEY `server_name` (`server_name`),
  KEY `port` (`port`),
  KEY `directory` (`directory`),
  KEY `file_name` (`file_name`),
  KEY `query` (`query`),
  KEY `status` (`status`),
  KEY `recv_seconds` (`recv_seconds`),
  KEY `recv_bytes` (`recv_bytes`),
  KEY `user_agent` (`user_agent`(333))
)
Теперь - программа обработки. Встал вопрос - на каком языке писать? По требованиям к высокой скорости все динамические языки отпадают. Остается классика - Си или Паскаль. Паскаль мне ближе, знаю его досконально, посему - выбран freepascal:
Код: Выделить всё
// файл logging.pp
{$MODE objfpc}
{$H+}
uses mysql50,sysutils,unixutil;
var HMySQL : PMySQL;
     H,U,P,DB,Base : pchar;
     Port,i : Cardinal;

function getTabStr(var S:string):string;
  var l,i:integer;
begin
  l:=length(s);  i:=1;  while (i<=l) and (s[i]<>#9) do inc(i);
  result:=copy(s,1,i-1);  s:=copy(s,i+1,l);
end;

var s,query,resquery,values,fn,dn:string;     
begin
    HMySQL:=nil;
    HMySQL := mysql_init(HMySQL);
    Port:=3306;
    H:='******'; // имя хоста
    U:='******'; // имя пользователя
    P:='******'; // пароль пользователя
    DB:='logs'; // база данных
    Base:='shgpi_edu_ru'; // таблица журнала
    HMySQL:=mysql_real_connect(HMySQL,PChar(H),PChar(U),Pchar(P),Nil,Port,Nil,0);
    try
     If (HMySQL=Nil) then raise Exception.Create('Can''t connect');
     mysql_select_db(HMySQL,DB);
     query:='insert delayed into '
     +Base
     +'(remote_host,date_time,method,server_name,port,directory,file_name,query,status,recv_seconds,recv_bytes,user_agent)'
     +'values ';
     while not eof do begin
      readln(s);
      values:='';
      for i:=1 to 5 do  values:=values+'"'+gettabstr(s)+'",';
      fn:=gettabstr(s);
      dn:=dirname(fn); if length(dn)>1 then dn:=dn+'/'; // если каталог - не корень, добавил в конце слэш - для удобства последующих SQL-запросов
      values:=values+'"'+dn+'",'+'"'+basename(fn,'')+'",';
      for i:=1 to 4 do values:=values+'"'+gettabstr(s)+'",';
      resquery:=query+'('+values+'"'+s+'")';
      mysql_query(HMySQL,pchar(resquery));
     end;
    finally
     mysql_close(HMySQL);
    end;
end.


И, наконец, последний штрих. Размещаю на веб-сервере получившийся после компиляции исполняемый файл logging в каталоге /opt/alogs/bin/, в настройках виртуального хоста апача пишу
Код: Выделить всё
CustomLog |/opt/alogs/bin/logging usefull
и перезапускаю апач. Все, можно идти, пить кофе, база данных журнала начинает заполняться запросами.

Теперь осталось только подождать заполнения журнала приемлимым количеством данных и можно начинать разрабатывать запросы и скрипты различной статистики.

Продолжение следует ...
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Журналирование Apache2 в mysql

Сообщение xdsl 30 июн 2009, 07:59

... день 25-й, 333350 коннектов, полумиллион неумолимо приближается.
Завели статистику посещаемости по адресу http://shgpi.edu.ru/stats/, готовим ее расширенный вариант. По дороге обнаружили, что rlike в mysql 5.0.41 в десятки раз медленнее работает, чем like и совершенно не оптимизирует операцию "|" в регулярном выражении.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Журналирование Apache2 в mysql

Сообщение xdsl 27 авг 2009, 12:25

На конец августа - более миллиона записей. Сделал выгрузку всех данных и разместил здесь: ftp://ftp.data.shgpi/uploads/xdsl/sql_logs/logs.shgpi.edu.ru.20090605-20090827.sql.bz2 (доступ только из локальных сетей ШГПИ!). Полученную таблицу можно использовать в учебном процессе, предварительно развернув на любом сервере баз данных (в случае несовместимости некоторых sql-конструкций можно легко поправить заголовок в начале файла). Польза, имхо, будет несомненной. Было-бы интересно также сравнить скорость работы идентичных запросов на различных типах серверов БД.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Журналирование Apache2 в mysql

Сообщение andy ice 23 сен 2010, 14:17

После загрузки веб-сервер стартует такую программу, перед окончанием работы - уничтожает. Получается, достаточно создать программу, которая при старте соединяется с сервером БД, держит это соединение, приходящие на стандартный вход строки журнала конвертирует по заданным требованиями и сохраняет в базу.
т.е. один раз запустился и запущенный ждет?
Встал вопрос - на каком языке писать? По требованиям к высокой скорости все динамические языки отпадают.
вопрос - почему отпадают? тот же PHP один раз запустился и живет себе в памяти, разобрать строку и отправить её в MySQL не сильно такая накладная задача
andy ice
 
Сообщения: 2
Зарегистрирован: 23 сен 2010, 12:46
Полное имя: Андрей Морозов

Re: Журналирование Apache2 в mysql

Сообщение xdsl 23 сен 2010, 21:41

andy ice писал(а):т.е. один раз запустился и запущенный ждет?

Ага.
Встал вопрос - на каком языке писать? По требованиям к высокой скорости все динамические языки отпадают.


вопрос - почему отпадают? тот же PHP один раз запустился и живет себе в памяти, разобрать строку и отправить её в MySQL не сильно такая накладная задача

PHP, конечно, запустился и живет, у нас даже один такой живчик на ВЦ есть, по SNMP с корневого коммутатора раз в 10 секунд информацию собирает, парсит и в базу складывает. Но коммутатор - наш, объем данных - небольшой, его минимум и максимум известны, в то время как shgpi.edu.ru - внешний портал, пиковая нагрузка - не детерминируется в принципе. Посему - пусть будет высокоскоростной бинарник. Работает уже больше года, все известные его сбои - только по вине электриков.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: Журналирование Apache2 в mysql

Сообщение xdsl 23 сен 2010, 22:30

Кстати, сейчас глянул - за год и 4 месяца накидало 12 миллионов с лишним коннектов, а за сегодня - около 50 тысяч (http://shgpi.edu.ru/stats2)
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.


Вернуться в Web-технологии

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron