I wrote a submodule where I define logging there since I mainly use my submodule to reuse code in my different rest api projects. How can I set up my custom logging record so that logging knows which code (main.py
or sub.py
) called the logging? I tried using __file__
, but then it would always say "sub.py".
My submodule:
# sub.py
import logging
from secrets import token_urlsafe
# https://stackoverflow.com/a/57820456/1150923
def record_factory(*args, **kwargs):
record = old_factory(*args, **kwargs)
record.session_id = session_id
# What do I do here?
# This doesn't work:
record.src = __file__
return record
session_id = token_urlsafe(8)
logger = logging.getLogger(__name__)
old_factory = logging.getLogRecordFactory()
logging.setLogRecordFactory(record_factory)
# Always prepend session_id and src to logs
format = logging.Formatter("%(asctime)s %(session_id) %(src) %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
handler = logging.StreamHandler()
handler.setFormatter(format)
logger.addHandler(handler)
logger.info("Hello!") # Should also print out "sub.py".
My main script:
# main.py
import logging
import sub
logger = logging.getLogger("sub")
logger.info("Hi!") # Should also print out "main.py".
Logging provides an attribute for the module name, the same value as __file__
, under the name pathname
.
Replace %(src)s
with %(pathname)s
.
The way the Logger
does it is via stack inspection in the Logger.findCaller
method. It walks up the stack until it finds a frame that isn't in the logging module. And then extracts that frame's filename, lineno, and function name.
See Is module __file__ attribute absolute or relative? for the issue with __name__
.