@@ -98,8 +98,13 @@ def _get_function_mapping(o):
98
98
# the module and the function's name is '__call__'. The first arg is what's important
99
99
# (the instance)
100
100
if hasattr (o , '__call__' ):
101
- #print "got mm %s" % o
102
- return (o .__call__ , o .__call__ )
101
+ # print "got mm %s" % o
102
+ try :
103
+ # return (o.__call__.im_func.func_code, o.__call__)
104
+ return (o .__call__ , o .__call__ )
105
+ except :
106
+ # print o
107
+ return (None , None )
103
108
return None
104
109
105
110
@@ -111,11 +116,17 @@ def _get_functions(self, functions, depths):
111
116
'''
112
117
self .functions = {}
113
118
self .depths = {}
119
+ functions = set (functions ) | set (depths .keys ())
114
120
for f in functions :
115
121
ident , info_obj = _get_function_mapping (f )
116
122
self .functions [ident ] = info_obj
117
123
if f in depths :
118
124
self .depths [ident ] = depths [f ]
125
+ # self.count = 0
126
+ # self.skipped = 0
127
+ self .min_depth = sys .maxint
128
+ # self.counts = {}
129
+ self .no_trace = set ()
119
130
120
131
def __init__ (self , functions , formatter = None , depths = None ):
121
132
self .formatter = formatter or Formatter ()
@@ -128,7 +139,9 @@ def _get_id(self, frame):
128
139
'''
129
140
Given a frame, figure out what function/method is being called.
130
141
'''
142
+
131
143
f = frame .f_code
144
+ # self.counts[f] = self.counts.get(f, 0) + 1
132
145
if f in self .functions :
133
146
return f # if it's in the functions dict, we know it's correct
134
147
else :
@@ -166,8 +179,12 @@ def _method_or_function_call(self, frame, ident):
166
179
self .trace_in (_name (f ), [], args .locals )
167
180
168
181
def tracefunc (self , frame , event , arg ):
182
+ # self.counts[event] = self.counts.get(event, 0) + 1
169
183
try :
170
- if event == 'call' :
184
+ if event == 'call' and frame .f_code not in self .no_trace :
185
+ # return
186
+ # f = frame.f_code
187
+ # ident = f if f in self.functions else None
171
188
ident = self ._get_id (frame )
172
189
if ident :
173
190
additional_depth = self .depths .get (ident , None )
@@ -183,6 +200,13 @@ def tracefunc(self, frame, event, arg):
183
200
if self .level <= min_depth_limit :
184
201
self .tracedframes .append ((frame .f_back , min_depth_limit ,
185
202
self .level < min_depth_limit ))
203
+ if min_depth_limit < self .min_depth :
204
+ self .min_depth = min_depth_limit
205
+ else :
206
+ self .no_trace .add (frame .f_code )
207
+ if self .level >= self .min_depth :
208
+ # print "cut off! %s:%s" % (frame.f_code.co_filename, frame.f_lineno)
209
+ return None
186
210
187
211
elif event == 'return' :
188
212
# print frame.f_code
@@ -193,7 +217,10 @@ def tracefunc(self, frame, event, arg):
193
217
if self .tracedframes [- 1 ][2 ]:
194
218
# self.trace_out("%s: %s" % (self._get_id(frame), arg))
195
219
self .trace_out (arg )
196
- self .tracedframes .pop ()
220
+ _x , min_depth_limit , _y = self .tracedframes .pop ()
221
+ if self .min_depth == min_depth_limit :
222
+ # recalculate min depth
223
+ self .min_depth = self ._min_depths ()
197
224
198
225
elif event == 'exception' :
199
226
if self .tracedframes and self .tracedframes [- 1 ][0 ] is frame .f_back :
@@ -205,14 +232,22 @@ def tracefunc(self, frame, event, arg):
205
232
if self .tracedframes [- 1 ][2 ]:
206
233
# self.trace_out("%s: %s" % (self._get_id(frame), arg))
207
234
self .trace_out (arg [0 ], exception = True )
208
- self .tracedframes .pop ()
235
+ _x , min_depth_limit , _y = self .tracedframes .pop ()
236
+ if self .min_depth == min_depth_limit :
237
+ # recalculate min depth
238
+ self .min_depth = self ._min_depths ()
239
+
209
240
except :
210
- pass # just swallow errors to avoid interference with traced processes
211
- # raise # for debugging
241
+ # pass # just swallow errors to avoid interference with traced processes
242
+ raise # for debugging
212
243
return self .tracefunc
213
244
214
245
def close (self ):
215
246
pass
247
+ # print "count=%s, skipped=%s" % (self.count, self.skipped)
248
+ # counts = sorted(self.counts.iteritems(), key=operator.itemgetter(1))
249
+ # counts = counts[-50:]
250
+ # print "count=%s, skipped=%s, counts=%s" % (self.count, self.skipped, counts)
216
251
217
252
218
253
class StdoutTracer (Tracer ):
@@ -228,6 +263,11 @@ def trace_out(self, r, exception=False):
228
263
print self .formatter .format_output (self .level - 1 , r , exception )
229
264
sys .stdout .flush ()
230
265
266
+ def close (self ):
267
+ # print "closing " + str(self.outputfile)
268
+ # print "count=%s, skipped=%s, counts=%s" % (self.count, self.skipped, self.counts)
269
+ pass
270
+
231
271
232
272
class PerThreadFileTracer (Tracer ):
233
273
'''Print trace to a file. To get thread safety, use a different
@@ -251,6 +291,7 @@ def trace_out(self, r, exception=False):
251
291
252
292
def close (self ):
253
293
# print "closing " + str(self.outputfile)
294
+ # print "count=%s, skipped=%s, counts=%s" % (self.count, self.skipped, self.counts)
254
295
self .outputfile .close ()
255
296
256
297
@@ -287,6 +328,18 @@ def r(x, y):
287
328
return reduce (r , inspect .getmembers (o , callable ), [])
288
329
289
330
331
+ def add_all_at_depth (dct , module , lvl ):
332
+ '''takes a depth dict, module, and level, and adds all the functions
333
+ in the module to the depth dict at the given level.
334
+
335
+ Returns: the dict with new values
336
+ '''
337
+ fns = all (module )
338
+ for f in fns :
339
+ dct [f ] = lvl
340
+ return dct
341
+
342
+
290
343
@contextmanager
291
344
def trace_on (objs = None , tracer = None ):
292
345
tracer = tracer or StdoutTracer (objs )
0 commit comments