From 7c16054d81ce9af44a4875650b506c9ec2403588 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 27 Aug 2014 01:22:01 +0200 Subject: [PATCH] Updated the logging documentation for recent changes. --- docs/errorhandling.rst | 27 +++++++++++++-------------- flask/logging.py | 24 ++++++++++++++++++++---- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/docs/errorhandling.rst b/docs/errorhandling.rst index 7c557e4f..aa1d34f7 100644 --- a/docs/errorhandling.rst +++ b/docs/errorhandling.rst @@ -32,18 +32,16 @@ Error Mails ----------- If the application runs in production mode (which it will do on your -server) you won't see any log messages by default. Why is that? Flask -tries to be a zero-configuration framework. Where should it drop the logs -for you if there is no configuration? Guessing is not a good idea because -chances are, the place it guessed is not the place where the user has -permission to create a logfile. Also, for most small applications nobody -will look at the logs anyways. +server) you might not see any log messages. The reason for that is that +Flask by default will just report to the WSGI error stream or stderr +(depending on what's available). Where this ends up is sometimes hard to +find. Often it's in your webserver's log files. -In fact, I promise you right now that if you configure a logfile for the -application errors you will never look at it except for debugging an issue -when a user reported it for you. What you want instead is a mail the -second the exception happened. Then you get an alert and you can do -something about it. +I can pretty much promise you however that if you only use a logfile for +the application errors you will never look at it except for debugging an +issue when a user reported it for you. What you probably want instead is +a mail the second the exception happened. Then you get an alert and you +can do something about it. Flask uses the Python builtin logging system, and it can actually send you mails for errors which is probably what you want. Here is how you can @@ -81,9 +79,10 @@ Logging to a File Even if you get mails, you probably also want to log warnings. It's a good idea to keep as much information around that might be required to -debug a problem. Please note that Flask itself will not issue any -warnings in the core system, so it's your responsibility to warn in the -code if something seems odd. +debug a problem. By default as of Flask 1.0, errors are logged to your +webserver's log automatically. Warnings however are not. Please note +that Flask itself will not issue any warnings in the core system, so it's +your responsibility to warn in the code if something seems odd. There are a couple of handlers provided by the logging system out of the box but not all of them are useful for basic error logging. The most diff --git a/flask/logging.py b/flask/logging.py index e31a833f..2bdab56c 100644 --- a/flask/logging.py +++ b/flask/logging.py @@ -11,8 +11,12 @@ from __future__ import absolute_import +import sys + +from werkzeug.local import LocalProxy from logging import getLogger, StreamHandler, Formatter, getLoggerClass, \ DEBUG, ERROR +from .globals import _request_ctx_stack PROD_LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s' @@ -24,7 +28,19 @@ DEBUG_LOG_FORMAT = ( ) -def should_log_for(app, mode): +@LocalProxy +def _proxy_stream(): + """Finds the most appropriate error stream for the application. If a + WSGI request is in flight we log to wsgi.errors, otherwise this resolves + to sys.stderr. + """ + ctx = _request_ctx_stack.top + if ctx is not None: + return ctx.request.environ['wsgi.errors'] + return sys.stderr + + +def _should_log_for(app, mode): policy = app.config['LOGGER_HANDLER_POLICY'] if policy == mode or policy == 'always': return True @@ -48,19 +64,19 @@ def create_logger(app): class DebugHandler(StreamHandler): def emit(self, record): - if app.debug and should_log_for(app, 'debug'): + 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'): + 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() + prod_handler = ProductionHandler(_proxy_stream) prod_handler.setLevel(ERROR) prod_handler.setFormatter(Formatter(PROD_LOG_FORMAT))