diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28488e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +target +Cargo.lock +.DS_Store +._.DS_Store +.VSCodeCounter diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..939eb9a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "be-technical-interview-rust" +version = "0.1.0" +edition = "2021" + +[dependencies] +regex = "1.10.4" +chrono = "0.4" diff --git a/Home-Task_exercise_interview_Rust.pdf b/Home-Task_exercise_interview_Rust.pdf new file mode 100644 index 0000000..3ceb90a Binary files /dev/null and b/Home-Task_exercise_interview_Rust.pdf differ diff --git a/README.md b/README.md index 0ca1e28..76b6c56 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,15 @@ -# be-technical-interview-rust +# Backend internal interview (rust) -Backend internal interview (Rust) \ No newline at end of file +A **Refactor metric-consumer** task + +[Home Task exercise description](Home-Task_exercise_interview_Rust.pdf) + +There are several branches developed as proposal: + +- [Basic fixed one](basic-fixed) + > A basic code review, fixed with minor and essential changes to work as expected. + > Tests are included for verification. + +- [Improve one](improved) + +- [Multiple input one](multi-input) diff --git a/input.txt b/input.txt new file mode 100644 index 0000000..171c69e --- /dev/null +++ b/input.txt @@ -0,0 +1,25 @@ +1650973075 cpu 47 +1650973087 cpu 47 +1650973099 mem 737917 +1650973111 cpu 50 +1650973123 cpu 49 +1650973135 cpu 49 +1650973147 mem 1761992 +1650973159 cpu 49 +1650973171 mem 1858502 +1650973183 cpu 51 +1650973195 cpu 55 +1650973207 mem 1076203 +1650973219 cpu 60 +1650973231 mem 640005 +1650973243 mem 324911 +1650973255 mem 1024 +1650973267 cpu 56 +1650973279 cpu 58 +1650973291 mem 1024 +1650973303 mem 1024 +1650973315 mem 1024 +1650973327 mem 1024 +1650973339 cpu 49 +1650973351 mem 1024 +1650973363 cpu 49 \ No newline at end of file diff --git a/output_expected.txt b/output_expected.txt new file mode 100644 index 0000000..00e2026 --- /dev/null +++ b/output_expected.txt @@ -0,0 +1,11 @@ +2022-04-26T11:37:00Z cpu 47.0 +2022-04-26T11:38:00Z cpu 48.75 +2022-04-26T11:39:00Z cpu 51.666666666666664 +2022-04-26T11:40:00Z cpu 60.0 +2022-04-26T11:41:00Z cpu 57.0 +2022-04-26T11:42:00Z cpu 49.0 +2022-04-26T11:38:00Z mem 737917.0 +2022-04-26T11:39:00Z mem 1810247.0 +2022-04-26T11:40:00Z mem 510535.75 +2022-04-26T11:41:00Z mem 1024.0 +2022-04-26T11:42:00Z mem 1024.0 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f48b5a1 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,76 @@ +use std::collections::HashMap; +use std::error::Error; +use std::fs::File; +use std::io::Read; +use std::time::{Duration, UNIX_EPOCH}; + +fn parse( + file: File, +) -> Result<HashMap<String, HashMap<std::time::SystemTime, f64>>, Box<dyn Error>> { + let mut file = file; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + + let mut metrics: HashMap<String, HashMap<std::time::SystemTime, Vec<f64>>> = HashMap::new(); + + for line in contents.lines() { + let re = regex::Regex::new(r"(\d+) (\w+) (\d+)").unwrap(); + if let Some(caps) = re.captures(line) { + let timestamp_raw = &caps[1]; + let metric_name = &caps[2]; + let metric_value_raw = &caps[3]; + + let timestamp = timestamp_raw.parse::<i64>().unwrap(); + let metric_value = metric_value_raw.parse::<f64>().unwrap(); + + if !metrics.contains_key(metric_name) { + metrics.insert(metric_name.to_string(), HashMap::new()); + } + + let minute = UNIX_EPOCH + Duration::from_secs((timestamp - (timestamp % 60)) as u64); + metrics + .get_mut(metric_name) + .unwrap() + .insert(minute, vec![metric_value]); + } else { + println!("invalid line"); + } + } + + let mut aggregated_metrics: HashMap<String, HashMap<std::time::SystemTime, f64>> = + HashMap::new(); + + for (metric_name, time_val_list) in metrics { + aggregated_metrics.insert(metric_name.clone(), HashMap::new()); + + for (time, values) in time_val_list { + let mut sum = 0.0; + for v in values.iter() { + sum += *v + } + let average = sum / values.len() as f64; + + aggregated_metrics + .get_mut(&metric_name) + .unwrap() + .insert(time, average); + } + } + + Ok(aggregated_metrics) +} + +fn main() { + let file = File::open("input.txt").expect("Unable to open file"); + let metrics = parse(file).expect("Unable to parse file"); + for (metric_name, time_val) in metrics { + for (time, value) in time_val { + println!( + "{} {:?} {:.2}", + metric_name, + chrono::DateTime::<chrono::Utc>::from(time), + value + ); + } + } +}