Source code for bag.log

"""Easily set up logging."""

import os
import logging
from logging.handlers import (
    RotatingFileHandler,
    TimedRotatingFileHandler,
    WatchedFileHandler,
)

FORMAT = "%(asctime)s %(levelname)s %(message)s"


[docs]def setup_log( name=None, path="logs", rotating=True, backups=3, file_mode="a", disk_level=logging.DEBUG, screen_level=logging.INFO, encoding="utf-8", ): """This logs to screen if ``screen_level`` is not None, and logs to disk if ``disk_level`` is not None. If you do not pass a log ``name``, the root log is configured and returned. If ``rotating`` is True, a RotatingFileHandler is configured on the directory passed as ``path``. If ``rotating`` is False, a single log file will be created at ``path``. Its ``file_mode`` defaults to `a` (append), but you can set it to `w`. """ # If strings are passed in as levels, "decode" them first levels = dict( debug=logging.DEBUG, # 10 info=logging.INFO, # 20 warn=logging.WARN, warning=logging.WARNING, # 30 error=logging.ERROR, # 40 critical=logging.CRITICAL, fatal=logging.FATAL, # 50 ) if isinstance(disk_level, str): disk_level = levels[disk_level.lower()] if isinstance(screen_level, str): screen_level = levels[screen_level.lower()] # Set up logging log = logging.getLogger(name) if screen_level: h1 = logging.StreamHandler() h1.setLevel(screen_level) log.addHandler(h1) if disk_level: if rotating: try: os.mkdir(path) except OSError: pass h2 = RotatingFileHandler( os.path.join(path, name or "root" + ".log.txt"), encoding=encoding, maxBytes=2 ** 22, backupCount=backups, ) else: h2 = WatchedFileHandler(path, mode=file_mode, encoding=encoding) h2.setLevel(disk_level) log.setLevel(disk_level) log.addHandler(h2) return log
[docs]def setup_rotating_logger( logger=None, backups=4, size=250000000, level=logging.DEBUG, encoding="utf-8", format=FORMAT, directory=".", ): """You may pass either a name or an existing logger as the first argument. This attaches a RotatingFileHandler to the specified logger. Returns the logger object. """ if isinstance(logger, str): filename = ".".join((logger, encoding, "log")) logger = logging.getLogger(logger) else: filename = ".".join((logger.name, encoding, "log")) hr = RotatingFileHandler( os.path.join(directory, filename), maxBytes=size, backupCount=backups, encoding=encoding, ) if format: hr.setFormatter(logging.Formatter(format)) logger.addHandler(hr) logger.setLevel(level) return logger
[docs]def setup_timed_rotating_logger( logger=None, level=logging.DEBUG, backups=14, when="D", interval=1, utc=True, delay=False, encoding="utf-8", format=FORMAT, directory=".", ): """You may pass either a name or an existing logger as the first argument. This attaches a TimedRotatingFileHandler to the specified logger. Returns the logger object. """ if isinstance(logger, str): filename = ".".join((logger, encoding, "log")) logger = logging.getLogger(logger) else: filename = ".".join((logger.name, encoding, "log")) hr = TimedRotatingFileHandler( os.path.join(directory, filename), utc=utc, encoding=encoding, when=when, interval=interval, backupCount=backups, delay=delay, ) if format: hr.setFormatter(logging.Formatter(format)) logger.addHandler(hr) logger.setLevel(level) return logger
[docs]def setup_watched_file_handler( logger=None, level=logging.DEBUG, format=FORMAT, encoding="utf-8", delay=False, directory=".", ): """You may pass either a name or an existing logger as the first argument. This attaches a WatchedFileHandler to the specified logger. Returns the logger object. The WatchedFileHandler detects when the log file is moved, so it is compatible with the logrotate daemon. """ if isinstance(logger, str): filename = ".".join((logger, encoding, "log")) logger = logging.getLogger(logger) else: filename = ".".join((logger.name, encoding, "log")) hr = WatchedFileHandler( os.path.join(directory, filename), delay=delay, encoding=encoding ) if format: hr.setFormatter(logging.Formatter(format)) logger.addHandler(hr) logger.setLevel(level) return logger