make 'path' and 'keywords' available in logging messages

Wrap all loggers used by job, extractor, downloader, and postprocessor
objects into a (custom) LoggerAdapter that provides access to the
underlying job, extractor, pathfmt, and kwdict objects and their
properties.

__init__() signatures for all downloader and postprocessor classes have
been changed to take the current Job object as their first argument,
instead of the current extractor or pathfmt.

(#574, #575)
This commit is contained in:
Mike Fährmann
2020-05-18 01:35:53 +02:00
parent 846d3a2466
commit ece73b5b2a
17 changed files with 149 additions and 97 deletions

View File

@@ -22,19 +22,68 @@ LOG_LEVEL = logging.INFO
class Logger(logging.Logger):
"""Custom logger that includes extractor and job info in log records"""
extractor = util.NONE
job = util.NONE
"""Custom logger that includes extra info in log records"""
def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
func=None, extra=None, sinfo=None,
factory=logging._logRecordFactory):
rv = factory(name, level, fn, lno, msg, args, exc_info, func, sinfo)
rv.extractor = self.extractor
rv.job = self.job
if extra:
rv.__dict__.update(extra)
return rv
class LoggerAdapter():
"""Trimmed-down version of logging.LoggingAdapter"""
__slots__ = ("logger", "extra")
def __init__(self, logger, extra):
self.logger = logger
self.extra = extra
def debug(self, msg, *args, **kwargs):
if self.logger.isEnabledFor(logging.DEBUG):
kwargs["extra"] = self.extra
self.logger._log(logging.DEBUG, msg, args, **kwargs)
def info(self, msg, *args, **kwargs):
if self.logger.isEnabledFor(logging.INFO):
kwargs["extra"] = self.extra
self.logger._log(logging.INFO, msg, args, **kwargs)
def warning(self, msg, *args, **kwargs):
if self.logger.isEnabledFor(logging.WARNING):
kwargs["extra"] = self.extra
self.logger._log(logging.WARNING, msg, args, **kwargs)
def error(self, msg, *args, **kwargs):
if self.logger.isEnabledFor(logging.ERROR):
kwargs["extra"] = self.extra
self.logger._log(logging.ERROR, msg, args, **kwargs)
class PathfmtProxy():
__slots__ = ("job",)
def __init__(self, job):
self.job = job
def __getattribute__(self, name):
pathfmt = object.__getattribute__(self, "job").pathfmt
return pathfmt.__dict__.get(name) if pathfmt else None
class KwdictProxy():
__slots__ = ("job",)
def __init__(self, job):
self.job = job
def __getattribute__(self, name):
pathfmt = object.__getattribute__(self, "job").pathfmt
return pathfmt.kwdict.get(name) if pathfmt else None
class Formatter(logging.Formatter):
"""Custom formatter that supports different formats per loglevel"""