|
|
import logging |
|
|
import os |
|
|
import sys |
|
|
import atexit |
|
|
|
|
|
|
|
|
_initialized_loggers = set() |
|
|
|
|
|
|
|
|
DEFAULT_LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO').upper() |
|
|
LOG_TO_FILE = os.getenv('LOG_TO_FILE', 'false').lower() == 'true' |
|
|
|
|
|
def setup_logger(logger_name: str, log_file: str = '', |
|
|
level: int = None) -> None: |
|
|
""" |
|
|
:param logger_name: name to give to logger |
|
|
:param log_file: file to save log to |
|
|
:param level: which base level of importance to set logger to (defaults to LOG_LEVEL env var) |
|
|
:return: *None* |
|
|
""" |
|
|
|
|
|
if logger_name in _initialized_loggers: |
|
|
return |
|
|
|
|
|
log = logging.getLogger(logger_name) |
|
|
|
|
|
|
|
|
if level is None: |
|
|
level = getattr(logging, DEFAULT_LOG_LEVEL, logging.INFO) |
|
|
|
|
|
formatter = logging.Formatter( |
|
|
fmt="%(name)s - %(levelname)s: %(asctime)-15s %(message)s") |
|
|
|
|
|
|
|
|
stream_handler = logging.StreamHandler(sys.stdout) |
|
|
stream_handler.setFormatter(formatter) |
|
|
stream_handler.setLevel(level) |
|
|
|
|
|
log.setLevel(level) |
|
|
if not log.hasHandlers(): |
|
|
log.addHandler(stream_handler) |
|
|
|
|
|
|
|
|
if LOG_TO_FILE: |
|
|
os.makedirs('logs', exist_ok=True) |
|
|
if log_file == '': |
|
|
log_file = f"{logger_name}.log" |
|
|
log_file_path = os.path.join('logs', log_file) |
|
|
file_handler = logging.FileHandler(log_file_path, mode='w') |
|
|
file_handler.setFormatter(formatter) |
|
|
file_handler.setLevel(level) |
|
|
log.addHandler(file_handler) |
|
|
|
|
|
|
|
|
log.propagate = False |
|
|
|
|
|
|
|
|
_initialized_loggers.add(logger_name) |
|
|
|
|
|
|
|
|
atexit.register(_cleanup_logger, logger_name) |
|
|
|
|
|
def _cleanup_logger(logger_name: str) -> None: |
|
|
""" |
|
|
Clean up logger handlers on program exit. |
|
|
|
|
|
:param logger_name: name of the logger to clean up |
|
|
""" |
|
|
log = logging.getLogger(logger_name) |
|
|
handlers = log.handlers[:] |
|
|
for handler in handlers: |
|
|
handler.close() |
|
|
log.removeHandler(handler) |
|
|
|
|
|
|