Не все ошибки может отследить разработчик, многие появляются в процессе использования ПО, в зависимости от окружения и т.д. Для меня очень важно отслеживать такие возможные баги, особенно на этапе запуска проекта. Я сильно не ухищрялся, просто периодически просматривал содержимое error.log файлов. Но проектов, которые приходится поддерживать, становится всё больше, на многих из них развернуто по несколько серверов. В итоге для меня эта операция стала довольно трудоемкой. Естественно, это дело нужно автоматизировать.
В интернете есть серьезные решения для Enterprise-проектов, но мне хотелось чего-то простого, что с легкостью можно было бы установить на любой сервер. Итак, я описал необходимые мне задачи:
- Скрипт должен запускаться с какой-то периодичностью
- Должен выбирать ошибки за последний период, фильтровать их
- Отправлять на email
- Очищать error.log файл
С первым пунктом легко справится CRON. Скрипт нашей рассылки будет обычным php-файлом, который будет вызываться планировщиком задач. Я его запускаю каждый час, чтобы быть всегда готовым быстро что-то исправить:
0 * * * * php /var/www/alm/alm.php
Потом на практике я увидел, что везде формат error.log файла разный. Это зависит или от версии Apache, или от PHP, или от сборки. Поэтому парсить строки для фильтрации было трудно. Заметил я только одно общее место, которого мне и было достаточно, а фильтрация мне была нужна для того, чтобы настроить отправляемые мне типы ошибок. Так вот, во всех PHP-ошибках будет присутствовать «PHP Warning», «PHP Notice» и т.д. Я и сделал фильтр по этим ключам. Пример конфига (config.php):
//php return array( // ApacheLM will send log to this email 'email' => 'alexander.plutov@gmail.com', // Full path to the error log file 'errorLogFile' => '/var/log/apache2/error.log', // Fetch only these error types. Comment or remove if you don't need to get some types in mail. 'errorTypes' => array('Warning', 'Notice', 'Fatal') );
Сам мэйлер alm.php после себя очищает файл error.log. Не знаю, правильно это или нет, но меня напрягают эти здоровые файлы. Отправка реализована при помощи функции mail. Пока с ней проблем не было, но не исключаю, что, возможно, когда-нибудь заменю эту часть на работу с SMTP.
//php // Don't log possible errors in this script error_reporting(0); $conf = include_once 'config.php'; $records = getLogRecords($conf); if (count($records)) { sendEmail($conf, $records); } resetErrorLog($conf); function getLogRecords($conf) { $lines = array_reverse(file($conf['errorLogFile'])); $recordsMatch = array(); foreach ($lines as $line) { $line = trim($line); if (matchLine($conf, $line) && $line) { $recordsMatch[] = $line; } } return $recordsMatch; } function matchLine($conf, $line) { foreach ($conf['errorTypes'] as $errorType) { if (false !== mb_strpos($line, 'PHP ' . $errorType)) { return true; } } return false; } function sendEmail($conf, $records) { $subject = count($records) . ' errors at ' . date('Y-m-d H:i:s'); $body = ''; foreach ($records as $record) { $body .= $record . "\n\n"; } mail($conf['email'], $subject, $body); } function resetErrorLog($conf) { file_put_contents($conf['errorLogFile'], ''); }
Когда я запустил это на всех серверах, то мне в день приходило по ~50 писем, это был хороший стимул для баг фиксинга. Теперь приходит 2-3 письма в день.