_logger.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. # -*- test-case-name: twisted.logger.test.test_logger -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Logger class.
  6. """
  7. from time import time
  8. from twisted.python.compat import currentframe
  9. from twisted.python.failure import Failure
  10. from ._levels import InvalidLogLevelError, LogLevel
  11. class Logger(object):
  12. """
  13. A L{Logger} emits log messages to an observer. You should instantiate it
  14. as a class or module attribute, as documented in L{this module's
  15. documentation <twisted.logger>}.
  16. """
  17. @staticmethod
  18. def _namespaceFromCallingContext():
  19. """
  20. Derive a namespace from the module containing the caller's caller.
  21. @return: the fully qualified python name of a module.
  22. @rtype: L{str} (native string)
  23. """
  24. return currentframe(2).f_globals["__name__"]
  25. def __init__(self, namespace=None, source=None, observer=None):
  26. """
  27. @param namespace: The namespace for this logger. Uses a dotted
  28. notation, as used by python modules. If not L{None}, then the name
  29. of the module of the caller is used.
  30. @type namespace: L{str} (native string)
  31. @param source: The object which is emitting events via this
  32. logger; this is automatically set on instances of a class
  33. if this L{Logger} is an attribute of that class.
  34. @type source: L{object}
  35. @param observer: The observer that this logger will send events to.
  36. If L{None}, use the L{global log publisher <globalLogPublisher>}.
  37. @type observer: L{ILogObserver}
  38. """
  39. if namespace is None:
  40. namespace = self._namespaceFromCallingContext()
  41. self.namespace = namespace
  42. self.source = source
  43. if observer is None:
  44. from ._global import globalLogPublisher
  45. self.observer = globalLogPublisher
  46. else:
  47. self.observer = observer
  48. def __get__(self, oself, type=None):
  49. """
  50. When used as a descriptor, i.e.::
  51. # File: athing.py
  52. class Something(object):
  53. log = Logger()
  54. def hello(self):
  55. self.log.info("Hello")
  56. a L{Logger}'s namespace will be set to the name of the class it is
  57. declared on. In the above example, the namespace would be
  58. C{athing.Something}.
  59. Additionally, its source will be set to the actual object referring to
  60. the L{Logger}. In the above example, C{Something.log.source} would be
  61. C{Something}, and C{Something().log.source} would be an instance of
  62. C{Something}.
  63. """
  64. if oself is None:
  65. source = type
  66. else:
  67. source = oself
  68. return self.__class__(
  69. ".".join([type.__module__, type.__name__]),
  70. source,
  71. observer=self.observer,
  72. )
  73. def __repr__(self):
  74. return "<%s %r>" % (self.__class__.__name__, self.namespace)
  75. def emit(self, level, format=None, **kwargs):
  76. """
  77. Emit a log event to all log observers at the given level.
  78. @param level: a L{LogLevel}
  79. @param format: a message format using new-style (PEP 3101)
  80. formatting. The logging event (which is a L{dict}) is
  81. used to render this format string.
  82. @param kwargs: additional key/value pairs to include in the event.
  83. Note that values which are later mutated may result in
  84. non-deterministic behavior from observers that schedule work for
  85. later execution.
  86. """
  87. if level not in LogLevel.iterconstants():
  88. self.failure(
  89. "Got invalid log level {invalidLevel!r} in {logger}.emit().",
  90. Failure(InvalidLogLevelError(level)),
  91. invalidLevel=level,
  92. logger=self,
  93. )
  94. return
  95. event = kwargs
  96. event.update(
  97. log_logger=self, log_level=level, log_namespace=self.namespace,
  98. log_source=self.source, log_format=format, log_time=time(),
  99. )
  100. if "log_trace" in event:
  101. event["log_trace"].append((self, self.observer))
  102. self.observer(event)
  103. def failure(self, format, failure=None, level=LogLevel.critical, **kwargs):
  104. """
  105. Log a failure and emit a traceback.
  106. For example::
  107. try:
  108. frob(knob)
  109. except Exception:
  110. log.failure("While frobbing {knob}", knob=knob)
  111. or::
  112. d = deferredFrob(knob)
  113. d.addErrback(lambda f: log.failure, "While frobbing {knob}",
  114. f, knob=knob)
  115. This method is generally meant to capture unexpected exceptions in
  116. code; an exception that is caught and handled somehow should be logged,
  117. if appropriate, via L{Logger.error} instead. If some unknown exception
  118. occurs and your code doesn't know how to handle it, as in the above
  119. example, then this method provides a means to describe the failure in
  120. nerd-speak. This is done at L{LogLevel.critical} by default, since no
  121. corrective guidance can be offered to an user/administrator, and the
  122. impact of the condition is unknown.
  123. @param format: a message format using new-style (PEP 3101) formatting.
  124. The logging event (which is a L{dict}) is used to render this
  125. format string.
  126. @param failure: a L{Failure} to log. If L{None}, a L{Failure} is
  127. created from the exception in flight.
  128. @param level: a L{LogLevel} to use.
  129. @param kwargs: additional key/value pairs to include in the event.
  130. Note that values which are later mutated may result in
  131. non-deterministic behavior from observers that schedule work for
  132. later execution.
  133. """
  134. if failure is None:
  135. failure = Failure()
  136. self.emit(level, format, log_failure=failure, **kwargs)
  137. def debug(self, format=None, **kwargs):
  138. """
  139. Emit a log event at log level L{LogLevel.debug}.
  140. @param format: a message format using new-style (PEP 3101) formatting.
  141. The logging event (which is a L{dict}) is used to render this
  142. format string.
  143. @param kwargs: additional key/value pairs to include in the event.
  144. Note that values which are later mutated may result in
  145. non-deterministic behavior from observers that schedule work for
  146. later execution.
  147. """
  148. self.emit(LogLevel.debug, format, **kwargs)
  149. def info(self, format=None, **kwargs):
  150. """
  151. Emit a log event at log level L{LogLevel.info}.
  152. @param format: a message format using new-style (PEP 3101) formatting.
  153. The logging event (which is a L{dict}) is used to render this
  154. format string.
  155. @param kwargs: additional key/value pairs to include in the event.
  156. Note that values which are later mutated may result in
  157. non-deterministic behavior from observers that schedule work for
  158. later execution.
  159. """
  160. self.emit(LogLevel.info, format, **kwargs)
  161. def warn(self, format=None, **kwargs):
  162. """
  163. Emit a log event at log level L{LogLevel.warn}.
  164. @param format: a message format using new-style (PEP 3101) formatting.
  165. The logging event (which is a L{dict}) is used to render this
  166. format string.
  167. @param kwargs: additional key/value pairs to include in the event.
  168. Note that values which are later mutated may result in
  169. non-deterministic behavior from observers that schedule work for
  170. later execution.
  171. """
  172. self.emit(LogLevel.warn, format, **kwargs)
  173. def error(self, format=None, **kwargs):
  174. """
  175. Emit a log event at log level L{LogLevel.error}.
  176. @param format: a message format using new-style (PEP 3101) formatting.
  177. The logging event (which is a L{dict}) is used to render this
  178. format string.
  179. @param kwargs: additional key/value pairs to include in the event.
  180. Note that values which are later mutated may result in
  181. non-deterministic behavior from observers that schedule work for
  182. later execution.
  183. """
  184. self.emit(LogLevel.error, format, **kwargs)
  185. def critical(self, format=None, **kwargs):
  186. """
  187. Emit a log event at log level L{LogLevel.critical}.
  188. @param format: a message format using new-style (PEP 3101) formatting.
  189. The logging event (which is a L{dict}) is used to render this
  190. format string.
  191. @param kwargs: additional key/value pairs to include in the event.
  192. Note that values which are later mutated may result in
  193. non-deterministic behavior from observers that schedule work for
  194. later execution.
  195. """
  196. self.emit(LogLevel.critical, format, **kwargs)
  197. _log = Logger()
  198. _loggerFor = lambda obj:_log.__get__(obj, obj.__class__)