test_log.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. from __future__ import generators
  2. import sys
  3. import logging
  4. from celery.tests.utils import unittest
  5. from tempfile import mktemp
  6. from celery.tests.utils import StringIO
  7. try:
  8. from contextlib import contextmanager
  9. except ImportError:
  10. from celery.tests.utils import fallback_contextmanager as contextmanager
  11. from celery import log
  12. from celery.log import (setup_logger, setup_task_logger,
  13. get_default_logger, get_task_logger,
  14. redirect_stdouts_to_logger, LoggingProxy)
  15. from celery.tests.utils import override_stdouts, execute_context
  16. from celery.utils import gen_unique_id
  17. from celery.utils.compat import LoggerAdapter
  18. from celery.utils.compat import _CompatLoggerAdapter
  19. def get_handlers(logger):
  20. if isinstance(logger, LoggerAdapter):
  21. return logger.logger.handlers
  22. return logger.handlers
  23. def set_handlers(logger, new_handlers):
  24. if isinstance(logger, LoggerAdapter):
  25. logger.logger.handlers = new_handlers
  26. logger.handlers = new_handlers
  27. @contextmanager
  28. def wrap_logger(logger, loglevel=logging.ERROR):
  29. old_handlers = get_handlers(logger)
  30. sio = StringIO()
  31. siohandler = logging.StreamHandler(sio)
  32. set_handlers(logger, [siohandler])
  33. yield sio
  34. set_handlers(logger, old_handlers)
  35. class test_default_logger(unittest.TestCase):
  36. def setUp(self):
  37. self.setup_logger = setup_logger
  38. self.get_logger = get_default_logger
  39. log._setup = False
  40. def _assertLog(self, logger, logmsg, loglevel=logging.ERROR):
  41. def with_wrap_logger(sio):
  42. logger.log(loglevel, logmsg)
  43. return sio.getvalue().strip()
  44. context = wrap_logger(logger, loglevel=loglevel)
  45. execute_context(context, with_wrap_logger)
  46. def assertDidLogTrue(self, logger, logmsg, reason, loglevel=None):
  47. val = self._assertLog(logger, logmsg, loglevel=loglevel)
  48. return self.assertEqual(val, logmsg, reason)
  49. def assertDidLogFalse(self, logger, logmsg, reason, loglevel=None):
  50. val = self._assertLog(logger, logmsg, loglevel=loglevel)
  51. return self.assertFalse(val, reason)
  52. def test_setup_logger(self):
  53. logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
  54. root=False)
  55. set_handlers(logger, [])
  56. logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
  57. root=False)
  58. self.assertIs(get_handlers(logger)[0].stream, sys.__stderr__,
  59. "setup_logger logs to stderr without logfile argument.")
  60. self.assertDidLogFalse(logger, "Logging something",
  61. "Logger doesn't info when loglevel is ERROR",
  62. loglevel=logging.INFO)
  63. def test_setup_logger_no_handlers_stream(self):
  64. l = self.get_logger()
  65. set_handlers(l, [])
  66. def with_override_stdouts(outs):
  67. stdout, stderr = outs
  68. l = self.setup_logger(logfile=stderr, loglevel=logging.INFO,
  69. root=False)
  70. l.info("The quick brown fox...")
  71. self.assertIn("The quick brown fox...", stderr.getvalue())
  72. context = override_stdouts()
  73. execute_context(context, with_override_stdouts)
  74. def test_setup_logger_no_handlers_file(self):
  75. l = self.get_logger()
  76. set_handlers(l, [])
  77. tempfile = mktemp(suffix="unittest", prefix="celery")
  78. l = self.setup_logger(logfile=tempfile, loglevel=0, root=False)
  79. self.assertIsInstance(get_handlers(l)[0],
  80. logging.FileHandler)
  81. def test_redirect_stdouts(self):
  82. logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
  83. root=False)
  84. try:
  85. def with_wrap_logger(sio):
  86. redirect_stdouts_to_logger(logger, loglevel=logging.ERROR)
  87. logger.error("foo")
  88. self.assertIn("foo", sio.getvalue())
  89. context = wrap_logger(logger)
  90. execute_context(context, with_wrap_logger)
  91. finally:
  92. sys.stdout, sys.stderr = sys.__stdout__, sys.__stderr__
  93. def test_logging_proxy(self):
  94. logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
  95. root=False)
  96. def with_wrap_logger(sio):
  97. p = LoggingProxy(logger, loglevel=logging.ERROR)
  98. p.close()
  99. p.write("foo")
  100. self.assertNotIn("foo", sio.getvalue())
  101. p.closed = False
  102. p.write("foo")
  103. self.assertIn("foo", sio.getvalue())
  104. lines = ["baz", "xuzzy"]
  105. p.writelines(lines)
  106. for line in lines:
  107. self.assertIn(line, sio.getvalue())
  108. p.flush()
  109. p.close()
  110. self.assertFalse(p.isatty())
  111. self.assertIsNone(p.fileno())
  112. context = wrap_logger(logger)
  113. execute_context(context, with_wrap_logger)
  114. class test_task_logger(test_default_logger):
  115. def setUp(self):
  116. logger = get_task_logger()
  117. logger.handlers = []
  118. logging.root.manager.loggerDict.pop(logger.name, None)
  119. self.id = gen_unique_id()
  120. def setup_logger(self, *args, **kwargs):
  121. return setup_task_logger(*args, **dict(kwargs, task_name=self.id,
  122. task_id=self.id))
  123. def get_logger(self, *args, **kwargs):
  124. id = gen_unique_id()
  125. return get_task_logger(*args, **dict(kwargs, name=self.id))
  126. class MockLogger(logging.Logger):
  127. _records = None
  128. def __init__(self, *args, **kwargs):
  129. self._records = []
  130. logging.Logger.__init__(self, *args, **kwargs)
  131. def handle(self, record):
  132. self._records.append(record)
  133. def isEnabledFor(self, level):
  134. return True
  135. class test_CompatLoggerAdapter(unittest.TestCase):
  136. levels = ("debug",
  137. "info",
  138. "warn", "warning",
  139. "error",
  140. "fatal", "critical")
  141. def setUp(self):
  142. self.logger, self.adapter = self.createAdapter()
  143. def createAdapter(self, name=None, extra={"foo": "bar"}):
  144. logger = MockLogger(name=name or gen_unique_id())
  145. return logger, _CompatLoggerAdapter(logger, extra)
  146. def test_levels(self):
  147. for level in self.levels:
  148. msg = "foo bar %s" % (level, )
  149. logger, adapter = self.createAdapter()
  150. getattr(adapter, level)(msg)
  151. self.assertEqual(logger._records[0].msg, msg)
  152. def test_exception(self):
  153. try:
  154. raise KeyError("foo")
  155. except KeyError:
  156. self.adapter.exception("foo bar exception")
  157. self.assertEqual(self.logger._records[0].msg, "foo bar exception")
  158. def test_setLevel(self):
  159. self.adapter.setLevel(logging.INFO)
  160. self.assertEqual(self.logger.level, logging.INFO)
  161. def test_process(self):
  162. msg, kwargs = self.adapter.process("foo bar baz", {"exc_info": 1})
  163. self.assertDictEqual(kwargs, {"exc_info": 1,
  164. "extra": {"foo": "bar"}})
  165. def test_add_remove_handlers(self):
  166. handler = logging.StreamHandler()
  167. self.adapter.addHandler(handler)
  168. self.assertIs(self.logger.handlers[0], handler)
  169. self.adapter.removeHandler(handler)
  170. self.assertListEqual(self.logger.handlers, [])