PHP скрипт анализа логов

Задача была написать скрипт анализа логов, включая:

  • обработку повторяющихся ошибок
  • подсчетом количества повторов ошибок
  • хранение времени появления первого и последнего повтора ошибки
  • отправка каждой ошибки на email
  • хранение последней позиции курсора файла в первой строке лога

Формат лога представлял собой следующее:

PHP:
  1. 2009-07-23T10:25:11+00:00  DEBUG (7): Resource 'demo' not found
  2. 2009-07-24T17:10:20+00:00  DEBUG (7): Resource 'photos' not found
  3. 2009-07-24T17:11:22+00:00  DEBUG (7): Resource 'photos' not found

Т.е. одна ошибка в одну строку.

После обработки их скриптом, мы получали email с сообщением следующего формата, одна строка это одно сообщение:

PHP:
  1. DEBUG (7): Resource 'photos' not found - 2 times, first time - 2009-07-24 17:10:20 GMT, last time - 2009-07-24 17:11:22 GMT
  2. DEBUG (7): Resource 'demo' not found - 1 time, 2009-07-23 10:25:11 GMT

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

Вот собственно и сам log_analyzer.php:

PHP:
  1. define('ERROR_LOG_PATH', BASE_PATH.'/logs/error.log');
  2.  
  3. $fp = fopen(ERROR_LOG_PATH, 'r+');
  4. $position = fgets($fp);
  5. $position = intval($position);
  6.  
  7. fseek($fp, $position);
  8.  
  9. $time = strtotime("-7 minutes");
  10. $grabLog = false;
  11. $sphinxErrors = $sphinxWarnings = array();
  12. $errors = array();
  13. while(!feof($fp)){
  14.     $line = fgets($fp);
  15.     if( preg_match("/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2})/",$line, $matches) === 1 ){
  16.         $datetime = $matches[1];
  17.     } else {
  18.          continue;
  19.     }
  20.     $errorLine = str_replace($datetime, '', $line);
  21.     $formattedTime = date("Y-m-d H:i:s T", strtotime($datetime));
  22.     if (!isset($errors[$errorLine])){               
  23.         $errors[$errorLine]['firsttime'] = $formattedTime;
  24.         $errors[$errorLine]['lasttime'] = $formattedTime;
  25.         $errors[$errorLine]['times'] = 1;
  26.     } else {
  27.         $errors[$errorLine]['lasttime'] = $formattedTime;
  28.         $errors[$errorLine]['times']++;
  29.     }
  30.    
  31. }
  32. $newPosition = ftell($fp);
  33.  
  34.  
  35. if ( !rewind($fp) ) {
  36.     echo 'not working';
  37. }
  38. fwrite($fp, $newPosition."        \n");
  39. fclose($fp);
  40.  
  41.  
  42. if (!empty($errors)){
  43.     foreach ($errors as $text => $error){
  44.         if ($error['times']> 1){
  45.             $body = sprintf("%s - %s times, first time - %s, last time - %s",
  46.                 $text, $error['times'], $error['firsttime'], $error['lasttime']);
  47.         } else {
  48.             $body = sprintf("%s - %s time, %s",
  49.                 $text, $error['times'], $error['firsttime']);
  50.         }
  51.         Mail_Notifications::notifyError($body);
  52.     }
  53. }

Скрипт я запускаю с помощью cron каждые 7 минут.

Комментарии

Leave a Reply