[英]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)
方法在Logger
或Handler
上安裝過濾addFilter(filter)
。
例子:
class NoParsingFilter(logging.Filter):
def filter(self, record):
return not record.getMessage().startswith('parsing')
logger.addFilter(NoParsingFilter())
或者類似的東西,無論如何。
不要使用全局。 這是一場等待發生的意外。
您可以為記錄器指定任何對您有意義的以“.”分隔的名稱。
您可以將它們作為層次結構進行控制。 如果您有名為abc
和abd
記錄器,您可以檢查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.