blob: 91bb3f7a5a0eacae8e5a3d0578d65a56c0ca3a0c [file] [log] [blame]
"""Maintain a global logger instance."""
import logging
from typing import IO, Text
LOG_LEVEL = logging.WARNING
LOG_FORMAT = "%(asctime)s | [%(levelname)s] %(name)s: %(message)s"
LEVELS = [
logging.NOTSET,
logging.DEBUG,
logging.INFO,
logging.WARNING,
logging.ERROR,
logging.CRITICAL,
]
def compute_level(verbose: int, quiet: int) -> int:
"""Compute a log level based on input.
Log level is based on LOG_LEVEL.
:param int verbose:
Number of levels to increase log level.
:param int quiet:
Number of levels to decrease log level.
:returns int:
New log level. Either of NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL.
"""
if verbose < 0 or quiet < 0:
raise ValueError("Input must not be less than 0")
default_index = LEVELS.index(LOG_LEVEL)
index = min(len(LEVELS) - 1, max(0, default_index + quiet - verbose))
return LEVELS[index]
def configure_logger(name: Text, stream: IO[str], verbose: int, quiet: int):
"""Create handler for logging to an IO stream.
:param Text name:
Name of logger, e.g. __package__.
:param IO[str] stream:
Stream to log to, e.g. sys.stderr.
:param int verbose:
Number of levels to increase log level.
:param int quiet:
Number of levels to decrease log level.
"""
log_level = compute_level(verbose, quiet)
handler = logging.StreamHandler(stream)
handler.setFormatter(logging.Formatter(LOG_FORMAT))
handler.setLevel(log_level)
logger = logging.getLogger(name)
logger.setLevel(handler.level)
logger.addHandler(handler)