2017-07-13 1 views
1

私は自分のプロジェクトに固有の汎用ロガーインスタンスを持っています。それは自動的に2つのハンドラ(StreamHandlerTimedRotatingFileHandler)を作成し、それらにあらかじめ設定された異なる書式などを付けて添付します。pythonプロジェクトでモジュール間でloggerインスタンスを共有する必要はありますか?

/ 
- app.py 
- settings.py 
- dir1/ 
    - __init__.py 
    - mod1.py 
- dir2/ 
    - __init__.py 
    - mod2.py 

私はpython app.pyを使用してサーバを起動します。

logging_formatters = { 
    'fmt': "%(asctime)s [%(levelname)8s:%(process)05d] [%(module)10s:%(lineno)03d] (%(name)s) %(message)s", 
    'datefmt': "%Y-%m-%d %H:%M:%S" 
} 
def get_logger(
     application_name=None, 
     filename=None, 
     *args, 
     **kwargs 
): 
    if not isinstance(application_name, str): 
     raise ValueError("Logger class expects a string type application name") 

    if filename is None: 
     filename = application_name 

    if not filename.endswith(".log"): 
     filename = filename.split('.')[0] + ".log" 

    log_path = kwargs.get('log_path') 
    service_name = kwargs.get('service_name', '') 
    console_level = kwargs.get('console_level', logging.INFO) 
    file_level = kwargs.get('file_level', logging.DEBUG) 

    logger = logging.getLogger(application_name) 
    if len(logger.handlers) > 0: 
     return logger 
    # Create 2 handlers, and add them to the logger created 
    # ... 
    # ... 
    # ... 

さて、私のフラスコのプロジェクト構造を仮定のようなものです。 app.py自体はdir1.mod1dir2.mod2のモジュールをインポートします。以下のように、これらのモジュールの各々は、独自のロガーインスタンスを作成します。

logger = log_package.get_logger(
    application_name='{}.{}'.format(settings.APPLICATION_NAME, __name__), 
    filename=settings.LOG_FILE_NAME, 
    service_name=settings.SERVICE_NAME, 
) 

をしてapp.pyの場合、それは次のようになります。

logger = log_package.get_logger(
    application_name='{}.{}'.format(settings.APPLICATION_NAME, 'run'), 
    filename=settings.LOG_FILE_NAME, 
    service_name=settings.SERVICE_NAME, 
) 

さて、私が直面しています問題はそれです。 TimedRotatingFileHandlerはすべてのサブモジュール(つまり、dir1.mod1dir2.mod2など)で正常に動作していますが、app.pyのログは新しいファイルにロールオーバーされません。その特定のインスタンスは、サービスが開始されたときと同じファイルにログを書き込んでいます。たとえば。 2017-07-11でサービスを開始した場合、app.pyはログをLOG_FILE_NAME.log.2017-07-11に書き込んだり、他のモジュールは毎日ロールオーバーします(when=midnight)。新しいログはLOG_FILE_NAME.logに書き込まれます。

TimedRotatingFileHandlerは特定のファイルでは機能しません。私は、ディレクトリ内のすべてのファイルのlsofのコマンドを実行し、これが出力された:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME 
python 23795 ubuntu 4w REG 202,1 2680401 150244 /path/to/LOG_FILE_NAME.2017-07-12 
python 23795 ubuntu 33w REG 202,1 397074 150256 /path/to/LOG_FILE_NAME.log 

は、私はPythonのプロジェクトにモジュール間でロガーインスタンスを共有する必要がありますか?私はロギングモジュール自体がスレッドセーフであるため、これは必須ではないと思います。

+0

私は自分の答えを更新しました。 –

答えて

1

インスタンスは、LOG_FILE_NAME.log以外のファイルに書き込むべきではありません.LOG_FILE_NAME.2017-07-12などのその他のファイルは、ロールオーバー時に作成されるため、開いたままにしないでください。

同じファイル名を参照する2つの異なるハンドラインスタンスがある場合、予期しない動作が発生する可能性があります(1つのインスタンスがロールオーバーした場合、使用しているファイルですが、もう一方のインスタンスはまだ古いファイルへの参照を持ち、それに書き込み続けます)。

個々のモジュールロガーではなく、ルートロガーにハンドラーを接続するだけで、他のロガーはデフォルトの条件(ロガーのデフォルトはpropagateの設定は変更されていません)でハンドラーを選択します。

更新:常にハンドラは祖先ロガーに接続されている場合でも、ログ呼び出しのために使用されたロガーの名前を与える%(name)s。ロガーのpropagateFalseに設定されている場合、祖先ロガーのハンドラーは使用されないため、propagateはデフォルト値のTrueのままにしてください。

+0

しかし、私は '%(name)s'がロガーの名前を表したがります。誰か(私はいくつかの同僚と 'log_package'を共有しています)がプロジェクト' A'を作成している場合、プロジェクトのすべてのロガーを 'A.app'、' A.dir1.mod1'、...とログファイルは常に 'A.log'になります。私の関数定義の終わりに向かって、伝播値: 'logger.propagate = False'をオーバーライドしました。 'logger.propagate'を' True'にリセットする必要がありますか? – hjpotter92

関連する問題