#[macro_use] extern crate log; extern crate env_logger; extern crate linux_perf_file_reader; #[allow(unused_imports)] macro_rules! print_if_some_child { ($format: expr, $parent: expr, $($field: tt),*) => { $(if $parent.$field.is_some() { print!($format, stringify!($field), $parent.$field.as_ref().unwrap()); })* }; } macro_rules! print_if_some { ($format: expr, $($field: tt),*) => { $(if $field.is_some() { print!($format, stringify!($field), $field.as_ref().unwrap()); })* }; } fn main() { env_logger::init(); use linux_perf_file_reader::Event; let args: Vec = std::env::args().collect(); match linux_perf_file_reader::read_perf_file( args.get(1) .expect("use with perf.data file in command line"), ) { Err(e) => { error!("Error: {}", e); for e in e.iter().skip(1) { error!("caused by: {}", e); } std::process::exit(-1); } Ok(ref perf) => { println!("Info:"); print_if_some_child!( " {}: {}\n", perf.info, hostname, os_release, tools_version, arch, cpu_description, cpu_id, total_memory ); print_if_some_child!( " {}: {:?}\n", perf.info, command_line, cpu_topology, cpu_count ); if let Some(ref event_description) = perf.info.event_descriptions { for d in event_description { println!(" event_attribute {}{:?}: {:?}", d.name, d.ids, d.attributes); } } println!("\nAttrs:"); for attr in perf.event_attributes.iter() { println!(" {:?}", attr); } println!("\nEvents:"); for event in perf.events.iter() { match event { &Event::MMap { pid, tid, addr, len, pgoff, ref filename, ref sample_id, } => { println!( " Mmap: pid: {}, tid: {}, addr: {:x}, len: {}, pgoff: {:x} - {}", pid, tid, addr, len, pgoff, filename ); print_sample_id(sample_id); } &Event::MMap2 { pid, tid, addr, len, pgoff, maj, min, ino, ino_generation, prot, flags, ref filename, ref sample_id, } => { println!( " Mmap2: pid: {}, tid: {}, addr: {:x}, len: {}, pgoff: {:x} - {}", pid, tid, addr, len, pgoff, filename ); println!( " dev: {}:{} inode: {}, inode generation: {}, prot: {}, flags: {}", maj, min, ino, ino_generation, prot, flags ); print_sample_id(sample_id); } &Event::Exit { pid, ppid, tid, ptid, time, ref sample_id, } => { println!( " Exit: pid: {}, ppid: {}, tid:{}, ptid: {}, time: {}", pid, ppid, tid, ptid, time ); print_sample_id(sample_id); } &Event::Comm { pid, tid, ref comm, ref sample_id, } => { println!(" Comm: pid: {}, tid:{}, comm: {}", pid, tid, comm); print_sample_id(sample_id); } &Event::Sample { identifier, ip, pid, tid, time, addr, id, stream_id, cpu, res, period, ref call_chain, } => { print!(" Sample:"); print_if_some!(" {}: {:x}", ip, addr); print_if_some!( " {}: {}", pid, tid, time, id, identifier, stream_id, cpu, res, period ); println!(""); if !call_chain.is_empty() { println!(" call chain: "); for addr in call_chain.iter() { println!(" {:x}", addr); } } } &Event::FinishedRound => {} &Event::Unsupported => {} } } } } } fn print_sample_id(sample_id: &linux_perf_file_reader::SampleId) { print!(" Sample:"); print_if_some_child!(" {}: {}", sample_id, pid, tid, time, id, stream_id, cpu, res, identifier); println!(""); }