Сверхпростое логгирование в javascript

Зачем оно вообще надо?

Не все перфекционисты — инженеры, но все инженеры — перфекционисты (ну, почти). Нам нравятся красивые лаконичные абстракции. Мы видим красоту в наборе кракозябликов, которые человек неподготовленный и прочитать не сможет. Нам нравится чувствовать себя богами, создавая микро-вселенные, которые живут по нашим правилам. Предположительно, все эти качества берут начало из нашей необъятной лени. Нет, инженер не боится работы как класса, но люто ненавидит рутинные повторяющиеся действия, которые руки так и тянутся автоматизировать.

Написав несколько тысяч строк кода, предназначенного только лишь для логгирования, обычно мы приходим к созданиям каких-то своих паттернов и стандартов написания сообщений. К сожалению, нам все еще приходится применять эти паттерны вручную. Главное «зачем» class-logger — предоставить декларативный конфигурируемый способ простого логгирования шаблонных сообщений при создании класса и вызове его методов.

Что нужно логировать

логировать обязательно

  1. Начало/конец работы приложения. Нужно знать, что приложение действительно запустилось, как мы и ожидали, и завершилось так же ожидаемо.
  2. Вопросы безопасности. Здесь хорошо бы логировать попытки подбора пароля, логирование входа важных юзеров и т.д.
  3. Некоторая информация для дебага, с соответственным уровнем логирования.
  4. Некоторые SQL скрипты. Есть реальные случаи, когда это нужно. Опять-таки, умелым образом регулируя уровни, можно добиться отличных результатов.
  5. Выполняемые нити(Thread) могут быть логированы в случаях с проверкой корректной работы.

Что записывать в лог ?

Понимая суть процесса отладки, мы с легкостью ответим на этот вопрос: 

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

Невозможно, да и не нужно, фиксировать все состояния во все отрезки времени. Например, полиции достаточно лишь нескольких точных набросков, а не видеоклона, для поимки преступника. Тоже самое относится и к логам: разработчикам нужно только внести в них информацию о том, когда происходит переход в критическое состояние. Кроме того, логи должны содержать ключевые характеристики текущего состояния и причину перехода. 

Переход в критическое состояние 

Не все переходы состояний стоит записывать в лог

Важно рассмотреть программу как серию изменяемых состояний, разделить их на фазы и затем сосредоточиться на времени, когда выполнение переходит от одной фазы к другой. . Предположим, что существуют 3 фазы запуска приложения: 

Предположим, что существуют 3 фазы запуска приложения: 

  • загрузка настроек программы; 
  • подключение к зависимостям; 
  • запуск сервера. 


Запуск приложения с точки зрения переходов состояний 

Было бы очень разумно вести логи в начале и конце каждой фазы. Если бы произошла ошибка на этапе подключения к зависимостям и приложение бы зависло, то логи отчетливо показали бы, что после загрузки настроек оно вошло во вторую фазу процесса, не завершив его. Располагая этой информацией, разработчики смогли бы быстро определить проблему. 

Ключевые характеристики 

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

Например, когда HTTP-сервер переходит из состояния ожидания запроса в состояние получения запроса, он должен зафиксировать в логе HTTP-метод и URL, так как они описывают основы HTTP-запроса. Остальные его элементы (заголовки или часть тела сообщения) записываются в том случае, если их значения влияют на бизнес-логику. Например, если поведение сервера сильно отличается между состояниями Content-Type:application/json и Content-Type:multipart/form-data, заголовок следует записать. 

Причина перехода состояния 

Логирование причины перехода состояния чрезвычайно полезно для отладки. Логи должны кратко охватывать содержание предыдущих и следующих состояний, а также объяснять их причины. Они помогают разработчикам получить общую картину и ориентироваться в процессе реконструкции (отладки) выполнения программы. 

Пример 

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

Вот несколько анти-шаблонов логов, в которых отсутствуют ключевые характеристики состояния и причины: 

  • server.go: Error processing request (Запрос на обработку ошибок)
  • server.go: SSN rejected (Номер социального страхования отклонен)
  • server.go: SSN rejected for user UUID “123e4567-e89b-12d3-a456–426655440000” (Номер социального страхования отклонен для пользователя UUID “123e4567-e89b-12d3-a456–426655440000”)

Все они содержат определенную информацию, но ее недостаточно для ответов на вопросы, которые могут возникнуть у разработчиков в процессе поиска ошибки. Какой запрос не смог обработать сервер? Почему номер социального страхования был отклонен? Какой пользователь столкнулся с этой ситуацией? Грамотный и полезный для отладки лог будет выглядеть так: 

server.go: Received a SSN request(track id: “e4a49a27–1063–4ab3–9075-cf5faec22a16”) from user uuid “123e4567-e89b-12d3-a456–426655440000”(previous state), rejecting it(next state) because the server is expecting SSN format AAA-GG-SSSS but got **-***(why) 

( server.go: Получен запрос номера социального страхования (трек id: “e4a49a27–1063–4ab3–9075-cf5faec22a16”) от пользователя user uuid “123e4567-e89b-12d3-a456–426655440000” (предыдущее состояние), запрос отклонен (следующее состояние), так как сервер требует номер социального страхования в формате AAA-GG-SSSS, а получил **-*** (причина)

Monolog

MonologPSR-3

  • Logger — это объект, который мы используем для записи логов. Сам логгер не занимается записью, но управляет хендлерами. Может быть создано любое количество.
  • Handler — объект, который непосредственно обрабатывает данные. Вы можете добавить сколько угодно хендлеров в логгер. Все они будут вызываться по очереди, независимо от того смог данный хендлер обработать ошибку или нет. Метод isHandling определяет сможет ли этот хендлер обработать поступившую ошибку.

    Самое близкое сходство с хендлером, с моей точки зрения, это Event Observer.

  • Processor — любая вызываемая сущность (callable). Может быть несколько. Могут быть назначены как глобально, так и установлены для хендлера. Сначала запускаются глобальные процессоры. Основная задача процессора добавить дополнительные данные в лог (например IP, с которого был коннект, значение глобальных переменных, информация на какой git ветке сейчас находится код и так далее).
  • Formatter — преобразует вывод сообщения перед записью. Может быть только 1 на хендлер. Нужен для изменения форматирования тела сообщения, например для преобразования текста в html или json.
  • Channel — имя логгера. Оно будет написано при записи лога. Так как 1 хендлер может быть применен в 2ух разных логгерах (будет писать логи в 1 и тот же файл) это позволит определить откуда пришла ошибка.
  • Level — уровень ошибки. Данный параметр у хендлера означает минимальный уровень ошибки, который будет им обрабатываться.
  • Bubble — всплытие сообщения. После того, как хендлер обработал сообщение, то логгер передает сообщение следующему хендлеру. Этот процесс можно остановить с помощью свойства bubble. Если у хендлера значение этого свойства false (по умолчанию всегда true), то после того как этот хендлер выполнит свою работу (смог обработать данную ошибку), другие хендлеры уже не запустятся.
  • Sort Order — порядок выполнения. Последний добавленный хендлер всегда запускается самым первым. Именно эта особенность позволяет внедрять механизм полного отключения логгера (через bubbling false). Хендлеры добавленные через конструктор идут в порядке указанном в конструкторе.

Удобство

http://loggers.ru Длина: 7 символов

Старайтесь использовать Ваши URL-адреса сайта короткими и избегайте длинных доменных имен, когда это возможно. Описательный URL лучше распознается поисковыми системами. Пользователь лучше видит о чем предположительно страница сайта до перехода на сайт из поиска. Тем самым будет улучшен поведенческий фактор, и ваш посетитель не закроет сразу страницу посещенного сайта (например, http://www.mysite.com/ru/products).

Отлично, ваш сайт имеет favicon.

Favicon улучшает узнаваемость бренда в Yandex поиске и закладках браузера. Поскольку фавикон особенно важен для пользователей закладок вашего сайта, убедитесь, что он соответствует вашему бренду и гармонично отражает тему и содержание сайта.

Отлично, ваш сайт имеет пользовательскую страницу ошибок 404.

Когда посетитель сталкивается с 404 File Not Found error на вашем сайте, вы находитесь на грани потери посетителя из поисковой системы и других источников ! Создание пользовательской страницы 404 File Not Found позволяет свести к минимуму количество посетителей, потерянных таким образом.

47 КБ (средний показатель по всемирной паутине составляет 320 кб)

Двумя основными причинами увеличения размера страницы являются изображения сайта и файлы JavaScript. Размер страницы влияет на скорость загрузки вашего сайта; старайтесь держать Размер страницы ниже 2 Мб.
Совет :используйте изображения небольшого размера и оптимизируйте их (Размер и вес) ПЕРЕД ЗАГРУЗКОЙ на свой сайт . Используйте gzip. (сжимание сайта )обязательно если это не будет перегружать ваш хостинг

0.93 секунд

Скорость Сайта является важным фактором для ранжирования высоко в результатах поиска Google и Yandex ! Пользователь не готов ждать пока загрузиться ваш медленный сайт . Ресурсы: ознакомьтесь с учебниками разработчика Google для советов о том, как сделать ваш сайт работать быстрее.
Используйте инструмент Google https://developers.google.com/speed/pagespeed/insights/ для выявления и устранения проблем скорости загрузки сайта .

89 / 100

Page Speed

Loggers.ru скорость ПК сайта быстрый. Скорость страницы важна как для поисковых систем, так и для посетителей.

Введите ваше предложение в поле сообщение

Хорошо, заявлен язык сайтаЗаявленный Язык сайта: English

Убедитесь, что ваш объявленный язык совпадает с языком, обнаруженным Google и Yandex кроме того, определите язык Контента в HTML-коде каждой страницы.

Домены (TLD) зарегистрируй сейчас в REG.ru Статус
loggers.com Уже зарегистрирован
loggers.net Уже зарегистрирован
loggers.org Уже зарегистрирован
loggers.biz Доступный
loggers.io Уже зарегистрирован

Зарегистрируйте различные расширения вашего домена, чтобы защитить свой бренд от киберсквоттеров.

Домены (TLD) зарегистрируй сейчас в REG.ru Статус
logers.ru Доступный
poggers.ru Доступный
ooggers.ru Доступный
ioggers.ru Доступный
koggers.ru Доступный

Зарегистрируйте различные опечатки вашего домена, чтобы защитить свой бренд от cybersquatters.

Плохо! Адрес электронной почты был найден простым текстом!

Мы не рекомендуем добавлять на веб-страницы адреса электронной почты с простым текстом и ссылками. Так как вредоносные боты ежесекундно сканируют веб страницы в поисках адресов электронной почты для спама

В связи с чем вас завалят почтовым спамом и вы можете пропустить что то важное! Вместо этого рекомендуется использовать контактную форму.
А лучше используйте свой адрес электронной почты в виде картинки встроенной в текст !

Технологии

IP-адрес сервера Расположение сервера Поставщик услуг
46.229.213.32 Russia TimeWeb Ltd.

IP-адрес вашего сервера мало влияет на SEO. Тем не менее, попробуйте разместить свой сайт на сервере, который географически близок к вашим посетителям. Поисковые системы учитывают геолокацию сервера, а также скорость сервера.

Советы по созданию быстрогружающихся HTML-страниц:

Отлично, ваш сайт имеет несколько CSS-файлов. Плохо, на вашем сайте слишком много файлов JavaScript. Отлично, ваш сайт не использует вложенные таблицы. Плохо, ваш сайт использует встроенные стили.

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

Отлично, Мы обнаруживаем инструмент аналитики, установленный на этом веб-сайте.

Веб-аналитика позволяет измерять активность посетителей на вашем сайте. У вас должен быть установлен хотя бы один инструмент аналитики, но также может быть полезно установить второй, чтобы перепроверить данные
Самые популярные и полезные инструменты аналитики :
https://metrika.yandex.ru/
https://www.google.ru/analytics/
https://www.liveinternet.ru/

W3C не подтвержден

W3C это стандарт, который устанавливает для всех веб-страниц в интернет пространстве

Использование допустимой разметки, не содержащей ошибок, важно, поскольку синтаксические ошибки могут затруднить индексацию страницы поисковыми системами. Запускайте службу проверки W3C при каждом внесении изменений в код веб-сайта

Вы можете воспользоваться бесплатный валидатором W3C
http://validator.w3.org/

Тип вашей веб-страницы HTML 5

Doc type используется, чтобы проинструктировать веб-браузеры об используемом типе документа. Например, в какой версии HTML написана страница. Запись doctype помогает веб-браузерам правильно отображать содержимое.

Настройка фильтрации

Pantheios Нет (1)
Glog Командная строка, ручная, переменные среды окружения
log4cpp Конфигурационный файл (4), ручная
P7 Командная строка, удаленно по сети в режиме реального времени (2) (3), ручная
G3log Нет (5)
Spdlog Ручная
Easylogging Ручная (6)
Boost.Log Конфигурационный файл, ручная
  1. Для организации фильтрации нужно разработать свой FrontEnd
  2. Поддерживается только если данные высылаются по сети, в случае записи в локальный файл сервер не имеет доступа к Verbosity level
  3. В дополнение к глобальному уровню можно устанавливать уровни для каждого модуля.
  4. Иерархические логирование и установка уровней индивидуально для каждого логера
  5. По умолнчанию отключена, включается макросом G3_DYNAMIC_LOGGING, после этого можно в ручном режиме задать уровень на все логеры. Существенно снижает производительность.
  6. Поддержка заявлена производителем, но заставить ее работать не удалось, во время использования сложилось впечатление, что функция находится в стадии разработки или заброшена.

Логгеры температуры и влажности воздуха в серверных помещениях

Компьютеры в процессе работы выделяют тепло, а перегрев негативно сказывается на работе процессоров. В серверном центре недопустимы высокие температуры и показатели влажности, поэтому здесь устанавливают регулирующее климатическое оборудование. Если в системах охлаждения и энергообеспечения произойдет сбой, логгер зарегистрирует рост температурных/влажностных показателей.

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

Во всех этих случаях недопустимо использование бытовых контроллеров, так как их пороговые значения не соответствуют промышленным. Так, в рефрижераторах происходит охлаждение до -50 или -70 градусов, а на электроподстанциях трансформаторы нагреваются до +200 градусов. В быту такие температуры не встречаются. Кроме того, компактные и бюджетные модели не способны считывать информацию одновременно с нескольких независимо расположенных датчиков.

Компания Измеркон из Санкт-Петербурга в своем магазине предлагает купить мобильные автономные регистраторы данных – компактные цифровые, портативные или мультифункциональные, в отдельном кейсе. Такие устройства используются для постоянного аудита и позволяют подготовить информацию для отчетов (цифровой интерфейс позволяет передавать данные на компьютер для обработки). В этом случае фиксация данных ведется непрерывно, а большой объем встроенной памяти позволяет сохранить тысячи измерений. В некоторых моделях предусмотрены и встроенные аварийные сигналы, которые срабатывают, как только показатели температуры и влажности выходят за пределы заданного диапазона. Частоту записи пользователь может настроить автоматически.

Документация и зависимости

Документация Зависимости
Pantheios Полная (API + использование) STLSoft
Glog Рудиментарная, почти отсутствует Google gflags, слабая зависимость (1)
log4cpp Генерируемая (Doxygen) (API только) Boost, слабая зависимость (1)
P7 Полная (API + использование) Нет
G3log Базовая (общие методы использования) Нет
Spdlog Базовая (общие методы использования) Нет, только заголовочный файл (2)
Easylogging Базовая (общие методы использования) Нет, только заголовочный файл (2)
Boost.Log Базовая (общие методы использования) плюс базовое описание некоторых классов и их методов Boost
  1. Слабая зависимость – часть кода зависит от сторонних решений, но не препятствует компиляции, а лишь частично ограничивает функционал.
  2. Только заголовочный файл – библиотека распространяется в виде одного или нескольких заголовочных файлов, которые необходимо включать в каждый исходный файл Вашей программы, в случае Easylogging существенно снижается скорость компиляции. Но из этой ситуации есть выход – компилировать эти проекты в виде библиотеки и подключать уже ее, правда это потребует дополнительного времени на создание проекта.

Анализ ссылок

Мы нашли в общей сложности 47 ссылки, включая как внутренние, так и внешние ссылки вашего сайта

Анкор Тип Следовать
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внутренние ссылки Dofollow
Внешние ссылки Nofollow

Показать больше
Показывай меньше

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

Модуль Logging

Модуль logging в Python — это готовый к использованию, мощный модуль, предназначенный для удовлетворения потребностей как начинающих, так и корпоративных команд. Он используется большинством сторонних библиотек Python, поэтому вы можете интегрировать ваши логи с сообщениями из этих библиотек для создания единого журнала логов в вашего приложении.

Добавить logging в вашу программу на Python так же просто, как написать эту строчку:

import logging

С импортированным модулем logging вы можете использовать то, что называется «logger», для логирования сообщений, которые вы хотите видеть

По умолчанию существует 5 стандартных уровней severity, указывающих на важность событий. У каждого есть соответствующий метод, который можно использовать для логирования событий на выбранном уровне severity

Список уровней в порядке увеличения важности:

  • DEBUG
  • INFO
  • WARNING
  • ERROR
  • CRITICAL

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

import logging

logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

Вывод вышеупомянутой программы будет выглядеть так:

WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message

Вывод показывают уровень важности перед каждым сообщением вместе с root, который является именем, которое модуль logging дает своему логеру по умолчанию. Этот формат, который показывает уровень, имя и сообщение, разделенные двоеточием (:), является форматом вывода по умолчанию, и его можно изменить для включения таких вещей, как отметка времени, номер строки и других деталей

Обратите внимание, что сообщения debug() и info() не были отображены. Это связано с тем, что по умолчанию модуль ведения журнала регистрирует сообщения только с уровнем WARNING или выше

Вы можете изменить это, сконфигурировав модуль logging для регистрации событий всех уровней. Вы также можете определить свои собственные уровни, изменив конфигурации, но, как правило, это не рекомендуется, так как это может привести к путанице с журналами некоторых сторонних библиотек, которые вы можете использовать.

Создание провайдера логгирования

Последнее обновление: 06.11.2019

Стандартная инфраструктура ASP NET Core предоставляет, возможно, не самый удобные способы логгирования — на консоль, в окне Output в Visual Studio.
Однако в то же время ASP.NET Core позволяет полностью определить свою логику ведения лога. Допустим, мы хотим сохранять сообщения в текстовом файле.

Вначале добавим в проект новый класс FileLogger:

using Microsoft.Extensions.Logging;
using System;
using System.IO;

namespace HelloApp
{
    public class FileLogger : ILogger
    {
        private string filePath;
        private static object _lock = new object();
        public FileLogger(string path)
        {
            filePath = path;
        }
        public IDisposable BeginScope<TState>(TState state)
        {
            return null;
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            //return logLevel == LogLevel.Trace;
            return true;
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (formatter != null)
            {
                lock (_lock)
                {
                    File.AppendAllText(filePath, formatter(state, exception) + Environment.NewLine);
                }
            }
        }
    }
}

Класс логгера должен реализовать интерфейс ILogger. Этот интерфейс определяет три метода:

  • : этот метод возвращает объект IDisposable, который представляет некоторую область видимости для логгера. В данном случае нам
    этот метод не важен, поэтому возвращаем значение

  • : возвращает значения true или false, которые указыват, доступен ли логгер для использования. Здесь можно здать различную логику. В частности,
    в этот метод передается объект LogLevel, и мы можем, к примеру, задействовать логгер в зависимости от значения этого объекта. Но в данном случае просто возвращаем
    true, то есть логгер доступен всегда.

  • : этот метод предназначен для выполнения логгирования. Он принимает пять параметров:

    • : уровень детализации текущего сообщения

    • : идентификатор события

    • : некоторый объект состояния, который хранит сообщение

    • : информация об исключении

    • : функция форматирвания, которая с помощью двух предыдущих параметов позволяет получить собственно сообщение для логгирования

    И в данном методе как раз и производится запись в текстовый файл. Путь к этому файлу передается через конструктор

Далее добавим в проект класс FileLoggerProvider:

using Microsoft.Extensions.Logging;

namespace HelloApp
{
    public class FileLoggerProvider : ILoggerProvider
    {
        private string path;
        public FileLoggerProvider(string _path)
        {
            path = _path;
        }
        public ILogger CreateLogger(string categoryName)
        {
            return new FileLogger(path);
        }

        public void Dispose()
        {
        }
    }
}

Этот класс представляет провайдер логгирования. Он должен реализовать интерфейс ILoggerProvider. В этом интерфейсе определны два метода:

  • CreateLogger: создает и возвращает объект логгера. Для создания логгера используется путь к файлу, который передается через конструктор

  • Dispose: управляет освобождение ресурсов. В данном случае пустая реализация

Теперь создадим вспомогательный класс FileLoggerExtensions:

using Microsoft.Extensions.Logging;

namespace HelloApp
{
    public static class FileLoggerExtensions
    {
        public static ILoggerFactory AddFile(this ILoggerFactory factory,
                                        string filePath)
        {
            factory.AddProvider(new FileLoggerProvider(filePath));
            return factory;
        }
    }
}

Этот класс добавляет к объекту ILoggerFactory метод расширения , который будет добавлять наш провайдер логгирования.

Теперь используем провайдер в классе Startup:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.IO;

namespace HelloApp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddFile(Path.Combine(Directory.GetCurrentDirectory(), "logger.txt"));
            var logger = loggerFactory.CreateLogger("FileLogger");

            app.Run(async (context) =>
            {
                logger.LogInformation("Processing request {0}", context.Request.Path);
                await context.Response.WriteAsync("Hello World!");
            });
        }
    }
}

Теперь для логгирования будет использоваться файл logger.txt, который будет создаваться в папке проекта.

НазадВперед

Поддержка юникода

Pantheios Utf-16 (1)(4), Utf-8
Glog Нет
log4cpp Нет
P7 Windows — UTF-16, *nix — UTF-8, UTF-32
G3log Нет
Spdlog Нет
Easylogging Windows Utf-16 (2), Utf-8 (3)
Boost.Log UTF-8 частично (5)
  1. Почти идеально, за исключением того что итоговый лог файл не имеет маркера юникода и кодировку в программе просмотра нужно будет выбирать самому.
  2. Поддержка заявлена, но не реализована, символы юникода в лог файл не попадают.
  3. Макрос START_EASYLOGGINGPP не поддерживает юникод
  4. В одном сообщении нельзя совместить ANSI строку скажем с UTF-16
  5. Поддержка юникода осуществляется с помощью библиотеки Boost.Locale, предоставляется впечатляюще широкая поддержка разных форматов UTF-8/16/32 и прочие национальные локали, к сожалению, заставить работать Boost.Log удалось только с UTF-8 форматом файла и только с использованием функции инициализации синхронного логера «logging::add_file_log», все остальные попытки провалились и символы юникода не достигли файла, возможно при наличии достаточного времени этот функционал можно заставить работать

Обработка сбоев процесса

  • Автоматический, библиотека сама настраивает все векторы и сделает все сама, большим минусом такого решения является скудность перехватываемых сигналов, а так же помехи для приложения, которое возможно хотело бы само обрабатывать падение в целях сохранения crash dump файла или сброса буферов.
  • Ручной – библиотека предоставляет примитивы для перехвата падений и сброса буферов, а приложение уже само решает, когда и как установить перехватчик и что делать в случае падения.
  • Пусть падает, дело житейское
Pantheios Нет
Glog автоматический, только под Linux (1)
log4cpp Нет
P7 ручной и автоматический (2)
G3log автоматический, только под Linux (3)
Spdlog Нет (4)
Easylogging автоматический, только под Linux (5)
Boost.Log Нет (6)
  1. Перехватывается следующие сигналы: SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, SIGTERM.
  2. Перехватывается следующие сигналы: SIGSEGV, SIGILL, SIGFPE, SIGINT, SIGABRT, SIGBUS, SIGTERM, SIGBUS, PureVirtualCall, VectoredException, Newhandler, InvalidParameterHandler, status_access_, exception_array_bounds_exceeded, exception_datatype_misalignment, exception_flt_divide_by_zero, exception_flt_stack_check, exception_illegal_instruction, exception_int_divide_by_zero, exception_noncontinuable_exception, exception_priv_instruction, exception_stack_overflow
  3. Перехватывается следующие сигналы: SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, SIGTERM, Div by zero, illegal printf, out of bounds, access violation, std::future_error
  4. Перехватывается следующие сигналы: SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGINT
  5. Даже для синхронного режима есть риск потери данных в случае сбоя процесса, в случае использования асинхронного режима риск потери данных крайне высок

Использование Handlers

Обработчики используются, когда вы хотите настроить свои собственные logger и предназначены для отправки сообщений в сконфигурированные места назначения мест, такие как стандартный поток вывода или файл или HTTP, или на вашу электронную почту через SMTP.

У созданного вами logger может быть несколько обработчиков, а это значит, что вы можете настроить его на сохранение в файл журнала, а также на отправку по электронной почте.

Подобно logger, вы также можете установить уровень severity в обработчиках. Это полезно, если вы хотите установить несколько обработчиков для одного и того же logger, но хотите иметь разные уровни severity для каждого из них. Например, вы можете захотеть, чтобы журналы с уровнем WARNING и выше регистрировались на консоли, но все с уровнем ERROR и выше также должно быть сохранены в файл. Вот пример кода, который делает это:

# logging_example.py

import logging

# Create a custom logger
logger = logging.getLogger(__name__)

# Create handlers
c_handler = logging.StreamHandler()
f_handler = logging.FileHandler('file.log')
c_handler.setLevel(logging.WARNING)
f_handler.setLevel(logging.ERROR)

# Create formatters and add it to handlers
c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
c_handler.setFormatter(c_format)
f_handler.setFormatter(f_format)

# Add handlers to the logger
logger.addHandler(c_handler)
logger.addHandler(f_handler)

logger.warning('This is a warning')
logger.error('This is an error')
__main__ - WARNING - This is a warning
__main__ - ERROR - This is an error

Здесь logger.warning() создает LogRecord, который содержит всю информацию о событии, и передает ее всем имеющимся обработчикам: c_handler и f_handler.

c_handler является StreamHandler с уровнем WARNING и берет информацию из LogRecord для генерации вывода в указанном формате и выводит его на консоль. f_handler — это FileHandler с уровнем ERROR, и он игнорирует LogRecord, так как его уровень — WARNING.

Когда вызывается logger.error(), c_handler ведет себя точно так же, как и раньше, а f_handler получает LogRecord на уровне ERROR, поэтому он продолжает генерировать вывод точно так же, как c_handler, но вместо вывода на консоль, он записывает сообщение в указанный файл в этом формате:

2018-08-03 16:12:21,723 - __main__ - ERROR - This is an error

Имя logger, соответствующее переменной __name__, записывается как __main__, то есть имя, которое Python присваивает модулю, с которого начинается выполнение. Если этот файл импортируется каким-либо другим модулем, то переменная __name__ будет соответствовать его имени logging_example. Вот как это будет выглядеть:

# run.py

import logging_example
logging_example - WARNING - This is a warning
logging_example - ERROR - This is an error

Итоги

В заключение я хотел бы выделить ключевые моменты:

  1. Иерархическое логирование в БД логирует:
    • время начала и окончания активности
    • exception
    • parent/child связь (вызывающий/вызываемый)
  2. Плюсы такого логирования:
    • единый SQL для удобного анализа времён выполнения, логики
    • информация о запусках приложения хранится в одной таблице, их удобно сравнивать
  3. Недостатки:
    • логирование предполагает наличие boilerplate кода
    • нужно помнить о периодическом архивировании лог таблицы
  4. При реализации в Java необходимо учитывать следующие факторы:
    • появляется дополнительная зависимость от БД. При современном уровне развития DevOps процессов на мой взгляд это небольшая проблема.
    • boilerplate код можно убрать с помощью техник AOP, но надо анализировать последствия (сторонний компилятор, влияние на runtime).
    • ожидается, что время на запись в БД логирования пренебрежимо мало по сравнению с работой приложения. Connection pool, изменение таблицы логирования через первичный ключ, расположение БД на том же хосте, что и приложение — всё это способствует данному утверждению. Однако необходимо убедиться в этом на своём окружении. При необходимости DML операции с таблицей логирования можно делать асинхронно.
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *