1. Резюме
Ведение журнала, часто задний ход в цикле разработки, может фактически стать жизненно важным для команды разработчиков после того, как приложение будет запущено. Предполагая, что читатели хорошо знакомы с различными средами ведения журналов, такими как Log4J, SLF4J и т. Д., В этой статье изложены рекомендации по ведению журналов в реальных условиях, исследуется его влияние на атрибуты качества приложений, а также вновь открывается забытая высокопроизводительная, более интеллектуальная техника ведения журналов с коды и централизованная регистрация.
2 Введение
Ведение журнала часто отодвигается на задний план при архитектуре, проектировании и разработке приложений или даже при расширении приложений. Наконец, когда приложение готово, вы развертываете его. И что тогда происходит?
Ваше приложение теперь находится вне вашей среды разработки — оно не исчерпывает вашу любимую среду разработки IDE и тем более не имеет отладчика к вашим услугам. Теперь вы понимаете важность журналов. И когда вы просматриваете огромный набор журналов, пытаясь отладить любую проблему с вашим приложением, вы понимаете, что это не тривиальная задача. Это скучно, утомительно и требует много времени. Вы спрашиваете себя, со всем вашим опытом и знаниями, это то, что вам суждено было сделать — найти иголку в стоге сена бревен! Или, может быть, вы перекладываете это занятие на своих подчиненных или на команду поддержки приложений, которая в равной степени проклинает вас за утомительную и неблагодарную работу! Или, может быть, они просто опустят руки, а вы, архитектор / дизайнер, будете участвовать,бормоча себе под нос, как твои навыки теряются.
Журналы могут быть самой надежной основой вашего производственного приложения, и их не следует воспринимать легкомысленно или в качестве запоздалой мысли. Конечно, большинство из нас знает основы — что существуют различные уровни ведения журналов, которые можно включать или выключать по желанию, что существуют категории журналов и с использованием любимой среды ведения журналов — Log4J, Commons Logging или SLF4J, можно направлять журналы в различные пункты назначения. такие как файлы, базы данных, очереди JMS и т. д.
Но сколько из нас на самом деле планируют наши журналы? Кто из нас понимает, как логирование влияет на другие атрибуты качества системы? Сколько из нас постоянно сокращает журналы, имея в виду, как журналы могут повлиять на нашу систему и нашу жизнь после запуска приложения? Кто из нас использовал расширенные функции наших любимых каркасов для достижения высокой производительности?
В этой статье делается попытка подчеркнуть важность этого часто игнорируемого, но жизненно важного аспекта приложения и приводятся рекомендации по ведению журналов приложений. Наконец, он восстанавливает дизайн забытой техники ведения журналов, которая могла бы обеспечить высококачественное ведение журнала без ущерба для производительности и других атрибутов качества.
3 Ведение журнала по отношению к другим атрибутам качества системы
3.1.1 Мониторинг
Ведение журнала является наиболее частой реализацией атрибута мониторинга. Это помогает разработчику приложения найти причину ошибок приложения. Но часто это делается для того, чтобы быть единственной реализацией Мониторинга, возможно, потому, что для разработчика приложений проще всего написать оператор System.out.println () или logger.log () в различных местах код. Однако существует такая вещь, как слишком большое ведение журнала, которое может привести к тому, что будут пролонгированы полезные журналы происшествий, что нанесет ущерб самой цели и намерению ведения журнала. Разработчикам приложений будет полезно найти другие методы мониторинга системы, такие как использование или разработка консолей JMX. Это будет подробно обсуждаться в разделе «Ведение журнала для готовых приложений».
3.1.2 Производительность
Спросите любого специалиста или архитектора по производительности, и почти в 90% приложений было обнаружено, что чрезмерное ведение журналов очень сильно влияет на производительность. Ведение журнала — это интенсивная операция ввода-вывода, которая может повлиять на производительность приложения, особенно если ведение журнала выполняется традиционным способом, то есть синхронной записью в FileAppender в контексте потоков приложения. Мало того, это часто может привести к большому потреблению кучи и сборке мусора из-за регистрации кода, такого как —
if (logger.isDebugEnabled()) logger.debug("name "+person.name+" age "+person.age+" address "+person.address);
Кроме того, метод doAppend (), который вызывается изнутри для входа в приложение Log4J Appender, синхронизируется для обеспечения безопасности потоков. Это также означает, что потоки приложения не только синхронно выполняют операции ввода-вывода с тяжелым диском, но и блокируют друг друга во время записи в журнал! В одной из критических ситуаций, связанных с производительностью портала электронного управления, дамп потока обнаружил, что потоки портала блокируют друг друга для выполнения входа в один файловый appender, поскольку журналы приложений записываются в один набор файлов appender!
Фактически, определение текущего уровня журнала приложения — это в первую очередь то, что делает специалист по производительности, и зачастую просто изменение уровня журнала с DEBUG на INFO или WARNING дает значительные преимущества в производительности. Однако после того, как тест производительности производительности или немедленная проблема масштабируемости были решены, какой-то разработчик приложения снова пытается изменить уровень журнала на DEBUG, пытаясь найти основную причину функциональной ошибки в приложении. Это свидетельствует о нездоровой практике ведения журнала. В разделе «Ведение журнала для готовых приложений» мы также обсуждаем дисциплину и соблюдение гигиены бревен. В разделе «Высокопроизводительная и качественная регистрация» разрабатываются методы, позволяющие добиться качественной регистрации без ущерба для производительности приложения.
3.1.3 Безопасность (аудит и другая конфиденциальная информация)
Журналы аудита — это особый класс журналов, которые включают аудит безопасности приложения и используются для отслеживания действий пользователей. Это пример того, как ведение журнала помогает использовать методы обеспечения безопасности.
Однако, с другой стороны, если журналы содержат конфиденциальную информацию, такую как пароли учетных записей пользователей, они могут представлять уязвимость системы.
В-третьих, регистрация событий и потока приложения может помочь разработчику в мониторинге и отладке приложения, но также может раскрыть внутреннюю архитектуру приложения, что, безусловно, нежелательно.
В современных средах облачных приложений, где приложения могут размещаться в общедоступных облаках, такие уязвимости могут создавать риски для интеллектуальной собственности владельца приложения.
3.1.4 Масштабируемость и высокая доступность
Ведение журнала также влияет и зависит от масштабируемости и высокой доступности. Повышая производительность приложения с помощью методов «Высокопроизводительная и качественная регистрация», вы повышаете масштабируемость и доступность приложения с меньшим количеством оборудования, поскольку ваше приложение уже может упаковать более мощный удар в существующие ресурсы и имеет меньше причин для отказа.
Когда приложение масштабируется или активируется для пассивно-активной конфигурации для доступности, существует несколько экземпляров приложения, и стратегия ведения журнала становится важной. Желает ли группа поддержки или разработки приложений собирать журналы с 10 разных компьютеров или каталогов или иметь централизованное место для сбора журналов? Вот где централизованное распределенное ведение журнала становится необходимым.
3.1.5 Восстанавливаемость
Основные базы данных, такие как Oracle, уже используют журналы повторов для обеспечения возможности восстановления транзакций. Приложения могут также заимствовать лист и использовать специальный класс журналов для восстановления, если это необходимо.
3.1.6 Обработка ошибок и отказоустойчивость
В большинстве приложений ведение журнала является одной из мер, которые иногда используются для обработки ошибок. В случаях повторяющихся ошибок, таких как недоступность сервера SMS / Mail или даже базы данных в течение длительных периодов времени, не будет получено никаких преимуществ и даже много вреда, если регистрировать ошибку многократно и часто, особенно с огромными следами стека исключений, из-за увеличения Активность ввода / вывода. В процессе можно обнаружить, что важные журналы, которые были важны для анализа недельной давней проблемы, были перенесены. Такой подход только ухудшает плохую ситуацию.
3.1.7 Вместимость
При измерении емкости приложения архитекторам было бы полезно учитывать размер журналов, которые будут создаваться приложением во время производства, и оценивать требуемое дисковое пространство, предоставление централизованной файловой системы и так далее.
Для централизованного ведения журнала в распределенной среде также важно оценить размер объектов журнала, распределенных по сети на удаленном компьютере.
4 Тематическое исследование о пропущенной важности лесозаготовок
В этом разделе представлен опыт автора в форме примера внедрения встроенного приложения, в котором важность ведения журнала была упущена на этапе архитектуры, проектирования и разработки, но позже его можно было довести до дома через горькие уроки, усвоенные трудным путем.
Рассматриваемое встроенное приложение представляло собой устройство GPS, которое должно было быть развернуто на транспортных средствах для обеспечения отслеживания местоположения. Устройство не обеспечивало никакого пользовательского интерфейса, кроме светодиодов и нескольких кнопок, поэтому не было бы никого, кто мог бы управлять приложением внутри транспортных средств, в отличие от роскошного, который используется для приложений на стороне сервера. Так что, если что-то пошло не так с приложением устройства, как разработчики приложения должны были бы его диагностировать, когда все журналы записывались внутри устройства и передавались по всей стране внутри грузовиков?
Разработчики приложений наивно полагали, что у организации-клиента будут почти во всей Индии инженеры по обслуживанию, которые смогут снять устройство и принести его для анализа. Это было невозможно, одному из разработчиков пришлось сопровождать сервисных инженеров, чтобы скопировать журналы, войдя в операционную систему устройства. Вы можете себе представить, какое влияние оказали эти поздние ночевки на его здоровье и душевное состояние.
Следующим шагом, который сделали разработчики приложения, было создание кнопки загрузки журнала в приложении для обслуживания настольных компьютеров для устройства. Сервисные инженеры будут нести приложение для обслуживания настольных компьютеров в ноутбуках и загружать журналы с устройств. Это было, по крайней мере, улучшением, так как устройство не нужно было снимать с автомобиля, и появилась передышка для плохого разработчика, который ранее сопровождал сервисных инженеров в отдаленные места в безбожные часы. Однако вскоре выяснилось, что сервисные инженеры также не могут постоянно ездить в удаленные места, и они требуют, чтобы загрузка журналов осуществлялась командой разработчиков приложений.
Наконец, команде разработчиков пришлось усовершенствовать приложение устройства, чтобы оно могло отправлять свои журналы на внутренний сервер по требованию через беспроводную GPRS точно так же, как оно отправляло другие данные отслеживания.
Здесь следует отметить, что все эти дополнительные усилия, безусловно, не были учтены при сборе требований и не были учтены в бюджете во время первоначальной оценки и разработки. У команды разработчиков было типичное мышление, соответствующее требованиям клиентов Ведение журнала приложений не было требованием заказчика и не являлось заметным нефункциональным атрибутом, и у начинающих разработчиков не было предвидения, чтобы убедить своих столь же близоруких старших руководителей или менеджеров дать им время для создания такого средства, как бюджетное усилие , И когда десятки этих устройств были запущены (с сотнями больше в магазине), и они столкнулись со всеми вышеупомянутыми проблемами, им пришлось сжечь полночное масло, пока их менеджеры и клиенты сердито дышали им в шею. Такая неблагодарная работа!
5 Ведение журнала для готовых приложений
В предыдущем разделе «Ведение журнала в отношении других атрибутов качества системы» мы уже сталкивались с некоторыми проблемами, с которыми сталкиваются в производственной среде. Давайте перечислим их и многое другое в этом разделе о том, что можно и чего нельзя делать, чтобы подготовить производство приложений.
· Дисциплина и проверка кода логов
Дисциплина имеет первостепенное значение, и этот единственный шаг проложит путь к другим лучшим практикам, обсуждаемым в этой статье. Есть много производственных систем с несерьезными бревнами, такими как «Привет», «Пришел сюда», «Готово», «XXXYYYYZZZZ». Скорее всего, они были введены во время отладки приложения или даже во время модульного тестирования на этапе разработки приложения.
Оправдание для таких журналов в том, что они будут на уровне отладки и могут быть легко отключены. Однако на практике это делается редко, и, более того, существуют другие журналы на уровне отладки, которые не так легкомысленны. Для управления такими журналами потребуется чрезвычайно детальный и тщательный уровень конфигурации инфраструктуры ведения журналов, и это довольно часто упускается в работе.
Обзоры кода должны быть более эффективными, и старшие разработчики или руководители групп, просматривая журналы, должны быть твердыми, чтобы удалять менее полезные журналы, даже при появлении вызывающих комментариев, таких как: «Я только что сделал это для тестирования», «В чем суть проблемы» Все это; это просто журнал ». Было бы хорошо иметь правило, что журналы не должны быть средством отладки основных проблем во время разработки — для этого у нас есть отладчики в IDE!
· Классифицируйте журналы с той же тщательностью, что и при модульности приложения.
Это кажется очевидной практикой, но удивительно, сколько раз в производственной среде было замечено, что журналы приложений записываются с файлами SystemOut или SystemError сервера приложений или, как обсуждалось ранее, в случае, когда потоки портала электронного управления были блокируя друг друга, борясь за одного FileAppender и, в свою очередь, за один файловый ввод / вывод.
По крайней мере, ожидается, что разработчики будут иметь соглашение о присвоении имен на основе пакетов или полностью квалифицированное имя класса для получения регистраторов и, возможно, использовать разные назначения Appender для разных классификаций журналов.
Было бы хорошо иметь в виду, что уровень журналов во время производства должен быть ПРЕДУПРЕЖДЕН или, в зависимости от информации в журналах, на уровне INFO.
Эффективным методом было бы перечислить все возможные журналы в центральной конфигурации или классах констант и позволить разработчикам использовать только эти журналы. Более эффективный метод обсуждается в разделе «Проектирование высокопроизводительных интеллектуальных журналов».
· Вход в кластерную и распределенную среду
Почти все производственные серверные приложения должны быть кластеризованы и распределены для обеспечения масштабируемости и / или доступности. В кластерной среде журналы должны отражать компоненты, модули, подсистемы и даже экземпляры процессов, откуда они возникли.
Существует большое преимущество наличия централизованного сервера журналов в распределенной и кластерной среде, чтобы избежать хлопот сбора журналов из нескольких каталогов и машин. Это также будет иметь чрезвычайно полезный побочный эффект перемещения ввода-вывода на отдельную машину, так что при регистрации операций ввода-вывода производительность приложения не будет снижена.
· Вход в толстые распределенные клиенты или встроенные приложения
Как показано в анекдоте, описанном в разделе «Пример отсутствия важности ведения журнала», журналы в толстых клиентах или встроенных приложениях не всегда легко доступны для группы разработчиков, чтобы помочь им проанализировать дефекты. Механизм удаленной передачи журналов должен быть хорошо продуман и разработан с должным включением в план проекта.
· Использование сопоставленного диагностического контекста и вложенного диагностического контекста
MappedDiagnosticContext (MDC) и NestedDiagnosticContext (NDC) Log4J используют хранилище ThreadLocal для хранения информации, специфичной для контекста. Они могут использоваться для хранения информации, такой как имя пользователя или идентификатор транзакции, чтобы идентифицировать все операции, выполненные конкретным пользователем или транзакцией. Это избавляет от необходимости передавать специфическую для контекста информацию через классы и методы только с целью ведения журнала. При использовании PatternLayout% x или% X {key} сохраненное значение будет отображаться в журнале.
· Планирование жизненного цикла и ведение бревен
Это включает в себя планирование размера каждого файла журнала и максимального количества файлов, прежде чем они будут пролонгированы. Это не сложно, но часто происходит — размер файла журнала не должен быть таким огромным, чтобы его нельзя было открыть с помощью текстового редактора! Так же, как существуют сценарии для регулярного резервного копирования базы данных, также должны быть сценарии для резервного копирования и архивирования журналов. Рекомендуется заархивировать файлы журналов на случай, если на диске будет ограничено пространство, что также облегчит их удаленную передачу.
· Не поддавайтесь искушению регистрировать информацию о местоположении источника во время выполнения
Информация о местонахождении приходит ценой потери производительности, так как каркас журналирования пытается определить текущий стек потоков и, следовательно, метод, имя файла и номер строки, что является дорогостоящей операцией. Скорее, самой информации журнала должно быть достаточно, чтобы выяснить источник журнала, предоставив информацию о сервере, подсистеме, модуле, компоненте, потоке и так далее.
· Избегайте ошибок записи с длинными трассами стека
Если возможно, в журнале должно быть достаточно информации, чтобы указать, где произошла ошибка, и следует по возможности избегать огромных следов стека. Конечно, это не мандат, особенно для исключений, таких как NullPointerException. Но это может быть сделано для некоторых конкретных ошибок приложения, которые могут быть легко идентифицированы. Кроме того, когда существует повторяющаяся проблема, которая сохраняется в течение длительного периода времени, например проблема с подключением к электронной почте, серверам SMS или серверам баз данных, было бы хорошо записывать проблему каждые 5 минут или около того, вместо того, чтобы заполнять журналы огромным стеком. следы каждые несколько секунд.
· Не используйте AOP без разбора для инъекций журналов, особенно в производстве
Самый базовый пример учебника AOP, данный новичку, предназначен для регистрации. Аргумент заключается в том, что ведение журнала является сквозной задачей, и можно использовать возможности AOP для ввода журналов перед входом или после выхода из метода. Этот пример или аргумент должны быть серьезно рассмотрены перед применением в производственных достойных приложениях. Как уже было установлено выше, регистрация не является пустяком, но она заслуживает планирования, как и большинство других нефункциональных требований (NFR).
· Не используйте ведение журнала в качестве замены для других стратегий мониторинга
Один из самых причудливых случаев использования ведения журнала — это «журналы производительности», такие как:
19 сентября 2010 10:20:30 PERF INFO Thread-25 OrderInsertAction.java Время, затрачиваемое на обработку OrderInsertAction: 50 мс
19 сентября 2010 10:20:33 PERF INFO Тема-8 OrderInsertDao.java Время, затраченное на вставку 30 мс
Автор была виновна в том, что делала это сама, не понимая, что она ставит под угрозу саму производительность, которую она измеряла, увеличивая число операций ввода-вывода.
Что было бы бесконечно лучшей практикой, так это захватывать «TimeStatistic» с общим временем и счетчиком, чтобы дать среднее время, максимальное время и минимальное время, затраченное на это, и отображать его на экране графического интерфейса.
6 Дизайн высокопроизводительной интеллектуальной системы ведения журналов
Стратегия, обсуждаемая в этом разделе, состоит в том, чтобы объединить централизованное ведение журнала с фасадом средства ведения журнала, который использует целочисленные коды вместо строк для журналов. Эта техника была использована автором по совету ее наставника с большим успехом.
В Интернете существует множество статей, посвященных созданию централизованных журналов с очередями и темами JMS или даже с сокетами. Централизованное ведение журнала обеспечивает высокую производительность, перемещая операции ввода-вывода на другую машину, оставляя узлам приложений небольшую нагрузку из-за сетевого ввода-вывода.
Однако ключевой момент здесь — объединить централизованное ведение журнала с использованием кодов вместо длинных строк. Практика использования строк для регистрации информации, невинно поощряемая существующими инфраструктурами, такими как Log4J или Commons Logging, приводит к использованию ценных ресурсов памяти, диска и сети, где может быть достаточно простого кода.
В отдельном файле может быть отображено соответствие между кодами ошибок и полной расшифрованной строкой.
Рассмотрим следующий журнал
[090822 16:02:48] ПРЕДУПРЕЖДЕНИЕ О ПЕРЕДАЧЕ (Tx-2-thread-1: 1163 TransmitData): сервер не ответил ACK, поэтому повторите попытку.
по сравнению с
1300604499194,4,192168001002,20600,1001,2,500000
Приведенный выше журнал указывает отметку времени в long, уровень журнала, ip-адрес компьютера, генерирующего журнал, целочисленные значения для процесса, модуль процесса, идентификатор экземпляра приложения и интегральный код ошибки, который при переводе будет передавать то же значение, что и полная длинная строка. Такой объект также чрезвычайно легок для передачи по сети в двоичном формате. В случае наличия контекстной информации для дальнейшего уточнения информации в журнале, массив Object [] также может быть передан, в то время как основной код ошибки будет преобразован в строку с заполнителями, как в формате printf ().
Использование коротких кодов для ошибок — практика, которая довольно распространена почти во всех основных продуктах, таких как Oracle, WebSphere, Microsoft. Например, в приложениях Microsoft Office при возникновении ошибки все, что появляется в диалоговом окне ошибки, представляет собой неразборчивый целочисленный код, который можно отправить в службу поддержки Microsoft для диагностики.
Различные коды ошибок могут быть преобразованы в полные строки переводчиком журнала во время просмотра.
Есть следующие преимущества для рассмотрения —
· Сокращение дискового пространства и тем самым более длительный срок хранения журналов и меньший размер файла
· Некоторая безопасность в том, что внутренний дизайн и работа приложения не обнаруживаются в журнале. Журналы могут быть переведены в полный текст с помощью переводчика для просмотра в автономном режиме.
· Сокращение использования памяти за счет исключения построения или передачи по сети длинных строк.
· Поскольку журналы, передаваемые в сети, чрезвычайно легки, можно поддерживать даже отладочный вход с минимальными издержками.
· Не допускается случайное построение бревен
· Более эффективный поиск конкретных ошибок с помощью пользовательских инструментов.
Кроме того, дисциплина ведения журналов может быть обеспечена путем предотвращения прямого использования Log4J или других подобных сред и написания собственного фасада поверх вашей любимой среды ведения журналов или настраиваемого ведения журнала, такого как —
public class LogClientFacade { public void log(int logLevel, int instanceId, int subsystemId, int componentId, int errorCode); public void logWithContext(int logLevel, int instanceId, int subsystemId, int componentId, int errorCode, Object[] contextInfo); public void logWithEx(int logLevel, int instanceId, int subsystemId, int componentId, int errorCode, Throwable ex); ... }
Такой интерфейс журнала обеспечит, чтобы разработчики позаботились о регистрации важной информации, такой как подсистемы, компоненты и т. Д., Для диагностики проблем в распределенной среде и избавил бы от необходимости, например, записи номера строки источника и имени файла с помощью дорогостоящих операций времени выполнения. ,
На приведенной выше схеме показан предлагаемый дизайн для такого решения. Намерение состоит в том, чтобы сделать процесс регистрации как можно более неблокирующим путем сбора информации в очередях и асинхронной обработки или передачи ее в потоках приемника. Максимальная выгода была бы получена при передаче информации в двоичном сериализованном формате по сети, особенно если полное решение однородно использует один язык.
Там будет простой графический интерфейс для просмотра журналов, когда они вливаются в сервер, а также просматривать автономные журналы. Он будет использовать переводчик для преобразования журналов в текстовый формат. Сами журналы записываются на диск в двоичном формате. Можно отметить, что эта методология имеет существенное значение в облачных средах для защиты конфиденциальности интеллектуальной собственности развертывателя.
6.1 Примечание о внедрении
Можно расширить существующие фреймворки, такие как Log4J / Commons Logging / SLF4J. Тем не менее, при этом может быть некоторое снижение эффективности, чтобы соответствовать общей природе внутренних API фреймворков. Например, Log4J сериализует сообщения журнала и трассировки стека как строки для отправки их по сети в SocketAppender и JMSAppender. Довольно легко расширить и переопределить выбранные части выбранных каркасов, например, путем добавления или расширения новых Appenders, расширения внутренних объектов передачи данных, таких как LoggingEvent, и выполнения настраиваемой сериализации. Или же можно просто создать простую пользовательскую структуру ведения журнала, которая не займет много времени для реализации, если требуется максимальная гибкость.
Другое интересное решение — использовать ли JMS, которую можно использовать, если приложение выполняется на сервере приложений, или с помощью автономной очереди, такой как WebSphereMQ, HornetQ или ActiveMQ. Тем не менее, следующий совет автора, если выбранный транспорт является JMS-
· Используйте мягкие атрибуты качества — например, избегая транзакций, избегая постоянства и допуская дубликаты в транспорте очереди. Помните, что строгая надежность снижает производительность и, скорее всего, не требуется для журналов.
· В пределах одной JVM, которая находится либо на сервере журналов, либо в клиентских подсистемах, рекомендуется использовать либо легковесные очереди java.util.concurrent, либо реализацию очереди в ВМ, которая позволит избежать издержек сериализации.
· Было бы целесообразно использовать посредники сообщений или мосты для транспорта, а не иметь централизованную очередь и делать удаленные вызовы к ней.
Личное предпочтение автора вместо этого использует простые сокеты.
7 Заключение
В этой статье мы обсудили лучшие практики и выявили ошибки при ведении журнала. Мы также предложили методику объединения централизованного ведения журнала с использованием кодов вместо строк в качестве высокопроизводительной практики более разумного ведения журнала.
Автор считает, что ее бывший наставник, г-н Акаш Гупта, архитектор решений в InterGlobe Technologies (() техника.
8 ссылок
Pro Apache Log4J от Самудры Гупты