debug.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. """The debug module contains utilities and functions for better
  2. debugging Eventlet-powered applications."""
  3. import os
  4. import sys
  5. import linecache
  6. import re
  7. import inspect
  8. __all__ = ['spew', 'unspew', 'format_hub_listeners', 'format_hub_timers',
  9. 'hub_listener_stacks', 'hub_exceptions', 'tpool_exceptions',
  10. 'hub_prevent_multiple_readers', 'hub_timer_stacks',
  11. 'hub_blocking_detection']
  12. _token_splitter = re.compile('\W+')
  13. class Spew(object):
  14. """
  15. """
  16. def __init__(self, trace_names=None, show_values=True):
  17. self.trace_names = trace_names
  18. self.show_values = show_values
  19. def __call__(self, frame, event, arg):
  20. if event == 'line':
  21. lineno = frame.f_lineno
  22. if '__file__' in frame.f_globals:
  23. filename = frame.f_globals['__file__']
  24. if (filename.endswith('.pyc') or
  25. filename.endswith('.pyo')):
  26. filename = filename[:-1]
  27. name = frame.f_globals['__name__']
  28. line = linecache.getline(filename, lineno)
  29. else:
  30. name = '[unknown]'
  31. try:
  32. src = inspect.getsourcelines(frame)
  33. line = src[lineno]
  34. except IOError:
  35. line = 'Unknown code named [%s]. VM instruction #%d' % (
  36. frame.f_code.co_name, frame.f_lasti)
  37. if self.trace_names is None or name in self.trace_names:
  38. print '%s:%s: %s' % (name, lineno, line.rstrip())
  39. if not self.show_values:
  40. return self
  41. details = []
  42. tokens = _token_splitter.split(line)
  43. for tok in tokens:
  44. if tok in frame.f_globals:
  45. details.append('%s=%r' % (tok, frame.f_globals[tok]))
  46. if tok in frame.f_locals:
  47. details.append('%s=%r' % (tok, frame.f_locals[tok]))
  48. if details:
  49. print "\t%s" % ' '.join(details)
  50. return self
  51. def spew(trace_names=None, show_values=False):
  52. """Install a trace hook which writes incredibly detailed logs
  53. about what code is being executed to stdout.
  54. """
  55. sys.settrace(Spew(trace_names, show_values))
  56. def unspew():
  57. """Remove the trace hook installed by spew.
  58. """
  59. sys.settrace(None)
  60. def format_hub_listeners():
  61. """ Returns a formatted string of the current listeners on the current
  62. hub. This can be useful in determining what's going on in the event system,
  63. especially when used in conjunction with :func:`hub_listener_stacks`.
  64. """
  65. from eventlet import hubs
  66. hub = hubs.get_hub()
  67. result = ['READERS:']
  68. for l in hub.get_readers():
  69. result.append(repr(l))
  70. result.append('WRITERS:')
  71. for l in hub.get_writers():
  72. result.append(repr(l))
  73. return os.linesep.join(result)
  74. def format_hub_timers():
  75. """ Returns a formatted string of the current timers on the current
  76. hub. This can be useful in determining what's going on in the event system,
  77. especially when used in conjunction with :func:`hub_timer_stacks`.
  78. """
  79. from eventlet import hubs
  80. hub = hubs.get_hub()
  81. result = ['TIMERS:']
  82. for l in hub.timers:
  83. result.append(repr(l))
  84. return os.linesep.join(result)
  85. def hub_listener_stacks(state = False):
  86. """Toggles whether or not the hub records the stack when clients register
  87. listeners on file descriptors. This can be useful when trying to figure
  88. out what the hub is up to at any given moment. To inspect the stacks
  89. of the current listeners, call :func:`format_hub_listeners` at critical
  90. junctures in the application logic.
  91. """
  92. from eventlet import hubs
  93. hubs.get_hub().set_debug_listeners(state)
  94. def hub_timer_stacks(state = False):
  95. """Toggles whether or not the hub records the stack when timers are set.
  96. To inspect the stacks of the current timers, call :func:`format_hub_timers`
  97. at critical junctures in the application logic.
  98. """
  99. from eventlet.hubs import timer
  100. timer._g_debug = state
  101. def hub_prevent_multiple_readers(state = True):
  102. from eventlet.hubs import hub
  103. hub.g_prevent_multiple_readers = state
  104. def hub_exceptions(state = True):
  105. """Toggles whether the hub prints exceptions that are raised from its
  106. timers. This can be useful to see how greenthreads are terminating.
  107. """
  108. from eventlet import hubs
  109. hubs.get_hub().set_timer_exceptions(state)
  110. from eventlet import greenpool
  111. greenpool.DEBUG = state
  112. def tpool_exceptions(state = False):
  113. """Toggles whether tpool itself prints exceptions that are raised from
  114. functions that are executed in it, in addition to raising them like
  115. it normally does."""
  116. from eventlet import tpool
  117. tpool.QUIET = not state
  118. def hub_blocking_detection(state = False, resolution = 1):
  119. """Toggles whether Eventlet makes an effort to detect blocking
  120. behavior in an application.
  121. It does this by telling the kernel to raise a SIGALARM after a
  122. short timeout, and clearing the timeout every time the hub
  123. greenlet is resumed. Therefore, any code that runs for a long
  124. time without yielding to the hub will get interrupted by the
  125. blocking detector (don't use it in production!).
  126. The *resolution* argument governs how long the SIGALARM timeout
  127. waits in seconds. If on Python 2.6 or later, the implementation
  128. uses :func:`signal.setitimer` and can be specified as a
  129. floating-point value. On 2.5 or earlier, 1 second is the minimum.
  130. The shorter the resolution, the greater the chance of false
  131. positives.
  132. """
  133. from eventlet import hubs
  134. assert resolution > 0
  135. hubs.get_hub().debug_blocking = state
  136. hubs.get_hub().debug_blocking_resolution = resolution
  137. if(not state):
  138. hubs.get_hub().block_detect_post()