О новой лёгкой библиотеке, позволяющей писать в журнал systemd при помощи logging
Завсегдатаи наверняка заметили, что на сайте уже некоторое время наблюдается затишье.
Всё потому, что идёт подготовка к его переезду на другой сервер, и на более свежую операционную систему.

В более свежей операционной системе на смену upstart пришла systemd, которая и будет управлять процессом нашего приложения (сайта). Помимо прочего systemd предоставляет удобные и достаточно мощные средства для работы с журналами сервисов, которыми нам хотелось бы воспользоваться после переезда.

Вот некоторые из них:
  • Хранение в записях журнала дополнительной информации (контекста);
  • Мощные фильтры для поиска записей (по времени, по сервису, по любым параметрам из контекста);
  • Настраиваемое постоянное или временное (до перезагрузки) хранение журналов;
  • Настраиваемое усечение журналов.

В стандартной поставке Питона, в библиотеке logging имеются обработчики для отсылки сообщений в различные системы. Например, существует SysLogHandler, позволяющий записывать сообщения в системный журнал, однако [пока] нет ничего похожего для интеграции с systemd.

На PyPI можно отыскать библиотеки для Python, являющиеся обвязками над API libsystemd.so, предлагающие интерфейс для работы с журналом и ещё много чем. В комплекте с systemd тоже идёт подобная обвязка.

Однако тащить в зависимости библиотеку, большей частью возможностей которой я пользоваться не планирую, да ещё и собирать её при установке, мне показалось перебором. Недолго думая, я накидал и выпустил вчера сигнальную версию systemd-logging (обвзяка над libsystemd.so выполнена при помощи ctyped).

После установки подключить и сконфигурировать библиотеку в большинстве случае до безобразия просто:

    from systemdlogging.toolbox import init_systemd_logging

init_systemd_logging()

После этого можно продолжать пользоваться logging как и ранее, сообщения при этом будут направлены в журнал systemd:

    import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

logger.debug('Отладочное сообщение')

try:
raise ValueError

except ValueError:
logger.exception('Что-то случилось', stack_info=True)

Без каких бы то ни было дополнительных телодвижений наряду с текстом сообщения будут сохраняться:
  • Данные о месте возникновения записи (имена процесса, нити, файла, модуля, функции, номер строки);
  • Для исключений: трассировка стека и стек вызовов (если указан stack_info=True).

Добавить контекст в сообщение тоже достаточно просто:

    # Добавим поля USER_NAME и SOME (ожидаются заглавные буквы) в сообщение.
logger.info('Это сообщение с дополнительным контекстом', extra={
'context': {
'USER_NAME': 'idlesign',
'SOME': 'значение',
}
})

И теперь мы можем воспользоваться всеми возможностями команды journalctl для навигации по журналу.
Немного дополнительной информации можно почерпнуть из документации (англ.).

Демо, которое можно использовать в качестве systemd сервиса, доступно здесь. Там же в коде даны примеры того, как можно искать записи в журнале, фильтровать по различным данным контекста.

Проект разрабатывается открыто. Желающие могут участвовать на GitHub.

Пишите в журнал в разумных количествах. Может пригодиться.

Категории

Язык

На заметку
Зарегистрированные пользователи могут публиковать свои Статьи.