记录格式化程序记录当前执行的功能

时间:2016-11-06 03:32:39

标签: python logging

在我的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'
        },
    },
    ...
})

1 个答案:

答案 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()