Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: 350 provide estimations related to memory #351

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 82 additions & 3 deletions cloud-scanner-cli/src/aws_inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl AwsInventory {
let location = UsageLocation::from(self.aws_region.as_str());

// Just to display statistics
let cpu_info_timer = Instant::now();
let cpu_ram_info_timer = Instant::now();

let mut inventory: Vec<CloudResource> = Vec::new();
for instance in instances {
Expand All @@ -106,16 +106,24 @@ impl AwsInventory {
.context("Cannot get CPU load of instance")
.unwrap();

let ramload = self
.clone()
.get_average_ram(&instance_id)
.await
.context("Cannot get RAM load of instance")
.unwrap();

let usage: InstanceUsage = InstanceUsage {
average_cpu_load: cpuload,
average_ram_load: ramload,
usage_duration_seconds: 300,
};

let cloud_resource_tags = Self::cloud_resource_tags_from_aws_tags(instance.tags());

info!(
"Total time spend querying CPU load of instances: {:?}",
cpu_info_timer.elapsed()
"Total time spend querying CPU & RAM load of instances: {:?}",
cpu_ram_info_timer.elapsed()
);

let inst = CloudResource {
Expand Down Expand Up @@ -288,6 +296,77 @@ impl AwsInventory {

Ok(resources)
}

/// Returns average RAM load of a given instance.
///
async fn get_average_ram(self, instance_id: &str) -> Result<f64> {
let res = self
.get_average_ram_usage_of_last_10_minutes(instance_id)
.await
.with_context(|| {
format!(
"Cannot retrieve average RAM load of instance: {}",
instance_id
)
})?;
if let Some(points) = res.datapoints {
if !points.is_empty() {
debug!("Averaging ram load data point: {:#?}", points);
let mut sum: f64 = 0.0;
for x in &points {
sum += x.average().unwrap();
}
let avg = sum / points.len() as f64;
return Ok(avg);
}
}
warn!(
"Unable to get RAM load of instance {}, it is likely stopped, using 0 as load",
instance_id
);
Ok(0 as f64)
}

/// Returns the instance RAM utilization usage on the last 10 minutes
async fn get_average_ram_usage_of_last_10_minutes(
self,
instance_id: &str,
) -> Result<GetMetricStatisticsOutput, aws_sdk_cloudwatch::Error> {
// We want statistics about the last 10 minutes using 5min sample
let measure_duration = Duration::minutes(10);
let sample_period_seconds = 300; // 5*60 (the default granularity of cloudwatch standard CPU metris)
let now: chrono::DateTime<Utc> = Utc::now();
let start_time: chrono::DateTime<Utc> = now - measure_duration;

let ram_metric_name = String::from("MemoryUtilization");
let ec2_namespace = "AWS/EC2";

let dimensions = vec![Dimension::builder()
.name("InstanceId")
.value(instance_id)
.build()];

let end_time_aws: aws_sdk_cloudwatch::primitives::DateTime =
aws_sdk_cloudwatch::primitives::DateTime::from_secs(now.timestamp());
let start_time_aws: aws_sdk_cloudwatch::primitives::DateTime =
aws_sdk_cloudwatch::primitives::DateTime::from_secs(start_time.timestamp());

let resp: GetMetricStatisticsOutput = self
.cloudwatch_client
.get_metric_statistics()
.end_time(end_time_aws)
.metric_name(ram_metric_name)
.namespace(ec2_namespace)
.period(sample_period_seconds)
.set_dimensions(Some(dimensions))
.start_time(start_time_aws)
.statistics(Statistic::Average)
.unit(StandardUnit::Percent)
.send()
.await?;

Ok(resp)
}
}

#[async_trait]
Expand Down
10 changes: 9 additions & 1 deletion cloud-scanner-cli/src/boavizta_api_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ mod tests {
instance_type: "m6g.xlarge".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 100.0,
average_ram_load: 50.0,
usage_duration_seconds: 3600,
}),
},
Expand Down Expand Up @@ -359,7 +360,7 @@ mod tests {
}

#[tokio::test]
async fn returns_different_pe_impacts_for_different_cpu_load() {
async fn returns_different_pe_impacts_for_different_cpu_ram_load() {
let instance1: CloudResource = CloudResource {
provider: CloudProvider::AWS,
id: "inst-1".to_string(),
Expand All @@ -368,6 +369,7 @@ mod tests {
instance_type: "m6g.xlarge".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 100.0,
average_ram_load: 50.0,
usage_duration_seconds: 3600,
}),
},
Expand All @@ -382,6 +384,7 @@ mod tests {
instance_type: "m6g.xlarge".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 1.0,
average_ram_load: 1.0,
usage_duration_seconds: 3600,
}),
},
Expand Down Expand Up @@ -413,6 +416,7 @@ mod tests {
instance_type: "m6g.xlarge".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 100.0,
average_ram_load: 50.0,
usage_duration_seconds: 3600,
}),
},
Expand All @@ -427,6 +431,7 @@ mod tests {
instance_type: "m6g.xlarge".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 100.0,
average_ram_load: 50.0,
usage_duration_seconds: 3600,
}),
},
Expand All @@ -441,6 +446,7 @@ mod tests {
instance_type: "type-not-in-boa".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 100.0,
average_ram_load: 50.0,
usage_duration_seconds: 3600,
}),
},
Expand Down Expand Up @@ -481,6 +487,7 @@ mod tests {
instance_type: "m6g.xlarge".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 100.0,
average_ram_load: 50.0,
usage_duration_seconds: 3600,
}),
},
Expand Down Expand Up @@ -527,6 +534,7 @@ mod tests {
instance_type: "m6g.xlarge".to_string(),
usage: Some(InstanceUsage {
average_cpu_load: 100.0,
average_ram_load: 50.0,
usage_duration_seconds: 3600,
}),
},
Expand Down
1 change: 1 addition & 0 deletions cloud-scanner-cli/src/cloud_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub enum ResourceDetails {
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct InstanceUsage {
pub average_cpu_load: f64,
pub average_ram_load: f64,
pub usage_duration_seconds: u32,
}

Expand Down