1 """The debug module contains utilities and functions for better
2 debugging Eventlet-powered applications."""
3 from __future__ import print_function
11 __all__ = ['spew', 'unspew', 'format_hub_listeners', 'format_hub_timers',
12 'hub_listener_stacks', 'hub_exceptions', 'tpool_exceptions',
13 'hub_prevent_multiple_readers', 'hub_timer_stacks',
14 'hub_blocking_detection']
16 _token_splitter = re.compile('\W+')
21 def __init__(self, trace_names=None, show_values=True):
22 self.trace_names = trace_names
23 self.show_values = show_values
25 def __call__(self, frame, event, arg):
27 lineno = frame.f_lineno
28 if '__file__' in frame.f_globals:
29 filename = frame.f_globals['__file__']
30 if (filename.endswith('.pyc') or
31 filename.endswith('.pyo')):
32 filename = filename[:-1]
33 name = frame.f_globals['__name__']
34 line = linecache.getline(filename, lineno)
38 src = inspect.getsourcelines(frame)
41 line = 'Unknown code named [%s]. VM instruction #%d' % (
42 frame.f_code.co_name, frame.f_lasti)
43 if self.trace_names is None or name in self.trace_names:
44 print('%s:%s: %s' % (name, lineno, line.rstrip()))
45 if not self.show_values:
48 tokens = _token_splitter.split(line)
50 if tok in frame.f_globals:
51 details.append('%s=%r' % (tok, frame.f_globals[tok]))
52 if tok in frame.f_locals:
53 details.append('%s=%r' % (tok, frame.f_locals[tok]))
55 print("\t%s" % ' '.join(details))
59 def spew(trace_names=None, show_values=False):
60 """Install a trace hook which writes incredibly detailed logs
61 about what code is being executed to stdout.
63 sys.settrace(Spew(trace_names, show_values))
67 """Remove the trace hook installed by spew.
72 def format_hub_listeners():
73 """ Returns a formatted string of the current listeners on the current
74 hub. This can be useful in determining what's going on in the event system,
75 especially when used in conjunction with :func:`hub_listener_stacks`.
77 from eventlet import hubs
80 for l in hub.get_readers():
81 result.append(repr(l))
82 result.append('WRITERS:')
83 for l in hub.get_writers():
84 result.append(repr(l))
85 return os.linesep.join(result)
88 def format_hub_timers():
89 """ Returns a formatted string of the current timers on the current
90 hub. This can be useful in determining what's going on in the event system,
91 especially when used in conjunction with :func:`hub_timer_stacks`.
93 from eventlet import hubs
97 result.append(repr(l))
98 return os.linesep.join(result)
101 def hub_listener_stacks(state=False):
102 """Toggles whether or not the hub records the stack when clients register
103 listeners on file descriptors. This can be useful when trying to figure
104 out what the hub is up to at any given moment. To inspect the stacks
105 of the current listeners, call :func:`format_hub_listeners` at critical
106 junctures in the application logic.
108 from eventlet import hubs
109 hubs.get_hub().set_debug_listeners(state)
112 def hub_timer_stacks(state=False):
113 """Toggles whether or not the hub records the stack when timers are set.
114 To inspect the stacks of the current timers, call :func:`format_hub_timers`
115 at critical junctures in the application logic.
117 from eventlet.hubs import timer
118 timer._g_debug = state
121 def hub_prevent_multiple_readers(state=True):
122 """Toggle prevention of multiple greenlets reading from a socket
124 When multiple greenlets read from the same socket it is often hard
125 to predict which greenlet will receive what data. To achieve
126 resource sharing consider using ``eventlet.pools.Pool`` instead.
128 But if you really know what you are doing you can change the state
129 to ``False`` to stop the hub from protecting against this mistake.
131 from eventlet.hubs import hub
132 hub.g_prevent_multiple_readers = state
135 def hub_exceptions(state=True):
136 """Toggles whether the hub prints exceptions that are raised from its
137 timers. This can be useful to see how greenthreads are terminating.
139 from eventlet import hubs
140 hubs.get_hub().set_timer_exceptions(state)
141 from eventlet import greenpool
142 greenpool.DEBUG = state
145 def tpool_exceptions(state=False):
146 """Toggles whether tpool itself prints exceptions that are raised from
147 functions that are executed in it, in addition to raising them like
149 from eventlet import tpool
150 tpool.QUIET = not state
153 def hub_blocking_detection(state=False, resolution=1):
154 """Toggles whether Eventlet makes an effort to detect blocking
155 behavior in an application.
157 It does this by telling the kernel to raise a SIGALARM after a
158 short timeout, and clearing the timeout every time the hub
159 greenlet is resumed. Therefore, any code that runs for a long
160 time without yielding to the hub will get interrupted by the
161 blocking detector (don't use it in production!).
163 The *resolution* argument governs how long the SIGALARM timeout
164 waits in seconds. The implementation uses :func:`signal.setitimer`
165 and can be specified as a floating-point value.
166 The shorter the resolution, the greater the chance of false
169 from eventlet import hubs
170 assert resolution > 0
171 hubs.get_hub().debug_blocking = state
172 hubs.get_hub().debug_blocking_resolution = resolution
174 hubs.get_hub().block_detect_post()