8. def trace_calls(self, frame, event, arg): co = frame.f_code
filename = co.co_filename if filename in (__file__,): # Ignore
ourself return self._send_notice(frame, event, arg) return
self.trace_calls
9. def _send_notice(self, frame, event, arg): co = frame.f_code
func_name = co.co_name line_no = frame.f_lineno filename =
os.path.abspath(co.co_filename) for d in IGNORE_DIRS: if
filename.startswith(d): return #
10. # interesting_locals = { n: v for n, v in
frame.f_locals.items() if (not inspect.ismodule(v) and not
inspect.isfunction(v) and not inspect.ismethod(v) and (n[:2] !=
'__' and n[-2:] != '__')) } #
12. $ smiley help usage: smiley [--version] [-v] [--log-file
LOG_FILE] [-q] [-h] [--debug] smiley spies on your apps as they run
optional arguments: --version show program's version number and
exit -v, --verbose Increase verbosity of output. --log-file
LOG_FILE Specify a file to log output. -q, --quiet suppress output
except warnings -h, --help show this help message and exit --debug
show tracebacks on errors Commands: complete print bash completion
command help print detailed help for another command monitor Listen
for running programs and show their progress. run Run another
program with monitoring enabled.
13. $ smiley help run usage: smiley run [-h] [--socket SOCKET]
command [command ...] Run another program with monitoring enabled.
positional arguments: command the command to spy on optional
arguments: -h, --help show this help message and exit --socket
SOCKET URL for the socket where the listener will be
(tcp://127.0.0.1:5556)
14. $ smiley help monitor usage: smiley monitor [-h] [--socket
SOCKET] Listen for running programs and show their progress.
optional arguments: -h, --help show this help message and exit
--socket SOCKET URL for the socket where to monitor on
(tcp://127.0.0.1:5556)
15. def _process_message(self, msg): print 'MESSAGE:', msg
msg_type, msg_payload = msg if msg_type == 'start_run': print
(Starting new run:', msg_payload.get(command_line')) elif msg_type
== 'end_run': print 'Finished run' else: line =
linecache.getline(msg_payload['filename'],
msg_payload['line_no']).rstrip() if msg_type == 'return': print
'%s:%4s: return>>> %s' % ( msg_payload['filename'],
msg_payload[line_no'], msg_payload['arg']) else: print '%s:%4s: %s'
% ( msg_payload['filename'], msg_payload[line_no'], line) if
msg_payload.get('locals'): for n, v in
sorted(msg_payload['locals'].items()): print '%s %s = %s' % ( ' ' *
len(msg_payload['filename']), n, v, ) print
16. def gen(m): for i in xrange(m): yield i def c(input): print
'input =', input data = list(gen(input)) print 'Leaving c()' def
b(arg): val = arg * 5 c(val) print 'Leaving b()' return val def
a(): print 'args:', sys.argv b(2) print 'Leaving a()' a()
25. Replay past runs Complex data types flickr/Chris
Marquardt
26. import json import traceback import types def
_json_special_types(obj): if isinstance(obj, types.TracebackType):
return traceback.extract_tb(obj) if isinstance(obj, type): # We
don't want to return classes return repr(obj) try: data =
dict(vars(obj)) data['__class__'] = obj.__class__.__name__
data['__module__'] = obj.__class__.__module__ except Exception as
err: data = repr(obj) return data def dumps(data): return
json.dumps(data, default=_json_special_types)
27. ?
28. class EventProcessor(object): __metaclass__ = abc.ABCMeta
@abc.abstractmethod def start_run(self, run_id, cwd, description,
start_time): """Called when a 'start_run' event is seen. """
@abc.abstractmethod def end_run(self, run_id, end_time, message,
traceback): """Called when an 'end_run' event is seen. """
@abc.abstractmethod def trace(self, run_id, event, func_name,
line_no, filename, trace_arg, local_vars, timestamp): """Called
when any other event type is seen. """
29. def get_runs(self): "Return the runs available to browse."
with transaction(self.conn) as c: c.execute( """ SELECT id, cwd,
description, start_time, end_time, error_message FROM run """ )
return c.fetchall()