Регистрация Python с контекстом - PullRequest
7 голосов
/ 08 июля 2011

У меня есть настройки регистрации в приложении Python, которое входит в файл и MongoDB.Настройка выглядит следующим образом:

[logger_root]
handlers=myHandler,mongoHandler
level=DEBUG
qualname=myapp

[handler_myHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=myFormatter
args=('myapp.log', 'a',20000000,10)

[handler_mongoHandler]
class=myapp.MongoLogger.MongoLogger
level=INFO
args=('log',)

[formatter_myFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

И MongoLogger имеет функцию emit (), например, такую:

def emit(self, record):
    logdata = record.__dict__
    try:
        if(self.data == None):
            self.initDb()
        self.logtable.insert(logdata)
    except:
       self.handleError(record)

Запись в журнал выполняется следующим образом:

 logger.info("Processing account %s..." % account)

Работает достаточно хорошо, но теперь у меня есть дополнительное требование.Я хочу, чтобы он имел некоторый контекст - то есть, чтобы иметь возможность определять пользовательское значение - скажем, имя учетной записи - чтобы каждый журнал, выполненный в процессе обработки учетной записи, имел имя учетной записи как часть record, переданного emit выше итакже доступен для форматера в строке myFormatter.

Возможно ли это сделать с помощью модуля регистрации?Может быть, есть другой, лучший способ сделать то же самое?

Ответы [ 3 ]

12 голосов
/ 08 июля 2011

Вы можете определить функцию внутри кода обработки учетной записи после получения имени учетной записи, например:

# account_name should already be defined
log = lambda msg: logger.info(msg, extra={'account': account_name})

###

log('Processing account...')

Обратите внимание на аргумент ключевого слова extra.Он используется для добавления дополнительного контекста в записи журнала - в данном случае это имя учетной записи.

Вы можете использовать контекст, переданный через extra в форматере:

format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(account)s'

Обратите внимание, что еслиВы настроили форматер таким образом и забыли передать account, вы получите исключение форматирования строки.

4 голосов
/ 10 августа 2017

Ответ Тони просто предоставляет функцию, но с помощью LoggerAdapter мы можем получить регистратор контекста.

class ILoggerAdapter(LoggerAdapter):
    def __init__(self, logger, extra):
        super(ILoggerAdapter, self).__init__(logger, extra)
        self.env = extra

    def process(self, msg, kwargs):
        msg, kwargs = super(ILoggerAdapter, self).process(msg, kwargs)

        result = copy.deepcopy(kwargs)

        default_kwargs_key = ['exc_info', 'stack_info', 'extra']
        custome_key = [k for k in result.keys() if k not in default_kwargs_key]
        result['extra'].update({k: result.pop(k) for k in custome_key})

        return msg, result

тогда просто оберните свой регистратор как

new_logger = ILoggerAdapter(old_logger, extra={'name': 'name'})

# new_logger is just same as old_logger    
# but can be pass to record
new_logger.info(msg='haha', id=100)

def emit(self, record):
    print(record.name)
    print(record.id)
0 голосов
/ 08 июля 2011

Вы можете расширить класс Handling и дать ему некоторый аргумент, содержащий имя учетной записи, хотя я не уверен, как это будет работать с файлом настройки ведения журнала.

В качестве альтернативы, я делал это раньше, добавляя методы-оболочки для вызова методов регистратора.

Итак, я бы определил:

class MyClass:
    account_name = "bob"
    def info(self, message):
        logging.info("%s|%s" % (self.account_name, message))

измените функцию emit для обработки распаковки, а затем вызовите self.info("Info message") вместо logger.info("Info message").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...