2016-11-06 48 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()