簡體   English   中英

Python 中的多行日志記錄

[英]Multi-line logging in Python

我正在使用 Python 3.3.5 和日志記錄模塊將信息記錄到本地文件(來自不同線程)。 在某些情況下,我想輸出一些附加信息,但不知道該信息究竟是什么(例如,它可能是一行文本或一個字典)。

我想做的是在寫入日志記錄后將此附加信息添加到我的日志文件中。 此外,僅當日志級別為錯誤(或更高)時才需要附加信息。

理想情況下,它看起來像:

2014-04-08 12:24:01 - INFO     - CPU load not exceeded
2014-04-08 12:24:26 - INFO     - Service is running
2014-04-08 12:24:34 - ERROR    - Could not find any active server processes
Additional information, might be several lines.
Dict structured information would be written as follows:
key1=value1
key2=value2
2014-04-08 12:25:16 - INFO     - Database is responding

由於沒有編寫自定義日志格式化程序,我找不到太多符合我要求的內容。 我已經閱讀了有關過濾器和上下文的內容,但這似乎不是一個很好的匹配。

或者,我可以只使用標准 I/O 寫入文件,但大多數功能已經存在於 Logging 模塊中,而且它是線程安全的。

任何投入將不勝感激。 如果確實需要自定義日志格式化程序,那么任何關於從哪里開始的指針都會很棒。

請記住,許多人認為多行日志消息是一種不好的做法(可以理解,因為如果您有像 DataDog 或 Splunk 這樣非常准備處理單行日志的日志處理器,多行日志將很難parse),您可以使用extra參數並使用自定義格式化程序將內容附加到將要顯示的消息中(查看日志包文檔中 'extra' 的用法)。

import logging

class CustomFilter(logging.Filter):
    def filter(self, record):
        if hasattr(record, 'dct') and len(record.dct) > 0:
            for k, v in record.dct.iteritems():
                record.msg = record.msg + '\n\t' + k + ': ' + v
        return super(CustomFilter, self).filter(record)
        
if __name__ == "__main__":
    logging.getLogger().setLevel(logging.DEBUG)
    extra_logger = logging.getLogger('extra_logger')
    extra_logger.setLevel(logging.INFO)
    extra_logger.addFilter(CustomFilter())
    logging.debug("Nothing special here... Keep walking")
    extra_logger.info("This shows extra",
                      extra={'dct': {"foo": "bar", "baz": "loren"}})
    extra_logger.debug("You shouldn't be seeing this in the output")
    extra_logger.setLevel(logging.DEBUG)
    extra_logger.debug("Now you should be seeing it!")
    

該代碼輸出:

DEBUG:root:Nothing special here... Keep walking
INFO:extra_logger:This shows extra
        foo: bar
        baz: loren
DEBUG:extra_logger:Now you should be seeing it!

我仍然建議在您的自定義過濾器中調用superfilter函數,主要是因為這是決定是否顯示消息的函數(例如,如果您的記錄器級別設置為logging.INFO ,並且您使用extra_logger.debug記錄某些extra_logger.debug ,不應看到該消息,如上例所示)

我只是在輸出文本中添加了\\n符號。

似乎我在定義 LogFormatter 字符串時犯了一個小錯誤:由於不小心轉義換行符,我錯誤地認為不可能將多行輸出寫入日志文件。

為@Barafu 指出這一點干杯(這就是我為他分配正確答案的原因)。

這是示例代碼:

import logging
lf = logging.Formatter('%(levelname)-8s - %(message)s\n%(detail)s')
lh = logging.FileHandler(filename=r'c:\temp\test.log')
lh.setFormatter(lf)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
log.addHandler(lh)
log.debug('test', extra={'detail': 'This is a multi-line\ncomment to test the formatter'})

結果輸出如下所示:

DEBUG    - test
This is a multi-line
comment to test the formatter

警告:

如果沒有要記錄的詳細信息,並且您傳遞了一個空字符串,則記錄器仍將輸出換行符。 因此,剩下的問題是:我們如何才能使這個有條件?

一種方法是實際登錄的信息之前更新的日志記錄格式,如所描述這里

我在較小的應用程序中使用了一個簡單的分線器:

for line in logmessage.splitlines():
            writemessage = logtime + " - " + line + "\n"
            logging.info(str(writemessage))

請注意,這不是線程安全的,可能只應在日志卷日志記錄應用程序中使用。

但是,您可以輸出以記錄幾乎所有內容,因為它會保留您的格式。 例如,我使用它來輸出使用以下格式的 JSON API 響應: json.dumps(parsed, indent=4, sort_keys=True)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM