Reputation: 30288
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".
Upvotes: 0
Views: 258
Reputation: 74655
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__
.
Upvotes: 1
Reputation: 890
You can use the inspect module in this case.
import inspect as insp
def record_factory(*args, **kwargs):
record = old_factory(*args, **kwargs)
record.session_id = session_id
(filename, line_number,func_name, lines, index) = insp.getframeinfo(insp.currentframe().f_back)
#Do whatever with this values.
return record
The way currentframe()
works is it returns the frame object for the caller’s stack frame. This can be passed into the getframeinfo() method.
Find more details here : inspect Module
Upvotes: 1