5. Что происходит внутри
С чем важно вазимодействовать:
– Logger – кто, что и ли будет писать
– Handler – как, куда и будет ли писать
6. Что происходит внутри
● Logger, фильтруя
событие, создает
LogRecord
● Передает его своим
handler'ам, которые
фильтруя выполняют
emit
● Просит то же самое
сделать своего
родителя
7. Иерархия и менеджер
● Логгеры наследуют правила в иерархии,
наверху - RootLogger
● Правила действуют во всей программе* -
следит logging.manager, у которого есть
loggerDict
8. Что делает logging.info
● Менеджер видит, что в loggerDict нет
корневого логгера и создает его
● RootLogger создается с:
– StreamHandler(sys.stderr)
– logLevel = WARNING
9. Чем грозит
● Это работает
● Во всей программе один логгер, меньше
опций настройки
● Если импортировать код в другую
программу, то она испортит корневой логгер
10. logging.getLogger
● logging.getLogger() - получить RootLogger
● logging.getLogger(__name__) - получить
логгер в иерархии
● logging.getLogger(__package__) - тоже
вариант, но меньше логгеров
11. Как работает getLogger
● В программе:
logger = getLogger('myproject.utils')
logger.info('Message')
● Менеджер модуля обращается к своему
loggerDict['myproject.utils'] и выполняет
функции Logger
● И для loggerDict['myproject'] ...
● И для loggerDict['root'] ...
12. Происходит по умолчанию
● Правила для RootLogger
● Если в словаре нет 'myproject', то он
добавляется как logging.PlaceHolder, чтобы
держать иерархию
Может быть не нужно, а может и запутать
13. Использование getLogger
● Практика большинства модулей
● Гибкая, но не кропотливая настройка
логгеров и хэндлеров
● Иерархия будет становиться сложнее
● Имея отдельный логгер нелегко узнать, куда
и как он пишет
14. Настройка логирования
Логика логирования может быть сложной:
– Логика зависящая от среды (dev, prod)
– Централизованное хранение логов
– Разные режимы работы программы (демон,
подпроцессы)
Каждый, кому нужны логи – потенциальный
источник усложнения логики
15. Настройка логгеров
● Чем раньше, тем лучше
– Если logger – глобальная переменная модулей
– В __init__ программы
● logging.dictConfig – указать все возможные
варианты, потом фильтровать
● Добавить свой метод, потом обновлять
логику через logger.manager
16. Событие в логировании
● Обычно запись – это строка, в которую
добавили значения нужных переменных
– Потом нужно grep'ать эти строчки
– По большим логам нужно grep'ать долго
17. Событие сейчас
● LogRecord – потенциально более удобный
объект, чем строка
● JSON – более универсальная и гибкая
структура для хранения информации
18. Добавление в LogRecord
● Добавить что-то важное для данного
события:
– Логин пользователя, который открыл
веб-страницу
– Версия кода
19. Добавление в LogRecord
● Передать через extra:
– logger.info(“Sent response”, extra={'client': 'example'})
– не подходит для систематического использования
● logging.LoggerAdapter
– Заменяет Logger в словаре loggerDict и ведет себя так же
– Не потомок Logger, поэтому настроить логику хэндлеров
напрямую нельзя
22. Централизация логирования
● logging → logstash
● Logstash – умеет отправлять в 20+ мест, в
том числе PostgreSQL, Twitter
● Уже есть готовые хэндлеры:
– TCP с шифрованием
– UDP