Call Stack available to Logging Format
So, I have a method that returns a simple string of the call-stack.
def call_stack():
if "inspect" not in globals().keys():
import inspect
stack = [frame[3] for frame in inspect.stack() if frame[3] not in [inspect.stack()[0][3],"<module>"]]
s = ""
for method in stack:
if len(s) > 0:
s += "."
s += method
return s
def modify_logger(logger):
logger.args["call_stack"] = call_stack()
Is it possible to create this behavior?
import logging
logging.basicConfig(level=logging.DEBUG, format="%(call_stack)s 开发者_高级运维-- %(levelname)s: %(message)s")
def bar():
logging.debug("test")
def foo():
bar()
def monkey():
foo()
# modify root logger.
modify_logger(logging.getLogger())
# write to the log.
monkey()
Which results in the following entry:
monkey.foo.bar -- DEBUG: test
Perhaps the easiest way is just to define a custom debug
function:
import logging
def call_stack():
if "inspect" not in globals().keys():
import inspect
stack = [frame[3] for frame in inspect.stack()
if frame[3] not in [inspect.stack()[0][3],"<module>"]]
s='.'.join(reversed(stack))
return s
def debug(message):
logging.debug('{s} -- DEBUG: {m}'.format(
s=call_stack()[:-len('debug.')],m=message))
logging.basicConfig(level=logging.DEBUG, format="%(message)s")
def bar():
debug("test")
def foo():
bar()
def monkey():
foo()
monkey()
yields
monkey.foo.bar -- DEBUG: test
After having researched this pattern quite a bit yesterday, I realized that what I wanted wasn't reasonable for the Python language. Its an interpreted language, after all, which means that there is always a file that exists on a known path and a line number which can be referenced. It would make sense, in a compiled language like C#, Java, C, or C++ because you have namespaces, objects, and methods without the benefit of having a file/path and line number.
Moral of the story
When people tell you that what you're asking for doesn't make sense, don't just write them off. Take a few moments and scrutinize your original request along with your perspective before vigorously pursuing an answer to a question that might not make sense in your specific use-case or context.
I tried your solution mixed with another, it gave me the results I was looking for.
import logging
DEBUG = True
TRACE = True
#-----------------------------------------------------------------------------
# TRACE BACK
#-----------------------------------------------------------------------------
class ContextFilter(logging.Filter):
def filter(self, record):
import traceback
if "inspect" not in globals().keys():
import inspect
stack = [frame[3] for frame in inspect.stack()
if frame[3] not in [inspect.stack()[0][3],"<module>"]]
record.stack ='.'.join(reversed(stack))
return True
#----------------------------------------------------------------------- ---------
# LOGGER
#--------------------------------------------------------------------------------
logger = logging.getLogger()
if TRACE:
logger.addFilter(ContextFilter())
if DEBUG:
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(stack)s\n{%(pathname)s:%(lineno)d} - %(asctime)s - %(levelname)s - %(message)s')
fh = logging.FileHandler('log_filename.txt')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
logger.addHandler(fh)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
logger.addHandler(ch)
else:
logger.setLevel(logging.NOTSET)
print 'NOT IN DEBUG MODE: Logging.NOTSET'
精彩评论