1mod checkpoint;
2
3use checkpoint::Checkpoint;
4use lazy_static::lazy_static;
5use std::fs::OpenOptions;
6use std::sync::Mutex;
7use std::io::Write;
8
9#[derive(Clone)]
10enum To {
11 Stderr,
12 File(String),
13}
14
15lazy_static! {
20 static ref LAST_CHECKPOINT: Mutex<Option<Checkpoint>> = Mutex::from(None);
21 static ref TO: Mutex<To> = Mutex::from(To::Stderr);
22}
23
24pub fn to_file(path: &str) {
25 let mut to = TO.lock().unwrap();
26 *to = To::File(String::from(path));
27}
28
29pub fn checkpoint(name: &str) {
30 let output = update_checkpoint(name);
31 if let Some(output) = output {
32 print(&output);
33 }
34}
35
36fn update_checkpoint(new_name: &str) -> Option<String> {
37 let mut last_checkpoint = LAST_CHECKPOINT.lock().unwrap();
38
39 let output = match &*last_checkpoint {
40 None => None,
42 Some(checkpoint) => Some(format!(
43 "{:?} from '{}' to '{}'\n",
44 checkpoint.instant.elapsed(),
45 checkpoint.name,
46 new_name,
47 )),
48 };
49
50 *last_checkpoint = Some(Checkpoint::new(new_name));
51
52 output
53}
54
55fn print(output: &str) {
56 let to;
57 {
58 to = TO.lock().unwrap().clone();
60 }
61
62 match to {
63 To::Stderr => {
64 eprint!("{}", output);
65 }
66 To::File(path) => {
67 let mut file = OpenOptions::new().create(true).append(true).open(&path).unwrap();
68 if let Err(e) = write!(file, "{}", output) {
69 eprint!("Error while writing to {}: {:?}", &path, e)
70 }
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 use std::thread::sleep;
80 use std::time::Duration;
81
82 #[test]
84 fn basic_to_file() {
85 to_file("/tmp/com.setofskills.global_duration.test-output.txt");
87 checkpoint("checkpoint 1");
88 sleep(Duration::from_millis(1000));
89 checkpoint("checkpoint 2");
90 sleep(Duration::from_millis(2000));
91 checkpoint("checkpoint 3");
92
93 }
96}