2013-07-19 9 views
25

への書き込みを取得できません、ここで私は、セットアップのすべてのコードです:フラスコロギング - それは[OK]をファイル

if __name__ == '__main__': 
    app.debug = False 

    applogger = app.logger 

    file_handler = FileHandler("error.log") 
    file_handler.setLevel(logging.DEBUG) 

    applogger.setLevel(logging.DEBUG) 
    applogger.addHandler(file_handler) 

    app.run(host='0.0.0.0') 

何が起こることは

  1. error.logには
  2. 何もありませんが作成されますされるが、
  3. StreamHandlerを追加せずにデバッグをfalseに設定したにもかかわらず、私はまだSTDOUTにすべてを取得します(これは正しいかもしれませんが、まだ変わっているようです)

私は完全にどこかに行っていますか、何が起こっていますか?

+0

'app.debug = True'を設定するとどうなりますか? – dAnjou

+1

何も変更はありません – fleshgolem

答えて

50

なぜこのようにそれをしない:あなたが今、あなたのアプリケーションを起動した場合、あなたはそのerror.logファイルが含まれている参照してくださいよ

if __name__ == '__main__': 
    init_db() # or whatever you need to do 

    import logging 
    logging.basicConfig(filename='error.log',level=logging.DEBUG) 

    app.run(host="0.0.0.0") 

INFO:werkzeug: * Running on http://0.0.0.0:5000/ 

詳細情報については、http://docs.python.org/2/howto/logging.html

をご覧ください。

さて、あなたが示した方法で2つのハンドラを使用することはできないと主張しているので、これを明確にする例を追加します。まず、自分のメインにこのロギングコードを追加します。我々は、セットアップが動作することを確認するよう

import logging, logging.config, yaml 
logging.config.dictConfig(yaml.load(open('logging.conf'))) 

は今も、いくつかのデバッグコードを追加します。

logfile = logging.getLogger('file') 
logconsole = logging.getLogger('console') 
logfile.debug("Debug FILE") 
logconsole.debug("Debug CONSOLE") 

残っているもの全てが「logging.confです"プログラム。

version: 1 
formatters: 
    hiformat: 
    format: 'HI %(asctime)s - %(name)s - %(levelname)s - %(message)s' 
    simple: 
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' 
handlers: 
    console: 
    class: logging.StreamHandler 
    level: DEBUG 
    formatter: hiformat 
    stream: ext://sys.stdout 
    file: 
    class: logging.FileHandler 
    level: DEBUG 
    formatter: simple 
    filename: errors.log 
loggers: 
    console: 
    level: DEBUG 
    handlers: [console] 
    propagate: no 
    file: 
    level: DEBUG 
    handlers: [file] 
    propagate: no 
root: 
    level: DEBUG 
    handlers: [console,file] 

この設定は、必要以上に複雑ですが、ロギングモジュールのいくつかの機能も示しています。今

、私たちは私たちのアプリケーションを実行すると、我々はこの出力(werkzeug-とコンソールロガー)を参照してください。

HI 2013-07-22 16:36:13,475 - console - DEBUG - Debug CONSOLE 
HI 2013-07-22 16:36:13,477 - werkzeug - INFO - * Running on http://0.0.0.0:5000/ 

はまた、「HI」を使用したとするカスタムフォーマッタことに注意してください。

"errors.log"ファイルを見てください。それは含まれています:

2013-07-22 16:36:13,475 - file - DEBUG - Debug FILE 
2013-07-22 16:36:13,477 - werkzeug - INFO - * Running on http://0.0.0.0:5000/ 
+1

私は実際には異なるレベルでログを取る複数のハンドラを実装することを目指しており、このアプローチは私を遠ざけることはありません – fleshgolem

+0

@fleshgolem:まだいくつかのハンドラを作成できます。ちょうどPythonのロギングでそれを行います。 – HolgerSchurig

+0

@fleshgolem:私が持っているURLを見て、logging.confを探します。そこで、2つ目のロガーの作成方法を見ていきます。ロガーには「root」と「simpleExample」があり、両方とも異なるログレベルを持つことができます。 – HolgerSchurig

12

[OK]を、私の失敗は2つの誤解から生じ:それは本番モード

2にで実行されていない限り、フラスコは明らかに、すべてのカスタムログを無視します)

1)デバッグ= Falseですプロダクションモードで動作させるには十分ではありません。あなたは、私がgeventのWSGIサーバーからアプリを開始した後、その

を行うにはWSGIサーバの任意の並べ替えでアプリをラップする必要がある(そして、より適切な場所に初期化をロギング移動)すべてがうまく

+2

あなたの結論は間違っています。私があなたに提案したコードは、a)ビルトイン・サーバー、b)テストおよび/またはデバッグ・モード、c)いくつかのハンドラで実行されます。さらに、あなたの質問はもともと「ファイルに書き込むことができませんでした」という質問が私によって解決されました。残念ながら、あなたはあなたの質問を途中で拡大し、別のものを求めていました...次回は、あなたの問題の方法をより正確に記述することをお勧めします。 – HolgerSchurig

+1

私は完全に同意しません。フラスコの内部ロガーがファイルに書き込まない理由を尋ねました。あなたは、そのロガーを回避するソリューションを提供しました。はい、それは動作しますが、私はそれを正確な答えとは見ません。私は私の問題をひどく述べたことに同意します。私は両方を開いたままにしておきますので、これを見つけた人はどちらの人でも助けを見つけるかもしれません – fleshgolem

+2

「フラスコ内部ロガー」はありません。 FlaskはPythonのロギングモジュールでロガーを使用しています(設定しています)。私はフラスコ/ロギングの "logging getLogger from ..."というステートメントを見るまで、実際には混乱を招くようなFlaskのドキュメントを見つけました。それ以来、Pythonのロギングモジュールは非常にうまく文書化されているので、簡単でした。だから、私はフラスコのロガーを迂回しません。もしそうならFlaskのログ出力はどうすればerrors.logに終わるでしょうか? – HolgerSchurig

6

出力を動作するようですあなたのアプリのコンソールには、基本的なWerkzeugのロガーがあり、それはlogging.getLogger( 'werkzeug')を通してアクセスすることができます。

あなたのロギングは、そのロガーとFlaskのハンドラを追加することで、開発とリリースの両方で機能することができます。

詳細情報とサンプルコード:Write Flask Requests to an Access Log

+2

私はこれを私自身の発見のためにしばらく時間がかかりました。「werkzeug」ロガーは、実際のHTTPレイアドロギングが起こる場所です。残念ながら、ログをフォーマットせず、代わりに ''%s - - [%s]%s \ n '%'をロガーにプッシュしています。したがって、同じスタイルのログを使用するには、そのフォーマットをローカルで再作成するか、 'werkzeug._internal._log'メソッドを呼び出す必要があります。 – Pyrce

+0

これは正解です。 –

+0

私にとって 'logging.Logger.manager.loggerDict'は' werkzeug'ログを含んでおらず、 '@ app.before_first_request'でそれを装飾するまで私の 'top-of-the-module' @デビッドの答え。 – xenoclast

1

これは動作します:

if __name__ == '__main__': 
    import logging 
    logFormatStr = '[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s' 
    logging.basicConfig(format = logFormatStr, filename = "global.log", level=logging.DEBUG) 
    formatter = logging.Formatter(logFormatStr,'%m-%d %H:%M:%S') 
    fileHandler = logging.FileHandler("summary.log") 
    fileHandler.setLevel(logging.DEBUG) 
    fileHandler.setFormatter(formatter) 
    streamHandler = logging.StreamHandler() 
    streamHandler.setLevel(logging.DEBUG) 
    streamHandler.setFormatter(formatter) 
    app.logger.addHandler(fileHandler) 
    app.logger.addHandler(streamHandler) 
    app.logger.info("Logging is set up.") 
    app.run(host='0.0.0.0', port=8000, threaded=True) 
2

私はそれに保って、私は他の答えを好きではなかったと私はフラスコはそれ自身のセットアップをした後、マイログの設定をしなければならなかったようにそれはそう。

@app.before_first_request 
def initialize(): 

    logger = logging.getLogger("your_package_name") 
    logger.setLevel(logging.DEBUG) 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.DEBUG) 
    formatter = logging.Formatter(
    """%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n%(message)s""" 
    ) 
    ch.setFormatter(formatter) 
    logger.addHandler(ch) 

私のアプリは、これらの方向コードでダイビングを取り、見ていないのはなぜhttp://flask.pocoo.org/docs/0.10/patterns/packages/

+0

私の問題はファイルへのロギングではなく、モジュールログとDockerのFlaskログとの組み合わせをフィルタリングしていましたが、私が動作させることができなかった理由は同じです(ロガーを嫌うフラスコ)。この答えは私に必要なものを与えました! – xenoclast

1

/package_name 
    __main__.py <- where I put my logging configuration 
    __init__.py <- conveniance for myself, not necessary 
    /tests 
    /package_name <- Actual flask app 
    __init__.py 
    /views 
    /static 
    /templates 
    /lib 

のように構成されている...

我々はに着陸モジュールですflask.logging.pyは、create_logger(app)という名前の関数を定義しています。その機能を調べることで、Flaskでログの問題をトラブルシューティングする際に潜在的な犯人についての手がかりを得ることができます。

その関数における紛争の最初の原因は、この行です:

変数app.logger_nameが自身であるimport_nameの値にFlask.__init__()方法、に設定されている:

logger = getLogger(app.logger_name) 

理由を見てみましょう受信パラメータはFlask(__name__)です。つまり、app.logger_nameには__name__の値が割り当てられます。これは主パッケージの名前になります。この例では「awesomeapp」としましょう。

これで、独自のロガーを手動で設定して作成することにしたとします。もしあなたのプロジェクトの名前が "awesomeapp"であれば、その名前を使ってロガーを設定する可能性もあると思いますが、それはかなり可能性が高いと思います。

my_logger = logging.getLogger('awesomeapp') # doesn't seem like a bad idea 
fh = logging.FileHandler('/tmp/my_own_log.log') 
my_logger.setLevel(logging.DEBUG) 
my_logger.addHandler(fh) 

いくつかの問題を除いて、これを行うことは理にかなっています。

Flask.loggerプロパティが初めて呼び出されたとき、それは順番に機能flask.logging.create_logger()呼び出すと、次のアクションが続いて起こる:

logger = getLogger(app.logger_name) 

を、プロジェクトの後にあなたのロガーの命名方法を覚えているとどのようにapp.logger_name共有しています名前も?上記のコード行では、関数logging.getLogger()が以前に作成されたロガーを取得したので、後であなたの頭を傷つけるような方法でそれを混乱させることになります。例えば、

ポーフォー、以前にロガーに登録していたハンドラーをすべて失っただけです。

その他の事項は、機能の中で起こりますが、細かいことはありません。sys.stderrおよび/またはResponseオブジェクトに吐き出される2つのlogging.StreamHandlerオブジェクトを作成して登録します。 1つはログレベル 'デバッグ'用で、もう1つは 'プロダクション'用です。私たちの手で構成されたロガーがフラスコに巻き込ま時に動作が異常なようだなぜそれが明確になるはずです点灯する上記の詳細と

class DebugLogger(Logger): 
    def getEffectiveLevel(self): 
     if self.level == 0 and app.debug: 
      return DEBUG 
     return Logger.getEffectiveLevel(self) 

class DebugHandler(StreamHandler): 
    def emit(self, record): 
     if app.debug and _should_log_for(app, 'debug'): 
      StreamHandler.emit(self, record) 

class ProductionHandler(StreamHandler): 
    def emit(self, record): 
     if not app.debug and _should_log_for(app, 'production'): 
      StreamHandler.emit(self, record) 

debug_handler = DebugHandler() 
debug_handler.setLevel(DEBUG) 
debug_handler.setFormatter(Formatter(DEBUG_LOG_FORMAT)) 

prod_handler = ProductionHandler(_proxy_stream) 
prod_handler.setLevel(ERROR) 
prod_handler.setFormatter(Formatter(PROD_LOG_FORMAT)) 

logger.__class__ = DebugLogger 
logger.addHandler(debug_handler) 
logger.addHandler(prod_handler) 

。新しい情報は私達に新しいオプションを与えます。別のロガーを保持したい場合は、プロジェクトとは別の名前(例:my_logger = getLogger('awesomeapp_logger'))にするのが最も簡単な方法です。別のオプションとして、Flaskのログ記録プロトコルと一貫性を持たせたい場合は、Flaskと同様の方法でFlask.loggerlogging.FileHandlerオブジェクトを登録することです。

def enable_file_logging(app): 
    import logging 
    from flask.logging import _should_log_for 

    logging_path = app.config['LOGGING_PATH'] 
    class DebugFileHandler(logging.FileHandler): 
     def emit(self, record): 
      if app.debug and _should_log_for(app, 'debug'): 
       logging.FileHandler.emit(self, record) 

    debug_file_handler = DebugFileHandler('/tmp/my_own_log.log') 
    app.logger.addHandler(debug_file_handler) 

app = Flask(__name__) 
enable_file_logging(app) 
関連する問題