Skip to content

Commit 195d8db

Browse files
lXXXwfacebook-github-bot
authored andcommitted
Count and sort PIDs
Summary: ## This Diff Implements a function to group and sort the events based on PIDs so the user can see the top PIDs which triggered the most events. ## Context `eden fam read -p /path/to/output/file` is a command to parse the output file of FAM into a summary report. Reviewed By: jdelliot Differential Revision: D69951071 fbshipit-source-id: 14e18a289360c71dec09f414116e75b61e27c8a7
1 parent 112d483 commit 195d8db

File tree

1 file changed

+77
-3
lines changed

1 file changed

+77
-3
lines changed

eden/fs/cli_rs/edenfs-commands/src/file_access_monitor.rs

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* GNU General Public License version 2.
66
*/
77

8+
use std::cmp::Reverse;
9+
use std::collections::HashMap;
810
use std::fmt::Debug;
911
use std::fs::File as FsFile;
1012
use std::io::BufRead;
@@ -195,6 +197,24 @@ fn parse_events<R: BufRead>(reader: R) -> Result<Vec<Event>> {
195197
Ok(objects)
196198
}
197199

200+
fn sort_pids(events: &[Event]) -> Vec<(u64, u64, u64)> {
201+
// Count the number of events with the same PID
202+
let mut pid_counts: HashMap<u64, (u64, u64)> = HashMap::new(); // pid -> (counter, ppid)
203+
for event in events {
204+
let process = &event.process;
205+
let count = pid_counts.entry(process.pid).or_insert((0, process.ppid));
206+
count.0 += 1;
207+
}
208+
209+
// Sort the results so we can find the top k
210+
let mut sorted_pids: Vec<(u64, u64, u64)> = pid_counts
211+
.into_iter()
212+
.map(|(pid, (count, ppid))| (pid, count, ppid))
213+
.collect();
214+
sorted_pids.sort_by_key(|(_, count, _)| Reverse(*count));
215+
sorted_pids
216+
}
217+
198218
#[async_trait]
199219
impl crate::Subcommand for ReadCmd {
200220
async fn run(&self) -> Result<ExitCode> {
@@ -203,13 +223,26 @@ impl crate::Subcommand for ReadCmd {
203223
let file = FsFile::open(path)?;
204224
let reader = BufReader::new(file);
205225

206-
let objects = parse_events(reader)?;
226+
let events = parse_events(reader)?;
207227

208228
if self.verbose {
209-
println!("Parsed {} objects", objects.len());
210-
println!("{:#?}", objects);
229+
println!("Parsed {} objects", events.len());
230+
println!("{:#?}", events);
211231
}
212232

233+
let sorted_pids = sort_pids(&events);
234+
235+
let slice = if self.count == 0 {
236+
&sorted_pids
237+
} else {
238+
&sorted_pids[..self.count.min(sorted_pids.len())]
239+
};
240+
241+
// Print the top results
242+
println!("{:<6} | {:<7} | {}", "PID", "PPID", "Counts");
243+
for (pid, count, ppid) in slice {
244+
println!("{:<6} | {:<7} | {}", pid, ppid, count);
245+
}
213246
Ok(0)
214247
}
215248
}
@@ -337,4 +370,45 @@ mod tests {
337370
assert!(parsed.is_ok());
338371
assert_eq!(parsed.unwrap().len(), 1);
339372
}
373+
374+
#[test]
375+
fn test_sort_pids() {
376+
fn make_event(pid: u64, ppid: u64) -> Event {
377+
Event {
378+
event_type: "NOTIFY_OPEN".to_string(),
379+
file: File {
380+
path: "what".to_string(),
381+
},
382+
process: Process {
383+
ancestors: vec![],
384+
args: vec![],
385+
command: "what".to_string(),
386+
pid,
387+
ppid,
388+
uid: 67890,
389+
},
390+
event_timestamp: 1740024705,
391+
}
392+
}
393+
394+
let events = vec![
395+
make_event(66778, 22309),
396+
make_event(980066, 11759),
397+
make_event(1, 2),
398+
make_event(1, 2),
399+
make_event(980066, 11759),
400+
make_event(980066, 11759),
401+
make_event(66778, 22309),
402+
make_event(980066, 11759),
403+
make_event(1, 2),
404+
make_event(980066, 11759),
405+
make_event(1, 2),
406+
];
407+
408+
let sorted_pids = sort_pids(&events);
409+
assert_eq!(sorted_pids.len(), 3);
410+
assert_eq!(sorted_pids[0].0, 980066);
411+
assert_eq!(sorted_pids[1].0, 1);
412+
assert_eq!(sorted_pids[2].0, 66778);
413+
}
340414
}

0 commit comments

Comments
 (0)