Последую призыву Ивана Сагалаева, прозвучащему в его посте «Обсуждения через блоги», и выскажу свое мнение о логировании в приложениях. Поводом к этому посту послужила заметка Евгения Сергеева «Каким должен быть правильный лог-файл».
После прочтения заметки Евгения, хочется с ним поспорить. Основные посылы заметки: лог должен быть один, лог должен быть дружественен к администратору, лог должен содержать максимум информации и лог должен быть текстовым.
Во-первых, я крайне не согласен с тем, что лог должен быть един и для программиста и для администратора. У этих двух ролей разные цели и задачи, и информация им нужна разная. Область администратора — внешнее окружение приложения: настройки ОС, СУБД / хранилища, файловые системы и прочие системные вещи. Область же программиста — внутренности приложения: работа и взаимодействие модулей, структура и целостность данных в хранилищах, ошибки приложения и пользователей и т.п.
Для администратора важно видеть ошибки, вызванные внешними (по отношению к приложению) причинами: нехватка места на диске, упал сервер БД, закрыт порт и т.д. Внутренняя кухня приложения администратора не касается. Программисту же наоборот, надо как можно больше информации о произошедшей ошибке: где, почему, что было перед этим, состояние в момент ошибки, как произошла и т.п. Как эти противоположные цели уместить в один лог я не представляю. Ну, можно, конечно, писать все сообщения в текстовый файл добавляя префикс, по которому можно будет фильтровать записи. Но учитывая желание программиста писать в лог как можно больше данных, в любом случае пострадает читаемость:
- если принять «одна запись — одна строка» (доп. информацию каким-то образом сереализовать и умещать в той-же строке), то отсеивать нужные записи будет легко, но прочитать что-то кроме сообщения об ошибке будет крайне трудно;
- если подробности писать в читаемом виде (т.е. «одна запись — много строк»), то разбираться в конкретном сообщении будет значительно проще, но найти это конкретное нужное сообщение в получающейся «портянке» станет весьма непросто.
Во-вторых, лог в виде одного текстового файла можно реализовать, если приложение небольшое и работает на одном сервере. Для крупного приложения, работающего на двух и более серверах, это уже не приемлемо — начинается фрагментация лога, когда связанные каким-то образом сообщения (например, одной сессией пользователя) размазываются по нескольким файлам на разных серверах.
Еще одиним моментом, связанным с читаемостью лога, является повторение ошибки. Если вам не повезло и код вызывающий запись в лог выполняется часто, лог будет завален одинаковыми сообщениями. Что еще больше усложняет ручной разбор лога.
Над темой логирования я размышляю уже давно и статья Евгения лишь подтолкнул оформить свои мысли в виде поста блоге. Сразу скажу, что рассматривать буду достаточно крупные приложения на платформе LAMP и акцент буду делать с точки зрения программиста.
Предположим, что у нас несколько физических серверов на которых работают разные части нашего приложения: ядро системы, фронтенды, различные вспомогательные сервисы, и, в дополнение к этому зоопарку, javascript на клиентской стороне. Мне, как разработчику, хочется контролировать работу всех этих систем и в случае возникновения ошибки получить максимум информации о текущем состоянии приложения. Помимо места возникновения и тяжести ошибки, нужны данные о контексте: содержимое запроса, запрашиваемый URL, http-заголовки запроса (реферер, UA и пр.), состояние сессии пользователя, куки и прочие данные, доступные в этом месте и полезные для анализа причин ошибки.
Кроме лога ошибок часто требуется, чтобы приложение информировало о какой-то ситуации. Например, очередь сообщений достигла некой сигнальной величины, или внешний сервис некорректно обратился к нашему приложению (предположим что такая ситуация была предусмотрена и она была корректно обработана, но об этом хорошо бы знать). Часть таких ситуаций можно обработать отдельным сервисом мониторинга (например, zabbix или nagios), но это не всегда возможно.
Помимо фиксации ошибок и мониторинга еще оной задачей логирования является помощь в контроле работы определенных подсистем (или всего приложения в целом). В этом случае событием, вызвавшим запись в лог, будет являться выполнение определенного кода (например, начало и конец выполнения определенного метода).
Исходя из данных посылов я постараюсь описать идеальную (с моей точки зрения) систему логирования. Система должна:
- иметь одно (или несколько) хранилище логов для агрегации сообщений
- позволять настроить выбор типа хранилища для сохранения сообщения по различным критериям. Например, ошибки соединения с внешними сервисами (база данных, очередь сообщений, кэш и пр.) записывать в текстовый лог, сообщения о неудачной транзакции отправлять по email, а все остальное отправлять в центральное хранилище.
- иметь механизмы для изменения детализации сообщений «на лету». Например, сохранять только ссобщения с приоритетом WARNING и выше, или не сохранять контекст сообщения для приоритета INFO
- иметь удобный пользовательский интерфейс для доступа к центральному хранилищу. Этот интерфейс должен обеспечивать возможность просмотра в удобной форме поступивших сообщений
- иметь возможность разнообразной автоматизации. Например раз в сутки формировать письмо со списком ошибок за прошедшие сутки, или отправлять письмо тимлиду при возникновении новой ошибки (или ошибки определенного типа), или предоставлять возможность из сообщения сформировать тикет в системе багтрекинга, и т.п.
Я провел небольшое изыскание и нашел несколько проектов, похожих на то, что я обрисовал выше:
- Airbrake — платный сервис, предоставляющий веб-интерфейс к собранным сообщениям. Ориентирован на RoR и iOs приложения.
- Errbit — проект с открытым исходным кодом, API-совместимый с Airbrake
- Graylog2 — еще один проект с открытым исходным кодом. Написан на Java, включает в себя сервер для сбора логов и веб-интерфейс для их анализа. В качестве хранилища использует MongoDB
Библиотеки:
- Lagger — на первый взгляд, интересная библиотека для логирования
Ссылки по теме:
А что вы думаете по этому поводу? Может у вас есть опыт использования подобных систем? Критика, замечания и дополнения приветствуются!


Добавлю ссылку по теме логов
http://www.youtube.com/watch?v=HeWfkPeDQbY
Я правильно понял, что под «системой логирования» Вы понимаете некое приложение, которое позволяет анализировать собранные данные? Если так, то автоматически добавляется необходимость сопровождения данной системы как программного продукта. Который, кстати, тоже склонен к содержанию багов и следовательно тоже нуждается в лог-файле.
Для меня текстовый файл — наиболее информативный источник. Если структура сообщения продумана, то регулярные выражения — единственный инструмент, который нужен для качественного анализа.
А вот насчет нескольких хранилищ соглашусь. Я в своей заметке в большей степени выступал против той ситуации когда несколько логов для администратора, а если один лог для админ и один для программиста — это вполне нормальное. Мне главное чтобы меня не заставляли собираться информацию по крупицам из разных источников.
В том числе. Основной частью моей «идеальной системы логирования» должны быть механизмы агрегации и хранения логов из множества источников. Пользовательский интерфейс упрощает анализ сообщений.
Согласен. Но для крупных проектов это зачастую оправдано.
Пример сообщения можешь привести? У меня не получилось сформировать достаточно информативное сообщение удобной длинны — либо в сообщении достаточно информации для анализа, но оно совершенно неудобно для вычленения его из текстового лога, либо легко найти конкретное сообщение, но информации недостаточно.
Если приложение работает на более чем одном сервере, то с текстовыми логами придется этим заниматься.