在我的python日志中,我想记录当前正在执行/运行的函数。例如;
class Foo:
def bar(self):
logging.info("I'm alive") # Writes to log: '[INFO]: Foo::bar(), I'm alive'
是否可以配置我的记录器来执行此操作?即,创建一个格式化程序来找到它?
logging.config.dictConfig({
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '[%(levelname)s] %(FUNCTION_NAME)s: %(message)s'
},
},
...
})
答案 0 :(得分:0)
您可以通过将信息上下文添加到记录器的record
来实现。为此,您需要定义自己的ContextFilter
类,并将其实例添加到记录器中。请注意,为了获取类名,我们依赖于调用self
类的实例的约定,而不是将其用作其他函数的参数(它基于此SO问题how-to-retrieve-class-information-from-a-frame-object )。另请注意,此解决方法无法确定internalFunc
的类,因为它没有self
参数。请参阅下面的代码。
import inspect
import logging
def get_class_from_frame(fr):
args, _, _, value_dict = inspect.getargvalues(fr)
if len(args) and args[0] == 'self':
instance = value_dict.get('self', None)
if instance:
return getattr(instance, '__class__', None)
return 'NOCLASS'
class ContextFilter(logging.Filter):
"""
This is a filter which injects contextual information into the log.
"""
def filter(self, record):
#we are adding the function field to the logger record
mystack = inspect.stack()[5]
record.function = '%s::%s'%(get_class_from_frame(mystack[0]), mystack[3])
return True
def buildLogger():
logger = logging.getLogger("root")
#now we use the function field in the format
myFormat = '[%(levelname)s] %(function)s: "%(message)s"'
formatter = logging.Formatter(myFormat)
# add an instance of ContextFilter to the logger
myFilter = ContextFilter()
logger.addFilter(myFilter)
ch = logging.StreamHandler()
ch.setFormatter(formatter)
logger.addHandler(ch)
logger.propagate = False
return logger
# Some testing
def myStandaloneFunction():
logger.warning('this is logged from myStandaloneFunction')
class A():
def afunc(self):
def internalFunc():
logger.warning('this is logged from inside internalFunc call')
logger.warning('this is logged from inside a afunc call')
internalFunc()
logger = buildLogger()
logger.warning('this is logged from module level')
myStandaloneFunction()
a = A()
a.afunc()