Обработчики логов

В предыдущей статье мы рассказали о логах, и что их можно записывать в файл. На самом деле всё ещё круче: их можно записывать куда угодно, даже в телеграм-ботов. В этой статье мы рассмотрим как это делать.

Вывод в файл

Первое, что стоит попробовать — это вывод логов в файл:

import logging

logging.basicConfig(filename='app.log', filemode='w')
logging.warning('This will get logged to a file')

Этот код запишет warning не в терминал, а в файл app.log. Наверное, вы уже обратили внимание на расширение файла. Да, для ведения логов создают файлы .log.

Ротация логов

Со временем файл начнёт разбухать. А через пару месяцев он может даже скушать всё свободное место на диске. Чтобы такого избежать, можно в явном виде сказать логеру, сколько памяти он может занимать:

import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger("Название логера")
logger.setLevel(logging.INFO)
handler = RotatingFileHandler("app.log", maxBytes=200, backupCount=2)
logger.addHandler(handler)

logger.info("Я новый логер!")

В этом примере кода мы создали свой логер. Логер — это штука, которая записывает логи. У логера уровень логирования INFO, а хэндлерRotatingFileHandler. Хэндлер — это штука, которая распоряжается логами. Она получает готовые логи, и лишь отвечает за то, куда их положить.

Хэндлер RotatingFileHandler складывает логи в файл app.log. Когда логов накапливается больше допустимого размера (200Байт), файл переименовывется в app.log.1. Затем появляется новый файл app.log, в который теперь пишутся логи. Когда и он заполнится, файл app.log.1 переименутеся в app.log.2, а файл app.log в app.log.1.

Файлы app.log.1 и app.log.2 — это бэкапы. Их создают, чтобы логи после переполнения файла не стирались совсем. Без них может случиться так, что вы зайдёте в логи как раз в момент, когда всё стёрлось. Бэкапов у вас будет столько, сколько указано в backupCount.

Когда все бэкапы уже заняты логами, и основной файл app.log — переполнен, сотрётся самый старый бэкап — app.log.2, на его место встанет бэкап чуть новее — app.log.1. Сам же app.log станет бэкапом app.log.1 и появится новый файл для логов — app.log.

Чтобы пользоваться логером, нужно писать логи в него. Обратите внимание на последнюю строчку в примере. Мы пишем не привычное logging.info("..."), а именно logger.info("...").

Свой хэндлер

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

import logging


class MyLogsHandler(logging.Handler):

    def emit(self, record):
        log_entry = self.format(record)
        # тут ваша логика

Если вы не знаете, что такое классы — не пугайтесь, это не обязательно. Просто заполните код в функции emit(self, record), где record — это как раз запись в логах. Причём, именно сам лог, объект, который помнит когда и где лог был сделан. Чтобы получить отформатированный текст лога, используйте log_entry = self.format(record). Здесь хэндлер обрабатывает лог к формату, который вы указали. О форматах было в статье о форматировании логов.

Когда всё готово, создайте логер с вашим хэндлером и пользуйтесь:

import logging

logger = logging.getLogger("Название логера")
logger.setLevel(logging.INFO)
logger.addHandler(MyLogsHandler())

logger.info("Я новый логер!")