logging.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # -*- coding: utf-8 -*-
  2. """
  3. flask.logging
  4. ~~~~~~~~~~~~~
  5. Implements the logging support for Flask.
  6. :copyright: (c) 2015 by Armin Ronacher.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. from __future__ import absolute_import
  10. import sys
  11. from werkzeug.local import LocalProxy
  12. from logging import getLogger, StreamHandler, Formatter, getLoggerClass, \
  13. DEBUG, ERROR
  14. from .globals import _request_ctx_stack
  15. PROD_LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
  16. DEBUG_LOG_FORMAT = (
  17. '-' * 80 + '\n' +
  18. '%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' +
  19. '%(message)s\n' +
  20. '-' * 80
  21. )
  22. @LocalProxy
  23. def _proxy_stream():
  24. """Finds the most appropriate error stream for the application. If a
  25. WSGI request is in flight we log to wsgi.errors, otherwise this resolves
  26. to sys.stderr.
  27. """
  28. ctx = _request_ctx_stack.top
  29. if ctx is not None:
  30. return ctx.request.environ['wsgi.errors']
  31. return sys.stderr
  32. def _should_log_for(app, mode):
  33. policy = app.config['LOGGER_HANDLER_POLICY']
  34. if policy == mode or policy == 'always':
  35. return True
  36. return False
  37. def create_logger(app):
  38. """Creates a logger for the given application. This logger works
  39. similar to a regular Python logger but changes the effective logging
  40. level based on the application's debug flag. Furthermore this
  41. function also removes all attached handlers in case there was a
  42. logger with the log name before.
  43. """
  44. Logger = getLoggerClass()
  45. class DebugLogger(Logger):
  46. def getEffectiveLevel(self):
  47. if self.level == 0 and app.debug:
  48. return DEBUG
  49. return Logger.getEffectiveLevel(self)
  50. class DebugHandler(StreamHandler):
  51. def emit(self, record):
  52. if app.debug and _should_log_for(app, 'debug'):
  53. StreamHandler.emit(self, record)
  54. class ProductionHandler(StreamHandler):
  55. def emit(self, record):
  56. if not app.debug and _should_log_for(app, 'production'):
  57. StreamHandler.emit(self, record)
  58. debug_handler = DebugHandler()
  59. debug_handler.setLevel(DEBUG)
  60. debug_handler.setFormatter(Formatter(DEBUG_LOG_FORMAT))
  61. prod_handler = ProductionHandler(_proxy_stream)
  62. prod_handler.setLevel(ERROR)
  63. prod_handler.setFormatter(Formatter(PROD_LOG_FORMAT))
  64. logger = getLogger(app.logger_name)
  65. # just in case that was not a new logger, get rid of all the handlers
  66. # already attached to it.
  67. del logger.handlers[:]
  68. logger.__class__ = DebugLogger
  69. logger.addHandler(debug_handler)
  70. logger.addHandler(prod_handler)
  71. return logger