linux-perf-file-reader 0.2.0

Library for parse perf.data file from Linux perf tool
Documentation
#[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<String> = 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!("");
}