2011-06-17 7 views
2

私はサーバーサブクラスでスレッドレスポンスハンドラを生成し、ハンドラはアプリケーションスレッドを開始します。 ObjGraphアプリケーションスレッドが正しく実行されていることを確認しています(私は負荷テストを行っており、アプリケーションインスタンスを35個実行するように調整しています)。スレッド固有のロガーインスタンスからのメモリリークを伴うPythonマルチスレッドアプリケーション

objgraph.typestats()を呼び出すと、各オブジェクトのインスタンスがインタプリタ内に現在いくつ存在しているかが分かります(GCに従って)。メモリリークの出力を見ると、700ロガーインスタンスが見つかります。これは、サーバーによって生成されたレスポンスハンドラの総数です。

アプリケーションスレッドがrun()メソッドを終了し、ロガーインスタンスへの参照が残っていないこと、またロガーインスタンスが完全に分離されていることを確認するには、logger.removehandler(memoryhandler)とlogger.removehandler (外部参照はありません)。これらのロガーインスタンスを削除する最終的なスタブとして、del()の最後のステートメントはdel self.loggerです。

init()でロガーを取得するには、適切な大きさの乱数を付けてファイルアクセス - アプリケーションログの衝突を避けるために、ログファイル名の一部と同じ大きな番号を使用します。

長短ですが、私はGCによって追跡された700のロガーインスタンスを持っていますが、アクティブなスレッドは35個しかありません。これらのロガーを強制終了するにはどうすればよいですか?より厄介なエンジニアソリューションは、ロガーのプールを作成し、アプリケーションスレッドの寿命の間に取得するだけですが、GCがこれを自動的に処理する必要がある場合に、より多くのコードを作成して維持します。

答えて

0

無制限の数のロガーを作成しないでください。これは良い習慣ではありません。文書に記載されているように、文脈依存の情報をログに取り込む他の方法があります。here

ロガーをインスタンス属性として持つ必要もありません。ロガーはシングルトンなので、どこからでも特定の名前を取得できます。推奨される方法は、ほとんどのシナリオでは十分なモジュールレベルのロガーに、

logger = logging.getLogger(__name__) 

を使用することです。

あなたの質問から、ハンドラとロガーが同じものではないかどうかはわかりません。たとえば、removeHandlerコール(ハンドラインスタンスの解放に役立つ参照カウントがゼロになるため、そのようにしてロガーインスタンスを解放することはありません)。

一般的に、ロガーの名前は、対象のイベントを生成するアプリケーションの部分の名前になります。

別のファイルに書き込むときは、毎回新しいファイル名を作成し、終了してスレッドが終了しようとしているときにハンドラを閉じることができます(その終了はハンドラリソースを解放するために重要です)。または、ログ出力に含まれるスレッドIDやその他のディスクリミネータを使用してすべてを1つのファイルに記録し、ログファイルに対して後処理を使用できます。

0

logging.Loggerを使用しているとき、私は)(同じメモリリークを満たし、そしてあなたはロガーが役に立たないときに、手動でハンドラFDを閉じようとする、のように:

for handler in logger.handlers: 
    handler.close()