Трассировка событий при логировании Попов Александр(@alexgpg), CTI(cti.ru) Зачем мы пишем логи? • Отладка. • Пишем прошедшие события. Кроме логов ничего нет. Если чтото не записали, то новой информации уже не будет. Проблемы анализа логов • Смешивание разных событий в одном логе. • В распределенной системе одно событие обрабатывается на нескольких машинах и записи об одном событии попадают в разные логи. • Для анализа логов нужно постоянно держать в голове контекст. Постоянно перемещаться между исходным кодом и логами. Антипаттерны логирования 1. Записи-близнецы • Не понять как различить и к чему относятся. Приходится понимать по косвенным признакам, по дополнительной информации. 2014-06-14 01:19:06 INFO: Request to API: user: [email protected] 2014-06-14 01:19:06 INFO: Request to API: user: [email protected] 2014-06-14 01:19:06 INFO: Request to API: user: [email protected] Антипаттерны логирования 2. Анонимный лог • Запись в логе в которой нет имени подсистемы. • Кто написал? • Доходит до ctrl+c ctrl+f по исходному коду, чтобы понять что это за подсистема Антипаттерны логирования 3. Отсутствие цели • Error request to api.something.com with code 500. • А что хотели-то? Антипаттерны логирования 4. Литературные логи • Request from server1.api.com from user ad12 with product id 18 • Текст не поискать по приложению • В отдельные нужные данные еще прицелится надо Антипаттерны логирования 5. Забытый отладочный вывод • puts user => logger.info user => logger.info «user: #{user}» Антипаттерны логирования 6. Object.inspect • Одновременно нечитаем человеком и машиной. #<User:0x00000001240990 @created_at=2014-06-13 23:13:01 +0400, @name="Petr", @organization=#<Organization:0x00000001240a08 @name="umbrella", @billing_id="122233">, @email="[email protected]", @external_id="5757585"> Антипаттерны логирования 7. Exception без стектрейса • Error Timeout reached. • Ээээ...а где оно возникло и где обработалось? Трассировка событий • Способ пометить всю цепочку сообщений одного события, чтобы отличать от остальных. • В начале обработки события генерируется уникальный ID и записывается в каждом сообщении в лог. • Этот ID передается через все обработчики, все слои приложения и машины участвующие в обработке. Трассировка событий Трассировка событий В коде(log4r) • Используем Nested Diagnostic Context (NDC) # Logging init logger = Log4r::Logger.new 'common' outputer = Log4r::Outputter.stdout outputer.formatter = Log4r::PatternFormatter.new(pattern: '%d %l: [%x] %m ') logger.add outputer # New request Log4r::NDC.push uuid() logger.info 'Incoming request' #... logger.info 'In progress' #... logger.error 'Bad params Трассировка событий В коде(ext_logging) ev = UserEvent.new ext_logger.info ev, 'Incoming request' ext_logger.info ev, 'In progress' ext_logger.error ev, 'Bad params' Трассировка событий В логе 2014-06-13 21:43:50 INFO: [9cc6fdc1] Incoming request 2014-06-13 21:43:50 INFO: [afc8ba03] In progress 2014-06-13 21:43:50 INFO: [9cc6fdc1] In progress 2014-06-13 21:43:50 ERROR: [9cc6fdc1] Bad params Трассировка событий Генерация ID события • Искусственная — просто генерируем новый уникальный ID. • Естественная — берем ID уже существующий в бизнес-логике. Например, ID транзакции из внешней системы. Трассировка событий Иерархическая структура событий • Обработка события может состоять из нескольких подзадач. • Интересно наблюдать каждую из подзадач раздельно и различать события в них друг от друга. • При этом есть главное инициирующее событие — корень дерева событий. Трассировка событий Что еще записать в лог • Короткое имя события(reg_user, create_conf). Тогда из записи будет понятна конечная цель • Пользователя-инициатора события. Логин, email, ip. • Подсистему или класс. I, [2014-06-04T03:48:09.422777 #17400] INFO -- : [b9f64570] (add_resource){[email protected]} <ResourcesService> | Add limit |=> {"company":"umbrella", "limit":"12"} Трассировка событий Преимущества • Разные события различимы. • Много контекста пишется сразу. • grep позволяет фильтровать по различным признакам. I, [2014-06-04T03:48:09.422777 #17400] INFO -- : [b9f64570] (add_resource){[email protected]} <ResourcesService> | Add limit |=> {"company":"umbrella", "limit":"12"} Хранимые события • Хранятся в базе. • Поиск средствами БД по множеству параметров(SQL, MongoDB query). • Можно показывать прямо в интерфейсе приложения. • Перезапуск обработки события в случае неудачи. Хранимые события Схема БД • • • • • • Уникальный ID Короткое имя Инициатор: ID или имя пользователя Время создания Статус: IN_POGRESS, DONE, FAILED Дополнительные данные в свободном формате(json, hstore) Хранимые события Трассировка событий в логах • Используем ID сохраненного события как ID для трассировки. ext_logging • Гем для поддержки трассировки событий в логах. • Трассировка событий. • Иерархия событий. • Пишет класс откуда был вызван логер. • https://bitbucket.org/alexgpg/ext_logging • Пока в разработке. Что почитать или посмотреть? • • • • Nail B. Harrison «Patterns for Logging Diagnostic Messages» Zipkin - distributed tracing system http://twitter.github.io/zipkin/ http://www.infoq.com/presentations/Zipkin ddima Дядя Дима - Логи ddima.livejournal.com/64901.html - часть первая ddima.livejournal.com/65086.html - часть вторая ddima.livejournal.com/65668.html - часть третья ddima.livejournal.com/66497.html - часть четвертая Выводы • Трассировка событий — простой полезный паттерн, который экономит время анализа логов. • События можно хранить в БД. Это дает возможности для гибкого задания параметров поиска по ним. Спасибо Вопросы?
© Copyright 2022 DropDoc