簡體   English   中英

使用過濾器記錄

[英]logging with filters

我正在使用 Logging ( import logging ) 來記錄消息。

在 1 個單個模塊中,我在調試級別記錄消息my_logger.debug('msg')

其中一些調試消息來自function_a() ,其他來自function_b() 我希望能夠根據它們來自 a 還是 b 來啟用/禁用日志記錄;

我猜我必須使用 Logging 的過濾機制。

有人可以告訴我下面的代碼需要如何檢測才能完成我想要的嗎?

import logging
logger = logging.getLogger( "module_name" )

def function_a( ... ):
    logger.debug( "a message" )

def function_b( ... ):
    logger.debug( "another message" )

if __name__ == "__main__":
    logging.basicConfig( stream=sys.stderr, level=logging.DEBUG )

    #don't want function_a()'s noise -> ....
    #somehow filter-out function_a's logging
    function_a()

    #don't want function_b()'s noise -> ....
    #somehow filter-out function_b's logging
    function_b()

如果我將這個簡單的例子擴展到更多模塊和每個模塊更多的函數,我會擔心很多記錄器;

我可以將其減少到每個模塊 1 個記錄器嗎? 請注意,日志消息是“結構化的”,即如果記錄它的函數正在執行一些解析工作,它們都包含前綴logger.debug("parsing: xxx") - 我可以用一行代碼關閉嗎? -關閉所有“解析”消息(無論發出消息的模塊/函數如何?)

只需實現logging.Filter的子類: http : //docs.python.org/library/logging.html#filter-objects 它將有一種方法filter(record) ,它檢查日志記錄並返回 True 以記錄它或返回 False 以丟棄它。 然后,您可以通過調用其addFilter(filter)方法在LoggerHandler上安裝過濾addFilter(filter)

例子:

class NoParsingFilter(logging.Filter):
    def filter(self, record):
        return not record.getMessage().startswith('parsing')

logger.addFilter(NoParsingFilter())

或者類似的東西,無論如何。

不要使用全局。 這是一場等待發生的意外。

您可以為記錄器指定任何對您有意義的以“.”分隔的名稱。

您可以將它們作為層次結構進行控制。 如果您有名為abcabd記錄器,您可以檢查ab的日志記錄級別並更改兩個記錄器。

您可以擁有任意數量的記錄器——它們很便宜。

最常見的設計模式是每個模塊一個記錄器。 請參閱命名 Python 記錄器

做這個。

import logging

logger= logging.getLogger( "module_name" )
logger_a = logger.getLogger( "module_name.function_a" )
logger_b = logger.getLogger( "module_name.function_b" )

def function_a( ... ):
    logger_a.debug( "a message" )

def function_b( ... ):
    logger_b.debug( "another message" )

if __name__ == "__main__":
    logging.basicConfig( stream=sys.stderr, level=logging.DEBUG )
    logger_a.setLevel( logging.DEBUG )
    logger_b.setLevel( logging.WARN )

    ... etc ...

我找到了一種在主腳本中使用函數的更簡單的方法:

# rm 2to3 messages
def filter_grammar_messages(record):
    if record.funcName == 'load_grammar':
        return False
    return True

def filter_import_messages(record):
    if record.funcName == 'init' and record.msg.startswith('Importing '):
        return False
    return True

logging.getLogger().addFilter(filter_grammar_messages)  # root
logging.getLogger('PIL.Image').addFilter(filter_import_messages)

我發現了一種更簡單的方法,即如何使用sshtunel模塊過濾以下問題的默認日志記錄配置,抑制 INFO 級別的消息。

帶有前 2 個不需要的記錄的默認報告如下所示:

2020-11-10 21:53:28,114  INFO       paramiko.transport: Connected (version 2.0, client OpenSSH_7.9p1)
2020-11-10 21:53:28,307  INFO       paramiko.transport: Authentication (password) successful!
2020-11-10 21:53:28,441  INFO       |-->QuerySSH: Query execution successful.

記錄器配置更新:

logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s  %(levelname)-10s %(name)s: %(message)s',
            handlers=[
                logging.StreamHandler(),
                logging.FileHandler(self.logging_handler)
            ]
        )

# Filter paramiko.transport debug and info from basic logging configuration
logger_descope = logging.getLogger('paramiko.transport')
logger_descope.setLevel(logging.WARN)

我很滿意的結果是這樣的:

2020-11-10 22:00:48,755  INFO       |-->QuerySSH: Query execution successful.

暫無
暫無

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

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