# -*- 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