2011-07-07 32 views
4

我在Python應用程序中的日誌記錄設置,它記錄到文件和MongoDB。該設置是這樣的:像這樣Python記錄與上下文

[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已發出()函數:

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字符串中。

是否有可能與記錄模塊,以做到這一點?有沒有更好的方法可以做到這一點?

回答

7

您可以定義賬務處理代碼中的函數,你得到後的帳戶名,如:

# 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,你會得到一個字符串格式化異常。

+0

+1。這比我的解決方案好得多! – TorelTwiddler

+0

啊哈,錯過了一個 - 額外的似乎正是我需要的,謝謝! – StasM

+1

另外LoggingAdapter可以幫助你完成lambda所做的事情,請看這裏:http://docs.python.org/howto/logging-cookbook.html#context-info – StasM

0

你可以擴展處理類,並給它包含的帳戶名,雖然我不知道如何將與記錄安裝文件的一些工作參數。

另外,我這樣做的方式之前是增加包裝方法來調用記錄器的方法。

所以我會定義:

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

變化發出函數來處理拆包,然後調用self.info("Info message")代替logger.info("Info message")

+0

我使用''logging.getLogger''所以我不得不讓它創建我的課,而不是記錄儀,並重新實現所有日誌記錄方法。我希望更多的東西一般... – StasM

3

託尼的回答只是提供了一個功能,但使用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)