2016-01-27 8 views
5

pythonのログ出力をロガーツリーに対応するツリー形式にしたいと考えています。例を見てください。ログメッセージをツリー形式でフォーマットする

私たちは、コードを持っているとしましょう:

import logging 

logger_a = logging.getLogger("a") 
logger_a_b = logging.getLogger("a.b") 
logger_a_b_c = logging.getLogger("a.b.c") 
# ... 


logger_a.debug("One") 

logger_a_b.warning("two") 
logger_a_b.warning("three") 

logger_a_b_c.critical("Four") 

logger_a_b.warning("Five") 

出力のようなものでなければなりません:

<--"a" 
    | DEBUG: One 
    | 
    o<--"a.b" 
    | | WARNING: Two 
    | | WARNING: Three 
    | | 
    | o<--"a.b.c" 
    |  | CRITICAL: Four 
    |  | 
    | | WARNING: Five 

私は手でログのそれぞれについて、フォーマッタを書くことができ、それは解決しませんo < - "ab"のようなものを挿入する問題と私は構造を記録することによって自動的にオフセットを計算することを好むでしょう。

logging treeというモジュールがあります。ロギングレイアウトを出力します。私が望むのは、ログメッセージをほぼ同じ方法で印刷することです。

ライブラリを知っていますか、それを簡単に行う方法はありますか?

+0

私はあなた自身のログハンドラを書く必要があると思います。組み込みの 'logging.StreamHandler'を継承しているかもしれません。 –

+0

標準出力をこのツリーに変換するのは難しくありません。モジュール名を取得し、ドットで区切り、メッセージの前にツリーを描きます。あなたはすでにすべての情報を持っているように見えますが、ビュー変換が必要です。 – viraptor

+0

おそらくそれで十分でしょう – MajesticRa

答えて

3

例に基づいて、ツリーを処理するカスタムFormatterを作成しました。

import logging 

# custom tree formatter 
class TreeFormatter(logging.Formatter): 
    formatPrefix = {} # map loggername, formatPrefix 

    def format(self, record): 
     s = "" 
     # first time this name is encountered: create the prefix and print the name 
     if not record.name in self.formatPrefix: 
      f = self.getFormatPrefix(record) 
      s += "%s \"%s\"\n" % (f, record.name) 

     # print the actual message 
     s += "%s %s: %s" % (self.formatPrefix[record.name], record.levelname, record.msg) 
     return s 


    # create the format prefix for the given package name 
    # (stored in self.formatPrefix[record.name]) 
    # and return the first line to print 
    def getFormatPrefix(self, record): 
     depth = record.name.count(".") 
     self.formatPrefix[record.name] = " |" * (depth+1) 

     if depth == 0: 
      return "<--" 

     return "%so<--" % ((" |" * depth)[:-1]) 

これを使用して、第1レベルのロガー(ここではa)を作成できます。残りのコードは変更されていません。ここで

は一例です:

# use this to create the first level logger 
def createTreeLogger(name, level=logging.DEBUG): 
    logger = logging.getLogger(name) 
    logger.setLevel(level) 
    ch = logging.StreamHandler() 
    ch.setLevel(level) 
    ch.setFormatter(TreeFormatter()) 
    logger.addHandler(ch) 
    return logger 


if __name__ == '__main__': 

    logger_a = createTreeLogger("a") # first level: use createLogger 
    # then create your loggers as always 
    logger_a_b = logging.getLogger("a.b") 
    logger_a_b_c = logging.getLogger("a.b.c") 


    logger_a.debug("One") 

    logger_a_b.warning("two") 
    logger_a_b.warning("three") 

    logger_a_b_c.critical("Four") 

    logger_a_b.warning("Five") 
    logger_a.warning("Six") 

いいです何loggingパッケージの内部には、自動的にサブパッケージ(a.b、A.B.C)に同じハンドラを使用することです。だから、このコードを実行することによって、あなたが得る:

<-- "a" 
    | DEBUG: One 
    o<-- "a.b" 
    | | WARNING: two 
    | | WARNING: three 
    | o<-- "a.b.c" 
    | | | CRITICAL: Four 
    | | WARNING: Five 
    | WARNING: Six 

一つの欠点は、複数のパッケージ階層を持っている場合、ログが混乱になるということです。しかし、TreeFormatterクラスはあなたのニーズに合わせて簡単に調整できます。

関連する問題