mirror of https://github.com/mitsuhiko/flask.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.6 KiB
90 lines
2.6 KiB
# -*- coding: utf-8 -*- |
|
""" |
|
flask.logging |
|
~~~~~~~~~~~~~ |
|
|
|
Implements the logging support for Flask. |
|
|
|
:copyright: (c) 2015 by Armin Ronacher. |
|
:license: BSD, see LICENSE for more details. |
|
""" |
|
|
|
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' |
|
DEBUG_LOG_FORMAT = ( |
|
'-' * 80 + '\n' + |
|
'%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' + |
|
'%(message)s\n' + |
|
'-' * 80 |
|
) |
|
|
|
|
|
@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 |
|
return False |
|
|
|
|
|
def create_logger(app): |
|
"""Creates a logger for the given application. This logger works |
|
similar to a regular Python logger but changes the effective logging |
|
level based on the application's debug flag. Furthermore this |
|
function also removes all attached handlers in case there was a |
|
logger with the log name before. |
|
""" |
|
Logger = getLoggerClass() |
|
|
|
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 = 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(debug_handler) |
|
logger.addHandler(prod_handler) |
|
return logger
|
|
|