2016-11-06 3 views
1

私のPythonのログ記録では、現在実行中/実行中の関数を記録したいと思います。例えば;Logging Formatterは現在実行中の関数を記録します

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() 
関連する問題