Last active
September 26, 2022 17:28
-
-
Save WxBDM/4fcb05cee1289545818b9a7d25756f0a to your computer and use it in GitHub Desktop.
Setting up logging levels using decorators
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
from logging.handlers import TimedRotatingFileHandler | |
import typing as t | |
LOG_FORMAT = '%(levelname)s %(asctime)s %(message)s' | |
LOG_FORMATTER = logging.Formatter(LOG_FORMAT) | |
LOG_LEVELS = {'not set' : logging.NOTSET, | |
'debug' : logging.DEBUG, | |
'info' : logging.INFO, | |
'warning' : logging.WARNING, | |
'error' : logging.ERROR, | |
'critical' : logging.CRITICAL} | |
def set_logfile_level(level: str) -> None: | |
"""Define the log level in which is written to the log file on disk. | |
By default, this level is set to `info`. | |
Options: | |
- `debug` | |
- `info` | |
- `warning` | |
- `error` | |
- `critical` | |
""" | |
def file_level_outer(func): | |
def wrapper(*args, **kwargs): | |
return func({'logfile' : LOG_LEVELS[level]}, *args) | |
return wrapper | |
return file_level_outer | |
def set_console_level(level: str) -> None: | |
"""Define the log level in which is written to the console. | |
By default, this level is set to `error`. | |
Options: | |
- `debug` | |
- `info` | |
- `warning` | |
- `error` | |
- `critical` | |
""" | |
def console_outter(func): | |
def wrapper(*args, **kwargs): | |
return func({'console' : LOG_LEVELS[level]}, *args) | |
return wrapper | |
return console_outter | |
def _setup_root_logger(handlers: t.List[t.Union[TimedRotatingFileHandler, logging.StreamHandler]]): | |
"""Sets up the root logging, which is called when `setup_logging` is complete. | |
""" | |
root = logging.getLogger() | |
min_level = min([handler.level for handler in handlers]) | |
root.setLevel(min_level) | |
for handler in handlers: | |
root.addHandler(handler) | |
def setup_module_log(name: str, *args) -> None: | |
"""Sets up the basic logging for a specific module, AKA a child logger. The root | |
logger will always be the minimum for these logs. | |
This function should only be called once for every log on disk. By default, | |
the log level is `info`. | |
Sample driver code on how to go about setting up logging: | |
``` | |
import setup_module_log, set_console_level, set_logfile_level | |
@set_logfile_level('warning') | |
@set_console_level('info') | |
def setup_logging(*args): | |
name = 'myLogger.log' | |
setup_module_log(name, *args) | |
``` | |
""" | |
# filter out only the arguments that are dictionaries. These come from the | |
# above decorators. These are default values. | |
log_level_d = {'logfile' : LOG_LEVELS['info'], | |
'console' : LOG_LEVELS['error']} | |
for arg in args: | |
if isinstance(arg, dict): | |
log_level_d = {key : value for key, value in arg.items()} | |
# The name of the module, set the baseline to none. | |
logger = logging.getLogger(name) | |
logger.setLevel(logging.NOTSET) | |
# the stdout to a log file, this instance is a timed rotating file handler. | |
fh = TimedRotatingFileHandler( | |
filename = name, | |
when = 'midnight', | |
utc = True, | |
) | |
fh.setFormatter(LOG_FORMATTER) # set the format for it. | |
fh.setLevel(log_level_d['logfile']) # set the level. | |
# Set the stdout for console. | |
ch = logging.StreamHandler() | |
ch.setLevel(log_level_d['console']) # set level | |
ch.setFormatter(LOG_FORMATTER) # set format | |
# If there are any additional handlers (see: | |
# https://docs.python.org/3/howto/logging.html#useful-handlers | |
# for more), add them below. You'll also want to create the | |
# associated decorator for this, just copy/paste and replace key value. | |
_setup_root_logger([fh, ch]) # really just setting minimum level. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment