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.

_logger.py 9.3KB

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