@@ -78,6 +78,7 @@ def __init__(self, *args, **kwargs):
7878 self ._string_table = StringTable ()
7979 self ._module_cache = {}
8080 self ._all_threads = set ()
81+ self ._last_replay_timestamp_us = None
8182
8283 # Thread status statistics (similar to LiveStatsCollector)
8384 self .thread_status_counts = {
@@ -97,6 +98,13 @@ def collect(self, stack_frames, timestamps_us=None):
9798 """Override to track thread status statistics before processing frames."""
9899 # Weight is number of timestamps (samples with identical stack)
99100 weight = len (timestamps_us ) if timestamps_us else 1
101+ if timestamps_us :
102+ last_timestamp_us = max (timestamps_us )
103+ if (
104+ self ._last_replay_timestamp_us is None
105+ or last_timestamp_us > self ._last_replay_timestamp_us
106+ ):
107+ self ._last_replay_timestamp_us = last_timestamp_us
100108
101109 # Increment sample count by weight
102110 self ._sample_count += weight
@@ -142,6 +150,27 @@ def set_stats(self, sample_interval_usec, duration_sec, sample_rate,
142150 "mode" : mode
143151 }
144152
153+ def set_replay_stats (self , info ):
154+ """Set the statistics that can be reconstructed during replay."""
155+ if self ._last_replay_timestamp_us is None :
156+ return
157+
158+ interval = info ["sample_interval_us" ]
159+ if interval <= 0 :
160+ return
161+ duration_us = max (
162+ interval ,
163+ self ._last_replay_timestamp_us - info ["start_time_us" ] + interval ,
164+ )
165+ self .set_stats (
166+ interval ,
167+ duration_us / 1_000_000 ,
168+ 1_000_000 / interval ,
169+ error_rate = None ,
170+ missed_samples = None ,
171+ mode = None ,
172+ )
173+
145174 def export (self , filename ):
146175 flamegraph_data = self ._convert_to_flamegraph_format ()
147176
0 commit comments