Skip to content

Instantly share code, notes, and snippets.

@WxBDM
Last active September 26, 2022 17:28
Show Gist options
  • Save WxBDM/4fcb05cee1289545818b9a7d25756f0a to your computer and use it in GitHub Desktop.
Save WxBDM/4fcb05cee1289545818b9a7d25756f0a to your computer and use it in GitHub Desktop.
Setting up logging levels using decorators
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