Здравствуйте!
Возникла проблема с парсингом логов - некоторые данные почему-то теряются и не попадают в базу.
Как все сделано:
Запущен nginx. Делается запрос вида
hostname.ru/s?e=1&r=2&p=3&u=4
Все такие запросы попадают в access.log
Затем, раз в 10 минут выполняется скрипт:
#!/bin/sh
# date (day)
#DATE=`date '+%d%m%y'`
DATE=`date --date='next day' "+%d%m%y"`
# date (with minutes)
DATEM=`date --date='next day' "+%d%m%y_%H%M"`
# rename logs file to '<filename>.<DATEM>'
mv /var/virtual/hostname.ru/logs/access.log /var/virtual/hostname.ru/logs/access.log.$DATEM
# reload nginx
/etc/init.d/nginx reload
# parse logs file
/var/virtual/hostname.ru/cron/parser_new.pl </var/virtual/hostname.ru/logs/access.log.$DATEM >/var/virtual/hostname.ru/logs/parser_new.log
# add DATEM-file log to the end of the DATE-file log
cat /var/virtual/hostname.ru/logs/access.log.$DATEM >> /var/virtual/hostname.ru/logs/access.log.$DATE
# remove temporary file
rm /var/virtual/hostname.ru/logs/access.log.$DATEM
Т.е. происходит следующее:
- файл с логами переименовывается - к названию добавляется дата с указанием числа,месяца,года,часа,минут.
- перезапускается nginx (и создается новый access.log)
- запускается парсер на файл с 10-минутными логами
- логи за 10 минут копируются в общий файл логов (который в конце дня bzip2'ается)
- файл 10-минутных логов удаляется
И так каждые 10 минут.
Как работает скрипт парсера (Perl):
1. построчно считывает файл логов
2. регексами разбивает строку - отбирает значения r,p,e,u
3. пишет в базу связку u-r
$query="INSERT INTO p${p}r (u,r,timestamp) VALUES ('$u','$r','$time') ON DUPLICATE KEY UPDATE timestamp='$time'";
$dbh->do($query);
if ($dbh->err()) {
Debug("($query) SQL ERROR: $DBI::errstr\n");
next;
};
4. записывает r-p-e в хеш-таблицу:
if (!defined($VALUE{$r}{$p}{$e})) { $VALUE{$r}{$p}{$e}=0; };
$VALUE{$r}{$p}{$e}++;
5. затем собранные данные пишет в базу:
foreach $r (keys %VALUE) {
foreach $p (keys %{$VALUE{$r}}) {
foreach $e (keys %{$VALUE{$r}{$p}}) {
print "r=$r p=$p e=$e $VALUE{$r}{$p}{$e}\n";
$query="INSERT INTO table (p,e,r,value,timestamp) VALUES ('$p','$e','$r','$VALUE{$r}{$p}{$e}','$day_start') ON DUPLICATE KEY UPDATE value=value+$VALUE{$r}{$p}{$e}";
$dbh->do($query);
if ($dbh->err()) {
Debug("($query) SQL ERROR: $DBI::errstr\n");
next;
};
};
};
};
Проблема:
Теряются некоторые запросы.
Причем, связка u-r записывается в базу ВСЕГДА (парсер, шаг 3). НО на шаге 4, судя по всему, почему-то не все записывается в хеш-таблицу (если верить print «r=$r p=$p e=$e $VALUE{$r}{$p}{$e}\n»;).
Если же потом, например, повторно делаю запросы - тогда они вполне могут пройти и попасть в базу.
Получается, что иногда считается, иногда нет. Где может быть косяк?
PS: Названия немного поменял.
PPS: Варианты «Да у тебя одни костыли, надо все по-другому с нуля переписать» не предлагать.