1- use std:: mem;
2- use std:: time:: { SystemTime , UNIX_EPOCH } ;
31use blazesym:: symbolize;
42use nix:: sys:: sysinfo;
3+ use std:: mem;
4+ use std:: time:: { SystemTime , UNIX_EPOCH } ;
55
66pub const MAX_STACK_DEPTH : usize = 128 ;
77pub const TASK_COMM_LEN : usize = 16 ;
@@ -35,7 +35,7 @@ impl EventHandler {
3535 pub fn new ( format : OutputFormat ) -> Self {
3636 // Get system uptime to calculate boot time
3737 let boot_time_ns = Self :: get_boot_time_ns ( ) ;
38-
38+
3939 Self {
4040 symbolizer : symbolize:: Symbolizer :: new ( ) ,
4141 format,
@@ -49,11 +49,11 @@ impl EventHandler {
4949 . duration_since ( UNIX_EPOCH )
5050 . expect ( "System time before Unix epoch" ) ;
5151 let now_ns = now. as_nanos ( ) as u64 ;
52-
52+
5353 // Get system uptime in nanoseconds
5454 let info = sysinfo:: sysinfo ( ) . expect ( "Failed to get sysinfo" ) ;
5555 let uptime_ns = ( info. uptime ( ) . as_secs_f64 ( ) * 1_000_000_000.0 ) as u64 ;
56-
56+
5757 // Boot time = current time - uptime
5858 now_ns - uptime_ns
5959 }
@@ -104,8 +104,10 @@ impl EventHandler {
104104 let unix_timestamp_ns = event. timestamp + self . boot_time_ns ;
105105 let timestamp_sec = unix_timestamp_ns / 1_000_000_000 ;
106106 let timestamp_nsec = unix_timestamp_ns % 1_000_000_000 ;
107- println ! ( "[{}.{:09}] COMM: {} (pid={}) @ CPU {}" ,
108- timestamp_sec, timestamp_nsec, comm, event. pid, event. cpu_id) ;
107+ println ! (
108+ "[{}.{:09}] COMM: {} (pid={}) @ CPU {}" ,
109+ timestamp_sec, timestamp_nsec, comm, event. pid, event. cpu_id
110+ ) ;
109111
110112 if event. kstack_size > 0 {
111113 println ! ( "Kernel:" ) ;
@@ -128,48 +130,43 @@ impl EventHandler {
128130
129131 fn handle_folded_extended ( & self , event : & StacktraceEvent ) {
130132 let comm = Self :: get_comm_str ( & event. comm ) ;
131- let tid = event. pid ; // For single-threaded processes, TID = PID
132-
133+
133134 let mut stack_frames = Vec :: new ( ) ;
134135
135- // Process user stack (if present)
136+ // Process kernel stack first (bottom of stack, closer to root)
137+ if event. kstack_size > 0 {
138+ let kstack = Self :: get_stack_slice ( & event. kstack , event. kstack_size ) ;
139+ let kernel_frames = symbolize_stack_to_vec ( & self . symbolizer , kstack, 0 ) ;
140+
141+ // Add kernel frames with [k] suffix (from bottom to top)
142+ for frame in kernel_frames. iter ( ) {
143+ stack_frames. push ( format ! ( "{}_[k]" , frame) ) ;
144+ }
145+ }
146+
147+ // Process user stack (on top of kernel stack)
136148 if event. ustack_size > 0 {
137149 let ustack = Self :: get_stack_slice ( & event. ustack , event. ustack_size ) ;
138150 let user_frames = symbolize_stack_to_vec ( & self . symbolizer , ustack, event. pid ) ;
139-
140- // Add user frames in reverse order (top to bottom )
141- for frame in user_frames. iter ( ) . rev ( ) {
151+
152+ // Add user frames (from bottom to top )
153+ for frame in user_frames. iter ( ) {
142154 stack_frames. push ( frame. clone ( ) ) ;
143155 }
144156 }
145157
146- // Process kernel stack (if present)
147- if event. kstack_size > 0 {
148- let kstack = Self :: get_stack_slice ( & event. kstack , event. kstack_size ) ;
149- let kernel_frames = symbolize_stack_to_vec ( & self . symbolizer , kstack, 0 ) ;
150-
151- // Add kernel frames with [k] suffix in reverse order (top to bottom)
152- for frame in kernel_frames. iter ( ) . rev ( ) {
153- stack_frames. push ( format ! ( "{}_[k]" , frame) ) ;
154- }
158+ // If no frames, skip this event
159+ if stack_frames. is_empty ( ) {
160+ return ;
155161 }
156162
157- // Format: timestamp_ns comm pid tid cpu stack1;stack2;stack3
158- // Convert kernel timestamp to Unix timestamp
159- let unix_timestamp_ns = event. timestamp + self . boot_time_ns ;
160- println ! (
161- "{} {} {} {} {} {}" ,
162- unix_timestamp_ns,
163- comm,
164- event. pid,
165- tid,
166- event. cpu_id,
167- stack_frames. join( ";" )
168- ) ;
163+ // Format for flamegraph.pl folded format:
164+ // comm;stack_frame1;stack_frame2;stack_frame3 count
165+ // The count is 1 for each sample
166+ println ! ( "{};{} 1" , comm, stack_frames. join( ";" ) ) ;
169167 }
170168}
171169
172-
173170fn print_frame (
174171 name : & str ,
175172 addr_info : Option < ( blazesym:: Addr , blazesym:: Addr , usize ) > ,
@@ -217,7 +214,11 @@ fn convert_stack_addresses(stack: &[u64]) -> Vec<blazesym::Addr> {
217214 . collect :: < Vec < _ > > ( )
218215 } else {
219216 // For same-sized types, still need to return owned data for consistency
220- stack. iter ( ) . copied ( ) . map ( |addr| addr as blazesym:: Addr ) . collect ( )
217+ stack
218+ . iter ( )
219+ . copied ( )
220+ . map ( |addr| addr as blazesym:: Addr )
221+ . collect ( )
221222 }
222223}
223224
@@ -242,26 +243,30 @@ fn get_symbolize_source(pid: u32) -> symbolize::source::Source<'static> {
242243}
243244
244245// Symbolize stack and return as vector of strings for folded format
245- fn symbolize_stack_to_vec ( symbolizer : & symbolize:: Symbolizer , stack : & [ u64 ] , pid : u32 ) -> Vec < String > {
246+ fn symbolize_stack_to_vec (
247+ symbolizer : & symbolize:: Symbolizer ,
248+ stack : & [ u64 ] ,
249+ pid : u32 ,
250+ ) -> Vec < String > {
246251 let converted = convert_stack_addresses ( stack) ;
247252 let stack_addrs = get_stack_slice ( stack, & converted) ;
248253 let src = get_symbolize_source ( pid) ;
249-
254+
250255 let syms = match symbolizer. symbolize ( & src, symbolize:: Input :: AbsAddr ( stack_addrs) ) {
251256 Ok ( syms) => syms,
252257 Err ( _) => {
253258 // Return addresses if symbolization fails
254- return stack_addrs. iter ( ) . map ( |addr| format ! ( "{:#x}" , addr) ) . collect ( ) ;
259+ return stack_addrs
260+ . iter ( )
261+ . map ( |addr| format ! ( "{:#x}" , addr) )
262+ . collect ( ) ;
255263 }
256264 } ;
257265
258266 let mut result = Vec :: new ( ) ;
259267 for ( addr, sym) in stack_addrs. iter ( ) . copied ( ) . zip ( syms) {
260268 match sym {
261- symbolize:: Symbolized :: Sym ( symbolize:: Sym {
262- name,
263- ..
264- } ) => {
269+ symbolize:: Symbolized :: Sym ( symbolize:: Sym { name, .. } ) => {
265270 result. push ( name. to_string ( ) ) ;
266271 }
267272 symbolize:: Symbolized :: Unknown ( ..) => {
@@ -306,4 +311,4 @@ fn show_stack_trace(stack: &[u64], symbolizer: &symbolize::Symbolizer, pid: u32)
306311 }
307312 }
308313 }
309- }
314+ }
0 commit comments