summaryrefslogtreecommitdiff
path: root/eventlet/debug.py
blob: 7db7f822f8cc89fb3d795d6d37b142088520ae1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
"""The debug module contains utilities and functions for better 
debugging Eventlet-powered applications."""

import os
import sys
import linecache

__all__ = ['spew', 'unspew', 'format_hub_listeners', 'hub_listener_stacks', 
'hub_exceptions', 'tpool_exceptions']

class Spew(object):
    """
    """
    def __init__(self, trace_names=None, show_values=True):
        self.trace_names = trace_names
        self.show_values = show_values

    def __call__(self, frame, event, arg):
        if event == 'line':
            lineno = frame.f_lineno
            if '__file__' in frame.f_globals:
                filename = frame.f_globals['__file__']
                if (filename.endswith('.pyc') or
                    filename.endswith('.pyo')):
                    filename = filename[:-1]
                name = frame.f_globals['__name__']
                line = linecache.getline(filename, lineno)
            else:
                name = '[unknown]'
                try:
                    src = inspect.getsourcelines(frame)
                    line = src[lineno]
                except IOError:
                    line = 'Unknown code named [%s].  VM instruction #%d' % (
                        frame.f_code.co_name, frame.f_lasti)
            if self.trace_names is None or name in self.trace_names:
                print '%s:%s: %s' % (name, lineno, line.rstrip())
                if not self.show_values:
                    return self
                details = '\t'
                tokens = line.translate(
                    string.maketrans(' ,.()', '\0' * 5)).split('\0')
                for tok in tokens:
                    if tok in frame.f_globals:
                        details += '%s=%r ' % (tok, frame.f_globals[tok])
                    if tok in frame.f_locals:
                        details += '%s=%r ' % (tok, frame.f_locals[tok])
                if details.strip():
                    print details
        return self


def spew(trace_names=None, show_values=False):
    """Install a trace hook which writes incredibly detailed logs
    about what code is being executed to stdout.
    """
    sys.settrace(Spew(trace_names, show_values))


def unspew():
    """Remove the trace hook installed by spew.
    """
    sys.settrace(None)
    
    
def format_hub_listeners():
    """ Returns a formatted string of the current listeners on the current
    hub.  This can be useful in determining what's going on in the event system,
    especially when used in conjunction with :func:`hub_listener_stacks`.
    """
    from eventlet import hubs
    hub = hubs.get_hub()
    result = ['READERS:']
    for l in hub.get_readers():
        result.append(repr(l))
    result.append('WRITERS:')
    for l in hub.get_writers():
        result.append(repr(l))
    return os.linesep.join(result)
    
def hub_listener_stacks(state):
    """Toggles whether or not the hub records the stack when clients register 
    listeners on file descriptors.  This can be useful when trying to figure 
    out what the hub is up to at any given moment.  To inspect the stacks
    of the current listeners, call :func:`format_hub_listeners` at critical
    junctures in the application logic.
    """
    from eventlet import hubs
    hubs.get_hub().set_debug_listeners(state)
    
def hub_exceptions(state):
    """Toggles whether the hub prints exceptions that are raised from its
    timers.  This can be useful to see how greenthreads are terminating.
    """
    from eventlet import hubs
    hubs.get_hub().set_timer_exceptions(state)
    from eventlet import greenpool
    greenpool.DEBUG = state
    
def tpool_exceptions(state):
    """Toggles whether tpool itself prints exceptions that are raised from 
    functions that are executed in it, in addition to raising them like
    it normally does."""
    from eventlet import tpool
    tpool.QUIET = not state