web-dev-qa-db-ja.com

フィルターを使用したロギング

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")が含まれています。 「構文解析」メッセージ(メッセージを送信しているモジュール/機能に関係なく?)

38
jd.

_logging.Filter_のサブクラスを実装するだけです: http://docs.python.org/library/logging.html#filter-objects 。ログレコードを調べてログに記録する場合はTrue、破棄する場合はFalseを返すfilter(record)という1つのメソッドがあります。次に、addFilter(filter)メソッドを呼び出して、LoggerまたはHandlerにフィルターをインストールできます。

例:

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

logger.addFilter(NoParsingFilter())
_

とにかく、そのようなもの。

56
David Z

グローバルは使用しないでください。それは起こるのを待っている事故です。

ロガーには、「。」で区切られた、わかりやすい名前を付けることができます。

それらを階層として制御できます。 a.b.cおよびa.b.dという名前のロガーがある場合、a.bのログレベルを確認して、両方のロガーを変更できます。

ロガーはいくつでも持つことができます-ロガーは安価です。

最も一般的な設計パターンは、モジュールごとに1つのロガーです。参照 Naming Python loggers

これを行う。

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 functio_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 ...
20
S.Lott

メインスクリプトで関数を使用する簡単な方法を見つけました。

# 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)
1
Gringo Suave