@@ -296,29 +296,90 @@ cdef stack_collect(ignore_profiler, thread_time, max_nframes, interval, wall_tim
296296 if task_id in thread_id_ignore_list:
297297 continue
298298
299- # Inject the task frame and replace the thread frame: this is especially handy for gevent as it allows us to
300- # replace the "hub" stack trace by the latest active greenlet, which is more interesting to show and account
301- # resources for.
302- if task_frame is not None :
303- frame = task_frame
304-
305- frames, nframes = _traceback.pyframe_to_frames(frame, max_nframes)
306-
307- event = stack_event.StackSampleEvent(
308- thread_id = thread_id,
309- thread_native_id = thread_native_id,
310- thread_name = thread_name,
311- task_id = task_id,
312- task_name = task_name,
313- nframes = nframes, frames = frames,
314- wall_time_ns = wall_time,
315- cpu_time_ns = cpu_time,
316- sampling_period = int (interval * 1e9 ),
317- )
299+ # Inject wall time for all running tasks
300+ if thread_id == nogevent.main_thread_id:
301+ main_thread_is_a_task = False
302+
303+ for task_id, task_name, task_frame in _task.list_tasks():
304+ if task_id == compat.main_thread.ident:
305+ main_thread_is_a_task = True
306+
307+ # task_frame is None, so use the thread frames list here
308+ frames, nframes = _traceback.pyframe_to_frames(frame, max_nframes)
309+
310+ event = stack_event.StackSampleEvent(
311+ thread_id = thread_id,
312+ thread_native_id = thread_native_id,
313+ thread_name = thread_name,
314+ task_id = task_id,
315+ task_name = task_name,
316+ nframes = nframes, frames = frames,
317+ wall_time_ns = wall_time,
318+ cpu_time_ns = cpu_time,
319+ sampling_period = int (interval * 1e9 ),
320+ )
321+
322+ # FIXME: we only trace spans per thread, so we assign the span to the main thread for now
323+ # we'd need to leverage the greenlet tracer to also store the active span
324+ event.set_trace_info(span, collect_endpoint)
325+ else :
326+ frames, nframes = _traceback.pyframe_to_frames(task_frame, max_nframes)
327+
328+ event = stack_event.StackSampleEvent(
329+ thread_id = thread_id,
330+ thread_native_id = thread_native_id,
331+ thread_name = thread_name,
332+ task_id = task_id,
333+ task_name = task_name,
334+ nframes = nframes, frames = frames,
335+ wall_time_ns = wall_time,
336+ # we don't have CPU time per task
337+ sampling_period = int (interval * 1e9 ),
338+ )
339+
340+ stack_events.append(event)
341+
342+ if not main_thread_is_a_task:
343+ frames, nframes = _traceback.pyframe_to_frames(frame, max_nframes)
344+
345+ event = stack_event.StackSampleEvent(
346+ thread_id = thread_id,
347+ thread_native_id = thread_native_id,
348+ thread_name = thread_name,
349+ nframes = nframes,
350+ frames = frames,
351+ wall_time_ns = wall_time,
352+ cpu_time_ns = cpu_time,
353+ sampling_period = int (interval * 1e9 ),
354+ )
355+
356+ event.set_trace_info(span, collect_endpoint)
357+
358+ stack_events.append(event)
359+ else :
360+ # Inject the task frame and replace the thread frame: this is especially handy for gevent as it allows us to
361+ # replace the "hub" stack trace by the latest active greenlet, which is more interesting to show and account
362+ # resources for.
363+ if task_frame is not None :
364+ frame = task_frame
365+
366+ frames, nframes = _traceback.pyframe_to_frames(frame, max_nframes)
367+
368+ event = stack_event.StackSampleEvent(
369+ thread_id = thread_id,
370+ thread_native_id = thread_native_id,
371+ thread_name = thread_name,
372+ task_id = task_id,
373+ task_name = task_name,
374+ nframes = nframes, frames = frames,
375+ wall_time_ns = wall_time,
376+ cpu_time_ns = cpu_time,
377+ sampling_period = int (interval * 1e9 ),
378+ )
318379
319- event.set_trace_info(span, collect_endpoint)
380+ event.set_trace_info(span, collect_endpoint)
320381
321- stack_events.append(event)
382+ stack_events.append(event)
322383
323384 if exception is not None :
324385 exc_type, exc_traceback = exception
0 commit comments