Browse Source

Always log now, even if debug is off.

pull/1161/head
Armin Ronacher 11 years ago
parent
commit
84ad89ffa4
  1. 3
      CHANGES
  2. 10
      docs/config.rst
  3. 10
      docs/upgrading.rst
  4. 13
      flask/app.py
  5. 43
      flask/logging.py
  6. 6
      flask/testsuite/basic.py
  7. 1
      flask/testsuite/blueprints.py
  8. 2
      flask/testsuite/helpers.py
  9. 1
      flask/testsuite/testing.py

3
CHANGES

@ -37,6 +37,9 @@ Version 1.0
result in the HTTP error of their choosing, but may be caught with result in the HTTP error of their choosing, but may be caught with
a custom error handler if desired. a custom error handler if desired.
- Added :meth:`flask.Config.from_mapping`. - 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 Version 0.10.2
-------------- --------------

10
docs/config.rst

@ -99,6 +99,14 @@ The following configuration values are used internally by Flask:
by this. by this.
``USE_X_SENDFILE`` enable/disable x-sendfile ``USE_X_SENDFILE`` enable/disable x-sendfile
``LOGGER_NAME`` the name of the logger ``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. ``SERVER_NAME`` the name and port number of the server.
Required for subdomain support (e.g.: Required for subdomain support (e.g.:
``'myapp.dev:5000'``) Note that ``'myapp.dev:5000'``) Note that
@ -229,7 +237,7 @@ The following configuration values are used internally by Flask:
``SESSION_REFRESH_EACH_REQUEST`` ``SESSION_REFRESH_EACH_REQUEST``
.. versionadded:: 1.0 .. versionadded:: 1.0
``TEMPLATES_AUTO_RELOAD`` ``TEMPLATES_AUTO_RELOAD``, ``LOGGER_HANDLER_POLICY``
Configuring from Files Configuring from Files
---------------------- ----------------------

10
docs/upgrading.rst

@ -19,6 +19,16 @@ installation, make sure to pass it the ``-U`` parameter::
$ easy_install -U Flask $ 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: .. _upgrading-to-010:
Version 0.10 Version 0.10

13
flask/app.py

@ -260,18 +260,6 @@ class Flask(_PackageBoundObject):
#: will be removed in favor of Blueprints #: will be removed in favor of Blueprints
enable_modules = True 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`. #: The JSON encoder class to use. Defaults to :class:`~flask.json.JSONEncoder`.
#: #:
#: .. versionadded:: 0.10 #: .. versionadded:: 0.10
@ -297,6 +285,7 @@ class Flask(_PackageBoundObject):
'PERMANENT_SESSION_LIFETIME': timedelta(days=31), 'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False, 'USE_X_SENDFILE': False,
'LOGGER_NAME': None, 'LOGGER_NAME': None,
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None, 'SERVER_NAME': None,
'APPLICATION_ROOT': None, 'APPLICATION_ROOT': None,
'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_NAME': 'session',

43
flask/logging.py

@ -11,7 +11,24 @@
from __future__ import absolute_import 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): def create_logger(app):
@ -30,16 +47,28 @@ def create_logger(app):
return Logger.getEffectiveLevel(x) return Logger.getEffectiveLevel(x)
class DebugHandler(StreamHandler): class DebugHandler(StreamHandler):
def emit(x, record): def emit(self, record):
StreamHandler.emit(x, record) if app.debug else None 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) logger = getLogger(app.logger_name)
# just in case that was not a new logger, get rid of all the handlers # just in case that was not a new logger, get rid of all the handlers
# already attached to it. # already attached to it.
del logger.handlers[:] del logger.handlers[:]
logger.__class__ = DebugLogger logger.__class__ = DebugLogger
logger.addHandler(handler) logger.addHandler(debug_handler)
logger.addHandler(prod_handler)
return logger return logger

6
flask/testsuite/basic.py

@ -559,6 +559,7 @@ class BasicFunctionalityTestCase(FlaskTestCase):
def test_teardown_request_handler_error(self): def test_teardown_request_handler_error(self):
called = [] called = []
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
@app.teardown_request @app.teardown_request
def teardown_request1(exc): def teardown_request1(exc):
self.assert_equal(type(exc), ZeroDivisionError) self.assert_equal(type(exc), ZeroDivisionError)
@ -621,6 +622,7 @@ class BasicFunctionalityTestCase(FlaskTestCase):
def test_error_handling(self): def test_error_handling(self):
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
@app.errorhandler(404) @app.errorhandler(404)
def not_found(e): def not_found(e):
return 'not found', 404 return 'not found', 404
@ -920,6 +922,7 @@ class BasicFunctionalityTestCase(FlaskTestCase):
def test_none_response(self): def test_none_response(self):
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.testing = True
@app.route('/') @app.route('/')
def test(): def test():
return None return None
@ -989,6 +992,7 @@ class BasicFunctionalityTestCase(FlaskTestCase):
def test_exception_propagation(self): def test_exception_propagation(self):
def apprunner(configkey): def apprunner(configkey):
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
@app.route('/') @app.route('/')
def index(): def index():
1 // 0 1 // 0
@ -996,7 +1000,7 @@ class BasicFunctionalityTestCase(FlaskTestCase):
if config_key is not None: if config_key is not None:
app.config[config_key] = True app.config[config_key] = True
try: try:
resp = c.get('/') c.get('/')
except Exception: except Exception:
pass pass
else: else:

1
flask/testsuite/blueprints.py

@ -137,6 +137,7 @@ class ModuleTestCase(FlaskTestCase):
@emits_module_deprecation_warning @emits_module_deprecation_warning
def test_error_handling(self): def test_error_handling(self):
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
admin = flask.Module(__name__, 'admin') admin = flask.Module(__name__, 'admin')
@admin.app_errorhandler(404) @admin.app_errorhandler(404)
def not_found(e): def not_found(e):

2
flask/testsuite/helpers.py

@ -473,6 +473,7 @@ class LoggingTestCase(FlaskTestCase):
def test_exception_logging(self): def test_exception_logging(self):
out = StringIO() out = StringIO()
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
app.logger_name = 'flask_tests/test_exception_logging' app.logger_name = 'flask_tests/test_exception_logging'
app.logger.addHandler(StreamHandler(out)) app.logger.addHandler(StreamHandler(out))
@ -492,6 +493,7 @@ class LoggingTestCase(FlaskTestCase):
def test_processor_exceptions(self): def test_processor_exceptions(self):
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
@app.before_request @app.before_request
def before_request(): def before_request():
if trigger == 'before': if trigger == 'before':

1
flask/testsuite/testing.py

@ -136,6 +136,7 @@ class TestToolsTestCase(FlaskTestCase):
def test_test_client_context_binding(self): def test_test_client_context_binding(self):
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
@app.route('/') @app.route('/')
def index(): def index():
flask.g.value = 42 flask.g.value = 42

Loading…
Cancel
Save