2016-11-06 87 views
1

在我的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

您可以通过将信息上下文添加到记录器的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()