Как заставить TimeRotatingHandler сохранять все уровни логов, а не только DEBUG - PullRequest
0 голосов
/ 05 мая 2020

ПРОБЛЕМА: при записи в файл регистрируются только сообщения DEBUG.

У меня есть обработчики для логирования. Один для стандартного вывода, а другой для файла. Уровень обработчика stdout установлен на INFO, тогда как уровень логирования обработчиков файлов установлен на DEBUG. Обработчик потока работает так, как ожидалось, т.е. все журналы с уровнем INFO и выше отправляются на stdout

Однако для обработчика файлов я могу видеть только сообщения DEBUG. Я ожидал, что все журналы, а не только DEBUG, будут в файле

Вот мой модуль ведения журнала

from datetime import datetime
import logging
from logging.handlers import TimedRotatingFileHandler
import os
import sys


LOGLEVELS = ["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL", "FATAL"]

FORMAT_STDOUT = '%(filename)s %(asctime)s - %(levelname)s - %(message)s'
FORMAT_FILE = '%(asctime)s - %(levelname)s - %(message)s'

LOG_ROOT = os.path.expanduser("~/.log/")

existing_loggers = {}


def get_logger(filename, loglevel=None, log_file=None):
    log_handler_name = filename.split('.')[0]
    if log_file:
        log_handler_name = log_handler_name + "_" + log_file

    if log_handler_name in existing_loggers:
        return existing_loggers[log_handler_name]

    formatter = logging.Formatter(
        fmt=FORMAT_STDOUT, datefmt='%d/%m/%Y %H:%M:%S')
    if not loglevel:
        loglevel = os.environ.get("LOG_LEVEL", "INFO")
        if loglevel not in LOGLEVELS:
            logging.warning("env var LOGGING set incorrectly. "
                            f"Excpected values {LOGLEVELS}. Setting to default INFO level")
            loglevel = "INFO"
    else:
        assert loglevel in LOGLEVELS
    logger = logging.getLogger(log_handler_name)
    logger.addFilter(ContextFilter(log_handler_name))
    logger.propagate = False

    sh = logging.StreamHandler(sys.stdout)
    sh.setLevel(getattr(logging, loglevel))
    sh.setFormatter(formatter)
    logger.addHandler(sh)

    if log_file:
        log_file = get_logfile(filename, log_file)
        fh = TimedRotatingFileHandler(log_file, when='H', interval=6)
        fh.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            fmt=FORMAT_FILE, datefmt='%d/%m/%Y %H:%M:%S')
        fh.setFormatter(formatter)
        logger.addHandler(fh)
    existing_loggers[log_handler_name] = logger
    return logger


def get_logfile(filename, log_file):
    filename = filename.split('.')[0]
    dt_obj = datetime.now()
    today = dt_obj.strftime("%Y-%m-%d")
    log_file = f'{log_file}_{filename}'
    log_dir = os.path.join(LOG_ROOT, today)
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    log_file = os.path.join(log_dir, log_file)
    return log_file


class ContextFilter(logging.Filter):
    """
    This is a filter which injects contextual information into the log.
    """

    def __init__(self, filename):
        super().__init__()
        self._pyfilename = filename

    def filter(self, record):
        record.filename = self._pyfilename
        return True
...