From 84ad89ffa4390d3327b4d35983dbb4d84293b8e2 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 27 Aug 2014 01:08:12 +0200 Subject: [PATCH] Always log now, even if debug is off. --- CHANGES | 3 +++ docs/config.rst | 10 +++++++- docs/upgrading.rst | 10 ++++++++ flask/app.py | 13 +---------- flask/logging.py | 43 +++++++++++++++++++++++++++++------ flask/testsuite/basic.py | 6 ++++- flask/testsuite/blueprints.py | 1 + flask/testsuite/helpers.py | 2 ++ flask/testsuite/testing.py | 1 + 9 files changed, 68 insertions(+), 21 deletions(-) diff --git a/CHANGES b/CHANGES index ec031c53..60bffd88 100644 --- a/CHANGES +++ b/CHANGES @@ -37,6 +37,9 @@ Version 1.0 result in the HTTP error of their choosing, but may be caught with a custom error handler if desired. - Added :meth:`flask.Config.from_mapping`. +- Flask will now log by default even if debug is disabled. The log format is + now hardcoded but the default log handling can be disabled through the + ``LOGGER_HANDLER_POLICY`` configuration key. Version 0.10.2 -------------- diff --git a/docs/config.rst b/docs/config.rst index cd2afebb..1975806e 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -99,6 +99,14 @@ The following configuration values are used internally by Flask: by this. ``USE_X_SENDFILE`` enable/disable x-sendfile ``LOGGER_NAME`` the name of the logger +``LOGGER_HANDLER_POLICY`` the policy of the default logging + handler. The default is ``'always'`` + which means that the default logging + handler is always active. ``'debug'`` + will only activate logging in debug + mode, ``'production'`` will only log in + production and ``'never'`` disables it + entirely. ``SERVER_NAME`` the name and port number of the server. Required for subdomain support (e.g.: ``'myapp.dev:5000'``) Note that @@ -229,7 +237,7 @@ The following configuration values are used internally by Flask: ``SESSION_REFRESH_EACH_REQUEST`` .. versionadded:: 1.0 - ``TEMPLATES_AUTO_RELOAD`` + ``TEMPLATES_AUTO_RELOAD``, ``LOGGER_HANDLER_POLICY`` Configuring from Files ---------------------- diff --git a/docs/upgrading.rst b/docs/upgrading.rst index 5b2d6f85..fa32efb5 100644 --- a/docs/upgrading.rst +++ b/docs/upgrading.rst @@ -19,6 +19,16 @@ installation, make sure to pass it the ``-U`` parameter:: $ easy_install -U Flask +.. _upgrading-to-10: + +Version 1.0 +----------- + +Flask 1.0 removed the ``debug_log_format`` attribute from Flask +applications. Instead the new ``LOGGER_HANDLER_POLICY`` configuration can +be used to disable the default log handlers and custom log handlers can be +set up. + .. _upgrading-to-010: Version 0.10 diff --git a/flask/app.py b/flask/app.py index fcacd0c2..a4ee1c46 100644 --- a/flask/app.py +++ b/flask/app.py @@ -260,18 +260,6 @@ class Flask(_PackageBoundObject): #: will be removed in favor of Blueprints enable_modules = True - #: The logging format used for the debug logger. This is only used when - #: the application is in debug mode, otherwise the attached logging - #: handler does the formatting. - #: - #: .. versionadded:: 0.3 - debug_log_format = ( - '-' * 80 + '\n' + - '%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' + - '%(message)s\n' + - '-' * 80 - ) - #: The JSON encoder class to use. Defaults to :class:`~flask.json.JSONEncoder`. #: #: .. versionadded:: 0.10 @@ -297,6 +285,7 @@ class Flask(_PackageBoundObject): 'PERMANENT_SESSION_LIFETIME': timedelta(days=31), 'USE_X_SENDFILE': False, 'LOGGER_NAME': None, + 'LOGGER_HANDLER_POLICY': 'always', 'SERVER_NAME': None, 'APPLICATION_ROOT': None, 'SESSION_COOKIE_NAME': 'session', diff --git a/flask/logging.py b/flask/logging.py index 5022a696..e31a833f 100644 --- a/flask/logging.py +++ b/flask/logging.py @@ -11,7 +11,24 @@ from __future__ import absolute_import -from logging import getLogger, StreamHandler, Formatter, getLoggerClass, DEBUG +from logging import getLogger, StreamHandler, Formatter, getLoggerClass, \ + DEBUG, ERROR + + +PROD_LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s' +DEBUG_LOG_FORMAT = ( + '-' * 80 + '\n' + + '%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' + + '%(message)s\n' + + '-' * 80 +) + + +def should_log_for(app, mode): + policy = app.config['LOGGER_HANDLER_POLICY'] + if policy == mode or policy == 'always': + return True + return False def create_logger(app): @@ -30,16 +47,28 @@ def create_logger(app): return Logger.getEffectiveLevel(x) class DebugHandler(StreamHandler): - def emit(x, record): - StreamHandler.emit(x, record) if app.debug else None + 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() + prod_handler.setLevel(ERROR) + prod_handler.setFormatter(Formatter(PROD_LOG_FORMAT)) - handler = DebugHandler() - handler.setLevel(DEBUG) - handler.setFormatter(Formatter(app.debug_log_format)) logger = getLogger(app.logger_name) # just in case that was not a new logger, get rid of all the handlers # already attached to it. del logger.handlers[:] logger.__class__ = DebugLogger - logger.addHandler(handler) + logger.addHandler(debug_handler) + logger.addHandler(prod_handler) return logger diff --git a/flask/testsuite/basic.py b/flask/testsuite/basic.py index d56da623..8b216b0e 100644 --- a/flask/testsuite/basic.py +++ b/flask/testsuite/basic.py @@ -559,6 +559,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): def test_teardown_request_handler_error(self): called = [] app = flask.Flask(__name__) + app.config['LOGGER_HANDLER_POLICY'] = 'never' @app.teardown_request def teardown_request1(exc): self.assert_equal(type(exc), ZeroDivisionError) @@ -621,6 +622,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): def test_error_handling(self): app = flask.Flask(__name__) + app.config['LOGGER_HANDLER_POLICY'] = 'never' @app.errorhandler(404) def not_found(e): return 'not found', 404 @@ -920,6 +922,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): def test_none_response(self): app = flask.Flask(__name__) + app.testing = True @app.route('/') def test(): return None @@ -989,6 +992,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): def test_exception_propagation(self): def apprunner(configkey): app = flask.Flask(__name__) + app.config['LOGGER_HANDLER_POLICY'] = 'never' @app.route('/') def index(): 1 // 0 @@ -996,7 +1000,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): if config_key is not None: app.config[config_key] = True try: - resp = c.get('/') + c.get('/') except Exception: pass else: diff --git a/flask/testsuite/blueprints.py b/flask/testsuite/blueprints.py index 8b3e530c..a389a988 100644 --- a/flask/testsuite/blueprints.py +++ b/flask/testsuite/blueprints.py @@ -137,6 +137,7 @@ class ModuleTestCase(FlaskTestCase): @emits_module_deprecation_warning def test_error_handling(self): app = flask.Flask(__name__) + app.config['LOGGER_HANDLER_POLICY'] = 'never' admin = flask.Module(__name__, 'admin') @admin.app_errorhandler(404) def not_found(e): diff --git a/flask/testsuite/helpers.py b/flask/testsuite/helpers.py index 38c1ceef..e08a2283 100644 --- a/flask/testsuite/helpers.py +++ b/flask/testsuite/helpers.py @@ -473,6 +473,7 @@ class LoggingTestCase(FlaskTestCase): def test_exception_logging(self): out = StringIO() app = flask.Flask(__name__) + app.config['LOGGER_HANDLER_POLICY'] = 'never' app.logger_name = 'flask_tests/test_exception_logging' app.logger.addHandler(StreamHandler(out)) @@ -492,6 +493,7 @@ class LoggingTestCase(FlaskTestCase): def test_processor_exceptions(self): app = flask.Flask(__name__) + app.config['LOGGER_HANDLER_POLICY'] = 'never' @app.before_request def before_request(): if trigger == 'before': diff --git a/flask/testsuite/testing.py b/flask/testsuite/testing.py index 11ab763b..25924839 100644 --- a/flask/testsuite/testing.py +++ b/flask/testsuite/testing.py @@ -136,6 +136,7 @@ class TestToolsTestCase(FlaskTestCase): def test_test_client_context_binding(self): app = flask.Flask(__name__) + app.config['LOGGER_HANDLER_POLICY'] = 'never' @app.route('/') def index(): flask.g.value = 42