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