1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
#[macro_use] extern crate quick_error;
extern crate rustc_serialize;
extern crate libc;
extern crate num_cpus;
use std::time::{SystemTime, Instant, Duration};
use std::collections::{VecDeque, HashMap};
mod meter;
mod scan;
mod error;
mod report;
pub use error::Error;
pub use report::ThreadReportIter;
pub type Pid = u32;
struct ThreadInfo {
user_time: u64,
system_time: u64,
child_user_time: u64,
child_system_time: u64,
}
struct Snapshot {
timestamp: SystemTime,
instant: Instant,
/// System uptime in centisecs
uptime: u64,
/// System idle time in centisecs
idle_time: u64,
process: ThreadInfo,
memory_rss: u64,
memory_virtual: u64,
memory_virtual_peak: u64,
memory_swap: u64,
read_bytes: u64,
write_bytes: u64,
read_ops: u64,
write_ops: u64,
read_disk_bytes: u64,
write_disk_bytes: u64,
write_cancelled_bytes: u64,
threads: HashMap<Pid, ThreadInfo>,
}
/// CPU usage of a single thread
pub struct ThreadUsage {
/// Thread's own CPU usage. 100% is a single core
pub cpu_usage: f32,
/// Thread's CPU usage with its awaited children. 100% is a single core
pub cpu_usage_with_children: f32,
}
pub struct ThreadIterator;
/// Report returned by `Meter::report`
#[derive(Debug, RustcEncodable)]
pub struct Report {
/// Timestamp
pub timestamp_ms: u64,
/// The interval time this data has averaged over in milliseconds
pub duration_ms: u64,
/// Uptime of a process (a number of seconds since self-meter has started)
pub uptime: u64,
/// The uptime of the system
///
/// Note this value can be smaller than `uptime` because this value doesn't
/// include time when system was sleeping
pub system_uptime: u64,
/// Whole system CPU usage. 100% is all cores
pub global_cpu_usage: f32,
/// Process' own CPU usage. 100% is a single core
pub process_cpu_usage: f32,
/// Process' CPU usage with its awaited children. 100% is a single core
pub gross_cpu_usage: f32,
/// Process' memory usage
pub memory_rss: u64,
/// Process' virtual memory usage
pub memory_virtual: u64,
/// Process' swap usage
pub memory_swap: u64,
/// Process' peak memory usage (not precise)
pub memory_rss_peak: u64,
/// Process' peak virtual memory usage (tracked by OS)
pub memory_virtual_peak: u64,
/// Process' swap usage (not precise)
pub memory_swap_peak: u64,
/// Bytes read per second from block-backed filesystems
pub disk_read: f32,
/// Bytes written per second from block-backed filesystems
pub disk_write: f32,
/// Bytes per second of cancelled writes (i.e. removed temporary files)
pub disk_cancelled: f32,
/// Bytes read per second (total)
pub io_read: f32,
/// Bytes written per second (total)
pub io_write: f32,
/// Read operations (syscalls) per second (total)
pub io_read_ops: f32,
/// Write operations (syscalls) per second (total)
pub io_write_ops: f32,
}
/// Report of CPU usage by single thread
#[derive(Debug, RustcEncodable)]
pub struct ThreadReport {
/// Threads' own CPU usage. 100% is a single core
pub cpu_usage: f32,
/// Threads' own CPU usage in kernel space. 100% is a single core
pub system_cpu: f32,
/// Threads' own CPU usage in user space. 100% is a single core
pub user_cpu: f32,
}
/// The main structure that makes mesurements and reports values
///
/// Create it with `new()` then add threads that you want to track in a thread
/// breakdown information with `meter.track_thread()` and
/// `meter.untrack_thread()`.
///
/// Then add `meter.scan()` with a timer to scan the process info. It's
/// recommended to call it on the interval of one second.
///
/// Method `report()` may be used to get structure with stats. `report_json()`
/// can return a `rustc_serialize::Json` and `report_json_str()` returns that
/// serialized.
///
/// Note that the structure returned with `report()` can be changed when we
/// bump **major version** of the library. And while `report_json()` and
/// `report_json_str()` will never break the type system, their format will
/// always reflect that of `report()` call.
///
/// We don't track all the threads separately because thread ids are useless
/// without names, and we can fine-tune performance in the case we have known
/// number of threads. Obviously, process-wide info accounts all the threads.
pub struct Meter {
#[allow(dead_code)]
scan_interval: Duration,
num_cpus: usize,
num_snapshots: usize,
start_time: SystemTime,
snapshots: VecDeque<Snapshot>,
thread_names: HashMap<Pid, String>,
/// This is a buffer for reading some text data from /proc/anything.
/// We use it to avoid memory allocations. This makes code a little bit
/// more complex, but we want to avoid overhead as much as possible
text_buf: String,
/// This is a smaller buffer for formatting paths, similar to `text_buf`
path_buf: String,
memory_rss_peak: u64,
memory_swap_peak: u64,
}