I have a library in which I am creating the logger as a class attribute
The entry point class accepts handlers and applies adds them to the root logger:
class Parser:
def __init__(self, handlers):
for hdlr in handlers:
logging.root.addHandler(hdlr)
Now this works if my internal classes initialise the logger like this:
class Event(abc.ABC):
def __init__(self):
self._log = logging.getLogger(__name__)
However, this is no use as the logs don't show the class name. So I tried this:
class Event(abc.ABC):
def __init__(self):
self._log = logging.getLogger(self.__class__.__name__)
This would allow me to see the class name in the logs for the subclasses.
Alas, this doesn't work. This answer will not work for me probably, since Event
objects are constructed after the __init__
method of Parser
is finished (and hence the loggers they use), so logging.root.manager.loggerDict
would still be empty.
This doesn't work either
class Parser:
def __init__(self, handlers):
for hdlr in handlers:
logging.root.addHandler(hdlr)
for cls in Event.__subclasses__():
logging.getLogger(cls.__name__).addHandler(handler)
EDIT:
This is my __init__.py
at the package root. I doubt it is any use. But I don't know what else to give, I have already provided all the logging code above.
"""
Attributions:
Logger decorators: https://stackoverflow.com/a/7004565
"""
import functools
import logging
class WrapperFormatter(logging.Formatter):
def format(self, record: logging.LogRecord):
if hasattr(record, "name_override"):
record.funcName = record.name_override
return super().format(record)
logfmt = "[%(levelname)s] %(name)s <%(module)s.%(funcName)s> %(message)s"
logger = logging.getLogger(__name__)
handler = logging.NullHandler()
logger.setLevel(logging.DEBUG)
handler.setLevel(logging.DEBUG)
handler.setFormatter(WrapperFormatter(logfmt))
logger.addHandler(handler)
def called(func):
@functools.wraps(func)
def wrapper(*a, **kw):
log = "called"
if a:
log += f" with {(repr(arg) for arg in a)}"
logger.debug(log, extra={"name_override": func.__name__})
return func(*a, **kw)
return wrapper
I have a feeling that I am doing this the wrong way.