Как стать автором
Обновить

Тонкости работы с логгированием в Python: краткий гайд для разработчиков

Уровень сложностиПростой
Время на прочтение13 мин
Количество просмотров6.2K
Всего голосов 10: ↑10 и ↓0+14
Комментарии11

Комментарии 11

Добавлю из собственного опыта:

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

  • единственное место где должны конфигурироваться ВООБЩЕ все логгеры - это уровень приложения. Пакеты могут(должны?) предоставить хелперные сущности, но финальная конфигурация всегда на стороне приложения. Только оно в полной мере понимает, какие логи оно хочет, где собирать, и куда отправлять. Пакеты без публичного интерфейса логгирования, или завязанные на корневой логгер - трудноотлаживаемые.

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

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

Подскажите. Как предполагается у вас с root handler настраивать отдельные пакеты по уровню логирования?

Например так: что бы у app.access был warn, на весь app и вложенные пакеты был debug, а на root был info

Не совсем понял кейс. Что подразумевается под "отдельные/вложенные пакеты"?
Если у нас есть логгер app и дочерние от него логгеры (для вложенных модулей?), включая дочерний от app логгер app.access, то уровни присвоятся соответственно - на app будет debug, на app.access будет warning, а на root будет info. Что в итоге запишется в журнал, а что будет отброшено, зависит от того, как вы разместите хендлеры по этим логгерам. Например, если хендлеры будут только в root logger, то debug сообщения от app и дочерних логгеров никуда не запишутся (от app.access они не дойдут до рутового логгера изначально, потому что у самого логгера app.access выставлен уровень WARN)

Давайте на примере. Сейчас приходиться делать что то типа такого для настройки уровней лоигрования вложенных модулей. Еще и везде propagate ставить что бы не дублировались сбщ.

{    
    'loggers': {
        'app': {
            'handlers': ['simple'],
            'level': 'DEBUG',
            'propagate': False
        },
        'app.access': {
            'handlers': ['simple'],
            'level': 'WARN',
            'propagate': False
        },
    },
    'root': {
        'handlers': ['simple'],
        'level': 'INFO',
    }
}

Но у вас я нигде не видел такого в примерах. Просто root handler с одним level и все. Неужели вам этого достаточно?

А точно нужно к каждому логгеру (app, app.access и root) прикручивать один и тот же хендлер? Почему бы не оставить его в каком-то из логгеров, который является для приложения корневым и тогда сообщения дублироваться не будут. Сообщение будет просто проходить весь путь до корневого логгера и фильтроваться при необходимости, а затем в корневом будет записано как и куда надо.

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

А что на счет асинхронного логирования?

Что конкретно вы имеете ввиду?

Хочу написать await logger.info(...)

Предложенный в статье QueueHandler фактически это и делает.

А вы знаете чем asyncio.Queue отличается от queue.Queue ?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории