Расширенный анализ логов apache. Как уйти от линейного поиска.

Nil

Новичок
Расширенный анализ логов apache. Как уйти от линейного поиска.

Стоит задача в написании статистики на основе логов апача. Статистика должна самую полную информацию. Вот что от неё требуется:
- уники по дням
- уники по часам
- хиты по дням
- количество страниц схаванных поисковыми роботами по дням
- какие именно страницы схаваны по каждому боту
- количество переходов с каждого поисковика по дням
- поисковые фразы отдельно по каждому поисковику
- клиентские браузеры
Это первоочередные задачи. Потом планирую расширить. Идей куча. Если кто знаком с таким мностром как sawmill, можно сравнить с ним. Сейчас пользуюсь awstats, но там очень много не хватает. Начал всё это писать на основе справочников ботов, браузеров, поисковиков как раз из awstats, но значительно их урезал. Начал тестить с куска дневного лога в 400 уников от посетителей + 400 запросов от ботов. Всего в логе 12000 хитов включая запросы ботов.

вот что получилось в черновом варианте
PHP:
<?php

   include("config.php");

/*   $result = mysql_connect("localhost", "root", "");
   mysql_select_db("apache"); */

   include("lib/robots.php");
   include("lib/browsers.php");
   include("lib/searcheng1.php");

   echo "<pre>";

  function file_put($fn,$mode,$data)
  {
     $fp = fopen ($fn, $mode);
     fwrite ($fp, $data);
     fclose ($fp);
  }

  function getmicrotime()
  {
	    list($usec, $sec) = explode(" ", microtime());
	    return ((float)$usec + (float)$sec);
  }

  $stime = getmicrotime();

  $fp = fopen ($cashedir."2006-02-19/dump.dat", "r");

  $i=0;
  $ips=array();
  $robots=array();
  $browsers=array();
  $srchcnt=array();
  $phrases=array();

  while (!feof($fp))
  {
     $fst=fgets($fp);

//     list($ip,$date,$time,$datetime,$uri,$answ,$size,$ref,$uagent)=explode("##",$filest);

     $fst=explode("##",$fst);

     $ip=$fst[0];
     $date=$fst[1];
     $time=$fst[2];
     $datetime=$fst[3];
     $uri=$fst[4];
     $answ=$fst[5];
     $size=$fst[6];
     $ref=$fst[7];
     $uagent=$fst[8];

	 // Robots
     $isrob=0;
   	 $cnt=sizeof($robots_base);
	 for ($i=0; $i<$cnt; $i++)
	 {
	      $rob=$robots_base[$i];
	      if (preg_match("/$rob/i",$uagent))
	      {
              if (@!$robots[$rob]=$robots[$rob]+1) $robots[$rob]=1;
	          $isrob=1; break;
	      }
	 }


     // UserAgent
     if (!$isrob)
     {
         // Browser version
         $isbrows=0;
         $cnt=sizeof($browsers_base);
	     for ($i=0; $i<$cnt; $i++)
	     {
	        $brow=$browsers_base[$i];
	        if (preg_match("/$brow/i",$uagent))
	        {
                if (@!$browsers[$brow]=$browsers[$brow]+1) $browsers[$brow]=1;
	            $isbrows=1;
	        }
	     }
         if (!$isbrows)
         if (@!$browsers["unknown"]=$browsers["unknown"]+1) $browsers["unknown"]=1;

         // Is from search engine
	     $cnt=sizeof($seident);
	     for ($i=0; $i<$cnt; $i++)
	     {
	        $se=$seident[$i];
	        if (preg_match("/$se/i",$ref))
	        {
                if (@!$srchcnt[$searchnames[$i]]=$srchcnt[$searchnames[$i]]+1) $srchcnt[$searchnames[$i]]=1;

                // Getting search phrase
                if (!preg_match("/$searchpregs[$i](.*)/i",$ref,$arr)) echo "$ref\n";
                else
                {
	              $phrase=$arr[0];
                  $phrase=substr($phrase,strpos($phrase,"=")+1);
	              if (strpos($phrase,"&")>0) $phrase=substr($phrase,0,strpos($phrase,"&"));
                  if (@!$phrases[$phrase]=$phrases[$phrase]+1) $phrases[$phrase]=1;
                }

	            break;
	        }
	     }
     }


     // IP
     if (!$isrob)
     if (@!$ips[$ip]=$ips[$ip]+1) $ips[$ip]=1;

     $i++;

//     if ($i==50) break;
  }
  fclose($fp);

  print_r($browsers);
  print_r($robots);
  print_r($srchcnt);
  print_r($phrases);

  $hits=0;
  foreach ($ips as $cnt) $hits+=$cnt;
  echo "hits=$hits\nuniqs=".count($ips);

  $etime=getmicrotime()-$stime;

  echo "\n\ntime=$etime\n";


?>
всё бы хорошо, но этот лог парсится на ненагруженном серваке примерно 40 сек.. что очень много. Т.к. у сайтов где буду юзать эти статсы примерно тысяч по 5 уников в день. Как разгрузить всё это хозяйство никак не придумаю. Всё идеи по увеличению скорости исчерпаны. Может кто уже имел опыт решения таких задач? Вся проблема в скорости. Возможно есть какие то алгоритмы нелинейного поиска которые можно применить к моему случаю. Я думаю если я этот анализатор запущу на лог в 5000, он будет несколько часов работать, что вообще не приемлимо. Тот же австатс парсит мой тестовый лог примерно секунд 10..
 

Фанат

oncle terrible
Команда форума
а ## -это ты сам добавил в лог апача? оригинально =)
этот лог парсится на ненагруженном серваке примерно 40 сек..
весь, равными долями?
то есть, скажем
$ip=$fst[0];
исполняется столько же, сколько
for ($i=0; $i<$cnt; $i++)
да?
 

Nil

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

что значит "весь, равными долями"?
исполняется столько раз, сколько записей в логе

вот это for ($i=0; $i<$cnt; $i++) никакого отношения к ипу не имеет

-~{}~ 02.03.06 13:05:

Кстать забыл добавить, известных ботов в $robots_base примерно 400 штук, браузеров в $browsers_base 120, поисковиков в $seident 80 штук. Как раз вот эти проходы по массивам для каждой записи лога и тормозят всё безбожно...
 

440hz

php.ru
я. так понял, что ты не лог апача парсишь а какой-то уже приготовленный

вот когда лог апача парсишь заменяй ботов, броузеры и что-там еще на 1,2,3,4,5 и тогда поиск по регулярным тебе не нужен будет
 

Nil

Новичок
это не чистый лог а всё тоже самое для простоты разделённое разделителем ##
не вижу смысла в логе заменять..
вот например этот регэксп ищет гугла
216\.239\.(35\.101|37\.101|39\.100|39\.101|51\.100|51\.101|35\.100)
как его заменю в логе без регулярных выражений?
 
Сверху