Skip to content

Commit c9df2ec

Browse files
committed
Basic implementation of a swtichable logging system
1 parent 4e2d98c commit c9df2ec

File tree

4 files changed

+80
-39
lines changed

4 files changed

+80
-39
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ Release date to be announced, codename to be selected
1717
deprecated for :func:`flask.send_file` because it was unreliable.
1818
Pass filenames instead or attach your own etags and provide a
1919
proper mimetype by hand.
20+
- Added support for Logbook and started the slow deprecation process
21+
for logging.
22+
- Removed `flask.Flask.debug_log_format` attribute.
2023

2124
Version 0.6.1
2225
-------------

flask/app.py

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from .templating import _DispatchingJinjaLoader, \
3434
_default_template_ctx_processor
3535
from .signals import request_started, request_finished, got_request_exception
36+
from .logging import init_logging_system, create_logger
3637

3738
# a lock used for logger initialization
3839
_logger_lock = Lock()
@@ -171,15 +172,6 @@ class Flask(_PackageBoundObject):
171172
#: .. versionadded:: 0.4
172173
logger_name = ConfigAttribute('LOGGER_NAME')
173174

174-
#: the name of the logging system that is configured by default. The
175-
#: default is ``'logging'`` but it can be set to ``'logbook'`` as well.
176-
#: The default will change to ``'logbook'`` at one point and later the
177-
#: ``'logging'`` support will eventually disappear together with this
178-
#: setting. Check the :ref:`log-transition` for more information.
179-
#:
180-
#: .. versionadded:: 0.7
181-
logging_system = ConfigAttribute('LOGGING_SYSTEM')
182-
183175
#: the logbook setup that should be in use. This is only used in case
184176
#: the `LOGGING_SYSTEM` is ``'logbook'``. It can point to any
185177
#: :class:`logbook.Processor`, :class:`logbook.Handler` or
@@ -188,18 +180,6 @@ class Flask(_PackageBoundObject):
188180
#: also subclass :class:`Flask` or use the signals to push and pop.
189181
logbook_setup = None
190182

191-
#: The logging format used for the debug logger. This is only used when
192-
#: the application is in debug mode, otherwise the attached logging
193-
#: handler does the formatting.
194-
#:
195-
#: .. versionadded:: 0.3
196-
debug_log_format = (
197-
'-' * 80 + '\n' +
198-
'%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' +
199-
'%(message)s\n' +
200-
'-' * 80
201-
)
202-
203183
#: Options that are passed directly to the Jinja2 environment.
204184
jinja_options = ImmutableDict(
205185
extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_']
@@ -215,11 +195,10 @@ class Flask(_PackageBoundObject):
215195
'USE_X_SENDFILE': False,
216196
'LOGGER_NAME': None,
217197
'SERVER_NAME': None,
218-
'MAX_CONTENT_LENGTH': None,
219-
'LOGGING_SYSTEM': 'logging'
198+
'MAX_CONTENT_LENGTH': None
220199
})
221200

222-
def __init__(self, import_name, static_path=None, use_logbook=None):
201+
def __init__(self, import_name, static_path=None, logging_system=None):
223202
_PackageBoundObject.__init__(self, import_name)
224203
if static_path is not None:
225204
self.static_path = static_path
@@ -325,6 +304,12 @@ def __init__(self, import_name, static_path=None, use_logbook=None):
325304
self.jinja_env = self.create_jinja_environment()
326305
self.init_jinja_globals()
327306

307+
# initialize logging
308+
if logging_system is None:
309+
logging_system = 'logging'
310+
self.logging_system = logging_system
311+
init_logging_system(self)
312+
328313
@property
329314
def logger(self):
330315
"""A :class:`logging.Logger` object for this application. The
@@ -348,7 +333,6 @@ def logger(self):
348333
with _logger_lock:
349334
if self._logger and self._logger.name == self.logger_name:
350335
return self._logger
351-
from flask.logging import create_logger
352336
self._logger = rv = create_logger(self)
353337
return rv
354338

flask/logging.py

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@
33
flask.logging
44
~~~~~~~~~~~~~
55
6-
Implements the logging support for Flask.
6+
Implements the logging support for Flask. This is not supposed to be a
7+
abstraction layer above multiple logging systems, it mainly exists because
8+
Flask started out using logging and is currently in the process to switch
9+
to Logbook. This module will become mostly useless once we drop support
10+
for the stdlib's logging.
11+
12+
In some other parts of Flask there are explicit hardcoded checks that
13+
opt-in features in case Logbook is present.
714
815
:copyright: (c) 2010 by Armin Ronacher.
916
:license: BSD, see LICENSE for more details.
@@ -13,21 +20,41 @@
1320

1421

1522
def create_logger(app):
23+
"""Creates a new logger for the application. This is mainly needed
24+
because Flask supports dynamic logger name changes. Once we drop
25+
support for logging we can remove this as well because it is easily
26+
possible to reflect the channel name from another value in logbook
27+
"""
28+
return logging_systems[app.logging_system][1](app)
29+
30+
31+
def init_logging_system(app):
1632
"""Initializes the logging system for this app."""
17-
return logging_systems[app.logging_system](app)
33+
return logging_systems[app.logging_system][0](app)
1834

1935

20-
def init_logbook(app):
36+
def create_logbook_logger(app):
2137
"""Initializes the logbook default config for the application."""
22-
try:
23-
from logbook import Logger
24-
except ImportError:
25-
raise RuntimeError('Logbook is not installed but required for '
26-
'the logbook logging backend.')
38+
from logbook import Logger
2739
return Logger(app.logger_name)
2840

2941

30-
def init_logging(app):
42+
def init_logbook(app):
43+
"""Stuffs a default logging setup on the application object in case
44+
the attribute was not set so far.
45+
"""
46+
if app.logbook_setup is None:
47+
from logbook import StderrHandler
48+
app.logbook_setup = StderrHandler(format_string=(
49+
'-' * 80 + '\n' +
50+
'{record.level_name} in {record.module} '
51+
'[{record.filename}:{record.lineno}]:\n' +
52+
'{record.message}\n' +
53+
'-' * 80
54+
))
55+
56+
57+
def create_logging_logger(app):
3158
"""Creates a logger for the given application. This logger works
3259
similar to a regular Python logger but changes the effective logging
3360
level based on the application's debug flag. Furthermore this
@@ -46,7 +73,12 @@ def emit(x, record):
4673

4774
handler = DebugHandler()
4875
handler.setLevel(DEBUG)
49-
handler.setFormatter(Formatter(app.debug_log_format))
76+
handler.setFormatter(Formatter(
77+
'-' * 80 + '\n' +
78+
'%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' +
79+
'%(message)s\n' +
80+
'-' * 80
81+
))
5082
logger = getLogger(app.logger_name)
5183
# just in case that was not a new logger, get rid of all the handlers
5284
# already attached to it.
@@ -56,7 +88,23 @@ def emit(x, record):
5688
return logger
5789

5890

91+
def create_dummy_logger(app):
92+
"""Creates a dummy logger."""
93+
return _DummyLogger(app.logger_name)
94+
95+
96+
class _DummyLogger(object):
97+
"""Not a very helpful logger."""
98+
def __init__(self, name, level=0):
99+
self.name = name
100+
self.level = level
101+
debug = info = warn = warning = notice = error = exception = \
102+
critical = log = lambda *a, **kw: None
103+
104+
105+
_dummy = lambda x: None
59106
logging_systems = {
60-
'logbook': init_logbook,
61-
'logging': init_logging
107+
'logbook': (init_logbook, create_logbook_logger),
108+
'logging': (_dummy, create_logging_logger),
109+
'none': (_dummy, create_dummy_logger)
62110
}

tests/flask_tests.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,8 @@ def test_logger_cache(self):
950950
app.logger_name = __name__ + '/test_logger_cache'
951951
assert app.logger is not logger1
952952

953-
def test_debug_log(self):
954-
app = flask.Flask(__name__)
953+
def perform_debug_log_test(self, logging_system):
954+
app = flask.Flask(__name__, logging_system=logging_system)
955955
app.debug = True
956956

957957
@app.route('/')
@@ -981,6 +981,12 @@ def exc():
981981
else:
982982
assert False, 'debug log ate the exception'
983983

984+
def test_logging_debug_log(self):
985+
self.perform_debug_log_test('logging')
986+
987+
def test_logbook_debug_log(self):
988+
self.perform_debug_log_test('logbook')
989+
984990
def test_exception_logging(self):
985991
out = StringIO()
986992
app = flask.Flask(__name__)

0 commit comments

Comments
 (0)