[英]logging with filters
I'm using Logging ( import logging
) to log messages.我正在使用 Logging (
import logging
) 来记录消息。
Within 1 single module, I am logging messages at the debug level my_logger.debug('msg')
;在 1 个单个模块中,我在调试级别记录消息
my_logger.debug('msg')
;
Some of these debug messages come from function_a()
and others from function_b()
;其中一些调试消息来自
function_a()
,其他来自function_b()
; I'd like to be able to enable/disable logging based on whether they come from a or from b;我希望能够根据它们来自 a 还是 b 来启用/禁用日志记录;
I'm guessing that I have to use Logging's filtering mechanism.我猜我必须使用 Logging 的过滤机制。
Can someone show me how the code below would need to be instrumented to do what I want?有人可以告诉我下面的代码需要如何检测才能完成我想要的吗?
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()
If I scaled this simple example to more modules and more funcs per module, I'd be concerned about lots of loggers;如果我将这个简单的例子扩展到更多模块和每个模块更多的函数,我会担心很多记录器;
Can I keep it down to 1 logger per module?我可以将其减少到每个模块 1 个记录器吗? Note that the log messages are "structured", ie if the function(s) logging it are doing some parsing work, they all contain a prefix
logger.debug("parsing: xxx")
- can I somehow with a single line just shut-off all "parsing" messages (regardless of the module/function emitting the message?)请注意,日志消息是“结构化的”,即如果记录它的函数正在执行一些解析工作,它们都包含前缀
logger.debug("parsing: xxx")
- 我可以用一行代码关闭吗? -关闭所有“解析”消息(无论发出消息的模块/函数如何?)
Just implement a subclass of logging.Filter
: http://docs.python.org/library/logging.html#filter-objects .只需实现
logging.Filter
的子类: http : //docs.python.org/library/logging.html#filter-objects 。 It will have one method, filter(record)
, that examines the log record and returns True to log it or False to discard it.它将有一种方法
filter(record)
,它检查日志记录并返回 True 以记录它或返回 False 以丢弃它。 Then you can install the filter on either a Logger
or a Handler
by calling its addFilter(filter)
method.然后,您可以通过调用其
addFilter(filter)
方法在Logger
或Handler
上安装过滤addFilter(filter)
。
Example:例子:
class NoParsingFilter(logging.Filter):
def filter(self, record):
return not record.getMessage().startswith('parsing')
logger.addFilter(NoParsingFilter())
Or something like that, anyway.或者类似的东西,无论如何。
Do not use global.不要使用全局。 It's an accident waiting to happen.
这是一场等待发生的意外。
You can give your loggers any "."-separated names that are meaningful to you.您可以为记录器指定任何对您有意义的以“.”分隔的名称。
You can control them as a hierarchy.您可以将它们作为层次结构进行控制。 If you have loggers named
abc
and abd
, you can check the logging level for ab
and alter both loggers.如果您有名为
abc
和abd
记录器,您可以检查ab
的日志记录级别并更改两个记录器。
You can have any number of loggers -- they're inexpensive.您可以拥有任意数量的记录器——它们很便宜。
The most common design pattern is one logger per module.最常见的设计模式是每个模块一个记录器。 See Naming Python loggers
请参阅命名 Python 记录器
Do this.做这个。
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 ...
I found a simpler way using functions in your main script:我找到了一种在主脚本中使用函数的更简单的方法:
# 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)
I've found a bit easier way how to filter default logging configuration on following problem using sshtunel module, supressing INFO level messages.我发现了一种更简单的方法,即如何使用sshtunel模块过滤以下问题的默认日志记录配置,抑制 INFO 级别的消息。
Default reporting with first 2 undesired records looked as follows:带有前 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.
Logger configuration update:记录器配置更新:
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)
And result I am happy with looks like this:我很满意的结果是这样的:
2020-11-10 22:00:48,755 INFO |-->QuerySSH: Query execution successful.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.