cloud_scanner_cli/
metric_exporter.rs

1//!  A module to format the results of cloud-scanner into OpenMetrics (Prometheus format) metrics
2use anyhow::{Context, Result};
3use std::sync::atomic::AtomicU64;
4
5use crate::impact_provider::CloudResourceWithImpacts;
6use prometheus_client::encoding::text::encode;
7use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue};
8use prometheus_client::metrics::family::Family;
9use prometheus_client::metrics::gauge::*;
10use prometheus_client::registry::Registry;
11
12use crate::model::{EstimatedInventory, InstanceState, ResourceDetails};
13use crate::ImpactsSummary;
14
15// Define a type representing a metric label set, i.e. a key value pair.
16#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)]
17pub struct SummaryLabels {
18    pub awsregion: String,
19    pub country: String,
20    pub cloud_scanner_version: String,
21    pub boaviztapi_version: String,
22}
23#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)]
24pub struct ResourceLabels {
25    pub awsregion: String,
26    pub country: String,
27    pub resource_type: ResourceType,
28    pub resource_id: String,
29    pub resource_tags: String,
30    pub resource_state: ResourceState,
31    pub cloud_scanner_version: String,
32    pub boaviztapi_version: String,
33}
34
35#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)]
36pub enum ResourceType {
37    BlockStorage,
38    Instance,
39    ObjectStorage,
40}
41
42#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)]
43pub enum ResourceState {
44    Running,
45    Stopped,
46    Unknown,
47}
48
49fn build_resource_labels(
50    resource: &CloudResourceWithImpacts,
51    cloud_scanner_version: &str,
52    boaviztapi_version: &str,
53) -> ResourceLabels {
54    let resource_type = match resource.clone().cloud_resource.resource_details {
55        ResourceDetails::Instance { .. } => ResourceType::Instance,
56        ResourceDetails::BlockStorage { .. } => ResourceType::BlockStorage,
57        ResourceDetails::ObjectStorage => ResourceType::ObjectStorage,
58    };
59    let resource_state = match resource.clone().cloud_resource.resource_details {
60        ResourceDetails::Instance {
61            instance_type: _,
62            usage,
63        } => match usage.unwrap().state {
64            InstanceState::Running => ResourceState::Running,
65            InstanceState::Stopped => ResourceState::Stopped,
66        },
67        _ => ResourceState::Unknown,
68    };
69
70    ResourceLabels {
71        awsregion: resource.cloud_resource.location.aws_region.clone(),
72        country: resource.cloud_resource.location.iso_country_code.clone(),
73        resource_type,
74        resource_id: resource.cloud_resource.id.clone(),
75        resource_tags: resource.cloud_resource.tags_as_metric_label_value(),
76        resource_state,
77        cloud_scanner_version: cloud_scanner_version.to_owned(),
78        boaviztapi_version: boaviztapi_version.to_owned(),
79    }
80}
81
82pub fn register_resource_metrics(
83    registry: &mut Registry,
84    resources_with_impacts: Vec<CloudResourceWithImpacts>,
85    cloud_scanner_version: &str,
86    boaviztapi_version: &str,
87) {
88    // Register metrics
89    let boavizta_resource_duration_of_use_hours =
90        Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
91    registry.register(
92        "boavizta_resource_duration_of_use_hours",
93        "Use duration considered to estimate impacts",
94        boavizta_resource_duration_of_use_hours.clone(),
95    );
96    let boavizta_resource_pe_embodied_megajoules =
97        Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
98    registry.register(
99        "boavizta_resource_pe_embodied_megajoules",
100        "Energy consumed for manufacture",
101        boavizta_resource_pe_embodied_megajoules.clone(),
102    );
103    let boavizta_resource_pe_use_megajoules =
104        Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
105    registry.register(
106        "boavizta_resource_pe_use_megajoules",
107        "Energy consumed during use",
108        boavizta_resource_pe_use_megajoules.clone(),
109    );
110    let boavizta_resource_adp_embodied_kgsbeq =
111        Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
112    registry.register(
113        "boavizta_resource_adp_embodied_kgsbeq",
114        "Abiotic resources depletion potential of embodied impacts",
115        boavizta_resource_adp_embodied_kgsbeq.clone(),
116    );
117    let boavizta_resource_adp_use_kgsbeq =
118        Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
119    registry.register(
120        "boavizta_resource_adp_use_kgsbeq",
121        "Abiotic resources depletion potential of use",
122        boavizta_resource_adp_use_kgsbeq.clone(),
123    );
124    let boavizta_resource_gwp_embodied_kgco2eq =
125        Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
126    registry.register(
127        "boavizta_resource_gwp_embodied_kgco2eq",
128        "Global Warming Potential of embodied impacts",
129        boavizta_resource_gwp_embodied_kgco2eq.clone(),
130    );
131    let boavizta_resource_gwp_use_kgco2eq =
132        Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
133    registry.register(
134        "boavizta_resource_gwp_use_kgco2eq",
135        "Global Warming Potential of use",
136        boavizta_resource_gwp_use_kgco2eq.clone(),
137    );
138
139    let boavizta_resource_cpu_load = Family::<ResourceLabels, Gauge<f64, AtomicU64>>::default();
140    registry.register(
141        "boavizta_resource_cpu_load",
142        "CPU load of instance",
143        boavizta_resource_cpu_load.clone(),
144    );
145
146    let boavizta_storage_size_gb = Family::<ResourceLabels, Gauge>::default();
147    registry.register(
148        "boavizta_storage_size_gb",
149        "Storage size in GB",
150        boavizta_storage_size_gb.clone(),
151    );
152
153    // Fill up metrics values
154    for resource in resources_with_impacts.iter() {
155        let resource_labels =
156            build_resource_labels(resource, cloud_scanner_version, boaviztapi_version);
157        let impacts = resource.impacts_values.as_ref();
158
159        // the impacts can be missing
160        if impacts.is_some() {
161            let impact_values = impacts.unwrap();
162            boavizta_resource_duration_of_use_hours
163                .get_or_create(&resource_labels)
164                .set(resource.impacts_duration_hours.into());
165            boavizta_resource_pe_use_megajoules
166                .get_or_create(&resource_labels)
167                .set(impact_values.pe_use_megajoules);
168            boavizta_resource_pe_embodied_megajoules
169                .get_or_create(&resource_labels)
170                .set(impact_values.pe_manufacture_megajoules);
171            boavizta_resource_adp_use_kgsbeq
172                .get_or_create(&resource_labels)
173                .set(impact_values.adp_use_kgsbeq);
174            boavizta_resource_adp_embodied_kgsbeq
175                .get_or_create(&resource_labels)
176                .set(impact_values.adp_manufacture_kgsbeq);
177            boavizta_resource_gwp_use_kgco2eq
178                .get_or_create(&resource_labels)
179                .set(impact_values.gwp_use_kgco2eq);
180            boavizta_resource_gwp_embodied_kgco2eq
181                .get_or_create(&resource_labels)
182                .set(impact_values.gwp_manufacture_kgco2eq);
183        }
184
185        // Export CPU usage metrics (for instances) and size metrics (for storage)
186        match &resource.cloud_resource.resource_details {
187            ResourceDetails::Instance {
188                usage: Some(instance_usage),
189                ..
190            } => {
191                let cpu_load = instance_usage.average_cpu_load;
192                boavizta_resource_cpu_load
193                    .get_or_create(&resource_labels)
194                    .set(cpu_load);
195            }
196            ResourceDetails::BlockStorage {
197                usage: Some(storage_usage),
198                ..
199            } => {
200                let size_gb = storage_usage.size_gb;
201                boavizta_storage_size_gb
202                    .get_or_create(&resource_labels)
203                    .set(size_gb as i64);
204            }
205            _ => {}
206        }
207    }
208}
209/// Returns metrics related to individual resources as String
210///
211/// - Individual resource metrics are prefixed with: `boavizta_resource_`
212pub fn get_resources_metrics(
213    resources_with_impacts: Vec<CloudResourceWithImpacts>,
214    cloud_scanner_version: &str,
215    boaviztapi_version: &str,
216) -> Result<String> {
217    let mut registry = <Registry>::default();
218    register_resource_metrics(
219        &mut registry,
220        resources_with_impacts,
221        cloud_scanner_version,
222        boaviztapi_version,
223    );
224    let mut buffer = String::new();
225    encode(&mut buffer, &registry).context("Fails to encode resources impacts into metrics")?;
226    let metrics = buffer;
227
228    Ok(metrics)
229}
230
231/// Return an ImpactsSummary as metrics in the prometheus format
232///
233/// - Summary metrics are prefixed with: `boavizta_`
234pub fn get_summary_metrics(
235    summary: &ImpactsSummary,
236    cloud_scanner_version: String,
237    boaviztapi_version: String,
238) -> Result<String> {
239    let mut registry = <Registry>::default();
240    register_summary_metrics(
241        &mut registry,
242        summary,
243        cloud_scanner_version,
244        boaviztapi_version,
245    );
246    let mut buffer = String::new();
247    encode(&mut buffer, &registry).context("Fails to encode impacts summary into metrics")?;
248    let metrics = buffer;
249    Ok(metrics)
250}
251
252/// Returns all metrics as string: both aggregated metrics (summary) as well a metrics of individual resources
253///
254/// - Summary metrics are prefixed with: `boavizta_`
255/// - Individual resource metrics are prefixed with: `boavizta_resource_`
256pub fn get_all_metrics(
257    summary: &ImpactsSummary,
258    estimated_inventory: EstimatedInventory,
259) -> Result<String> {
260    let cloud_scanner_version = estimated_inventory
261        .metadata
262        .cloud_scanner_version
263        .unwrap_or("".to_string());
264    let boaviztapi_version = estimated_inventory
265        .metadata
266        .boavizta_api_version
267        .unwrap_or("".to_string());
268
269    let mut registry = <Registry>::default();
270    register_summary_metrics(
271        &mut registry,
272        summary,
273        cloud_scanner_version.clone(),
274        boaviztapi_version.clone(),
275    );
276    register_resource_metrics(
277        &mut registry,
278        estimated_inventory.impacting_resources,
279        &cloud_scanner_version,
280        &boaviztapi_version,
281    );
282
283    let mut buffer = String::new();
284    encode(&mut buffer, &registry).context("Fails to encode impacts into metrics")?;
285    let metrics = buffer;
286
287    Ok(metrics)
288}
289
290fn register_summary_metrics(
291    registry: &mut Registry,
292    summary: &ImpactsSummary,
293    cloud_scanner_version: String,
294    boaviztapi_version: String,
295) {
296    let boavizta_number_of_resources_total = Family::<SummaryLabels, Gauge>::default();
297    // Register the metric family with the registry.
298    registry.register(
299        // With the metric name.
300        "boavizta_number_of_resources_total",
301        // And the metric help text.
302        "Number of resources detected during the inventory",
303        boavizta_number_of_resources_total.clone(),
304    );
305
306    let boavizta_number_of_resources_assessed = Family::<SummaryLabels, Gauge>::default();
307    // Register the metric family with the registry.
308    registry.register(
309        // With the metric name.
310        "boavizta_number_of_resources_assessed",
311        // And the metric help text.
312        "Number of resources that were considered in the estimation of impacts",
313        boavizta_number_of_resources_assessed.clone(),
314    );
315
316    let boavizta_duration_of_use_hours = Family::<SummaryLabels, Gauge<f64, AtomicU64>>::default();
317    // Register the metric family with the registry.
318    registry.register(
319        // With the metric name.
320        "boavizta_duration_of_use_hours",
321        // And the metric help text.
322        "Use duration considered to estimate impacts",
323        boavizta_duration_of_use_hours.clone(),
324    );
325
326    let boavizta_pe_manufacture_megajoules =
327        Family::<SummaryLabels, Gauge<f64, AtomicU64>>::default();
328    // Register the metric family with the registry.
329    registry.register(
330        // With the metric name.
331        "boavizta_pe_manufacture_megajoules",
332        // And the metric help text.
333        "Energy consumed for manufacture",
334        boavizta_pe_manufacture_megajoules.clone(),
335    );
336
337    let boavizta_pe_use_megajoules = Family::<SummaryLabels, Gauge<f64, AtomicU64>>::default();
338    // Register the metric family with the registry.
339    registry.register(
340        // With the metric name.
341        "boavizta_pe_use_megajoules",
342        // And the metric help text.
343        "Energy consumed during use",
344        boavizta_pe_use_megajoules.clone(),
345    );
346
347    let boavizta_adp_manufacture_kgsbeq = Family::<SummaryLabels, Gauge<f64, AtomicU64>>::default();
348    // Register the metric family with the registry.
349    registry.register(
350        // With the metric name.
351        "boavizta_adp_manufacture_kgsbeq",
352        // And the metric help text.
353        "Abiotic resources depletion potential of manufacture",
354        boavizta_adp_manufacture_kgsbeq.clone(),
355    );
356
357    let boavizta_adp_use_kgsbeq = Family::<SummaryLabels, Gauge<f64, AtomicU64>>::default();
358    // Register the metric family with the registry.
359    registry.register(
360        // With the metric name.
361        "boavizta_adp_use_kgsbeq",
362        // And the metric help text.
363        "Abiotic resources depletion potential of use",
364        boavizta_adp_use_kgsbeq.clone(),
365    );
366
367    let boavizta_gwp_manufacture_kgco2eq =
368        Family::<SummaryLabels, Gauge<f64, AtomicU64>>::default();
369    // Register the metric family with the registry.
370    registry.register(
371        // With the metric name.
372        "boavizta_gwp_manufacture_kgco2eq",
373        // And the metric help text.
374        "Global Warming Potential of manufacture",
375        boavizta_gwp_manufacture_kgco2eq.clone(),
376    );
377
378    let boavizta_gwp_use_kgco2eq = Family::<SummaryLabels, Gauge<f64, AtomicU64>>::default();
379    // Register the metric family with the registry.
380    registry.register(
381        // With the metric name.
382        "boavizta_gwp_use_kgco2eq",
383        // And the metric help text.
384        "Global Warming Potential of use",
385        boavizta_gwp_use_kgco2eq.clone(),
386    );
387
388    let summary_labels: SummaryLabels = SummaryLabels {
389        awsregion: summary.aws_region.to_string(),
390        country: summary.country.to_string(),
391        cloud_scanner_version,
392        boaviztapi_version,
393    };
394
395    // Set the values
396    boavizta_number_of_resources_total
397        .get_or_create(&summary_labels)
398        .set(summary.number_of_resources_total as i64);
399    boavizta_number_of_resources_assessed
400        .get_or_create(&summary_labels)
401        .set(summary.number_of_resources_assessed as i64);
402
403    boavizta_duration_of_use_hours
404        .get_or_create(&summary_labels)
405        .set(summary.duration_of_use_hours);
406
407    boavizta_pe_manufacture_megajoules
408        .get_or_create(&summary_labels)
409        .set(summary.pe_manufacture_megajoules);
410
411    boavizta_pe_use_megajoules
412        .get_or_create(&summary_labels)
413        .set(summary.pe_use_megajoules);
414
415    boavizta_adp_manufacture_kgsbeq
416        .get_or_create(&summary_labels)
417        .set(summary.adp_manufacture_kgsbeq);
418
419    boavizta_adp_use_kgsbeq
420        .get_or_create(&summary_labels)
421        .set(summary.adp_use_kgsbeq);
422
423    boavizta_gwp_manufacture_kgco2eq
424        .get_or_create(&summary_labels)
425        .set(summary.gwp_manufacture_kgco2eq);
426
427    boavizta_gwp_use_kgco2eq
428        .get_or_create(&summary_labels)
429        .set(summary.gwp_use_kgco2eq);
430}
431
432#[cfg(test)]
433mod tests {
434    use super::*;
435    use crate::impact_provider::ImpactsValues;
436    use crate::model::{
437        CloudProvider, CloudResource, CloudResourceTag, EstimationMetadata, InstanceUsage,
438        StorageUsage,
439    };
440    use crate::usage_location::UsageLocation;
441
442    #[tokio::test]
443    async fn test_get_summary_metrics() {
444        let summary: ImpactsSummary = ImpactsSummary {
445            number_of_resources_total: 5,
446            number_of_resources_assessed: 2,
447            number_of_resources_not_assessed: 3,
448            duration_of_use_hours: 1.0,
449            adp_manufacture_kgsbeq: 0.1,
450            adp_use_kgsbeq: 0.2,
451            pe_manufacture_megajoules: 0.3,
452            pe_use_megajoules: 0.4,
453            gwp_manufacture_kgco2eq: 0.5,
454            gwp_use_kgco2eq: 0.6,
455            aws_region: "eu-west-1".to_string(),
456            country: "IRL".to_string(),
457        };
458
459        let cloud_scannner_version = "4.5.6".to_string();
460        let boaviztapi_version = "v1.2.3".to_string();
461
462        let metrics =
463            get_summary_metrics(&summary, cloud_scannner_version, boaviztapi_version).unwrap();
464
465        println!("{}", metrics);
466
467        let expected = r#"# HELP boavizta_number_of_resources_total Number of resources detected during the inventory.
468# TYPE boavizta_number_of_resources_total gauge
469boavizta_number_of_resources_total{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 5
470# HELP boavizta_number_of_resources_assessed Number of resources that were considered in the estimation of impacts.
471# TYPE boavizta_number_of_resources_assessed gauge
472boavizta_number_of_resources_assessed{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 2
473# HELP boavizta_duration_of_use_hours Use duration considered to estimate impacts.
474# TYPE boavizta_duration_of_use_hours gauge
475boavizta_duration_of_use_hours{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1.0
476# HELP boavizta_pe_manufacture_megajoules Energy consumed for manufacture.
477# TYPE boavizta_pe_manufacture_megajoules gauge
478boavizta_pe_manufacture_megajoules{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.3
479# HELP boavizta_pe_use_megajoules Energy consumed during use.
480# TYPE boavizta_pe_use_megajoules gauge
481boavizta_pe_use_megajoules{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.4
482# HELP boavizta_adp_manufacture_kgsbeq Abiotic resources depletion potential of manufacture.
483# TYPE boavizta_adp_manufacture_kgsbeq gauge
484boavizta_adp_manufacture_kgsbeq{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.1
485# HELP boavizta_adp_use_kgsbeq Abiotic resources depletion potential of use.
486# TYPE boavizta_adp_use_kgsbeq gauge
487boavizta_adp_use_kgsbeq{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.2
488# HELP boavizta_gwp_manufacture_kgco2eq Global Warming Potential of manufacture.
489# TYPE boavizta_gwp_manufacture_kgco2eq gauge
490boavizta_gwp_manufacture_kgco2eq{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.5
491# HELP boavizta_gwp_use_kgco2eq Global Warming Potential of use.
492# TYPE boavizta_gwp_use_kgco2eq gauge
493boavizta_gwp_use_kgco2eq{awsregion="eu-west-1",country="IRL",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.6
494# EOF
495"#;
496
497        assert_eq!(expected, metrics);
498    }
499
500    #[tokio::test]
501    async fn test_get_all_metrics_for_instance() {
502        let tag1 = CloudResourceTag {
503            key: "tag_key_1".to_string(),
504            value: Some("tag_value_1".to_string()),
505        };
506        let tag2 = CloudResourceTag {
507            key: "tag_key_2".to_string(),
508            value: Some("tag_value_2".to_string()),
509        };
510
511        let cloud_resource: CloudResource = CloudResource {
512            provider: CloudProvider::AWS,
513            id: "inst-1".to_string(),
514            location: UsageLocation::try_from("eu-west-3").unwrap(),
515            resource_details: ResourceDetails::Instance {
516                instance_type: "m6g.xlarge".to_string(),
517                usage: Some(InstanceUsage {
518                    average_cpu_load: 100.0,
519                    state: InstanceState::Running,
520                }),
521            },
522            tags: vec![tag1, tag2],
523        };
524
525        let cloud_resource_with_impacts = CloudResourceWithImpacts {
526            cloud_resource,
527            impacts_values: Some(ImpactsValues {
528                adp_manufacture_kgsbeq: 0.1,
529                adp_use_kgsbeq: 0.2,
530                pe_manufacture_megajoules: 0.3,
531                pe_use_megajoules: 0.4,
532                gwp_manufacture_kgco2eq: 0.5,
533                gwp_use_kgco2eq: 0.6,
534                raw_data: None,
535            }),
536            impacts_duration_hours: 1.0,
537        };
538
539        let estimated_inventory: EstimatedInventory = EstimatedInventory {
540            metadata: EstimationMetadata {
541                description: None,
542                boavizta_api_version: Some("v1.2.3".to_owned()),
543                cloud_scanner_version: Some("4.5.6".to_owned()),
544                estimation_date: None,
545                execution_statistics: None,
546            },
547            impacting_resources: vec![cloud_resource_with_impacts],
548        };
549
550        let summary = ImpactsSummary::new(
551            "eu-west-3".to_string(),
552            "FRA".to_string(),
553            &estimated_inventory,
554            1.0,
555        );
556        let metrics = get_all_metrics(&summary, estimated_inventory).unwrap();
557
558        println!("{}", metrics);
559
560        let expected = r#"# HELP boavizta_number_of_resources_total Number of resources detected during the inventory.
561# TYPE boavizta_number_of_resources_total gauge
562boavizta_number_of_resources_total{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1
563# HELP boavizta_number_of_resources_assessed Number of resources that were considered in the estimation of impacts.
564# TYPE boavizta_number_of_resources_assessed gauge
565boavizta_number_of_resources_assessed{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1
566# HELP boavizta_duration_of_use_hours Use duration considered to estimate impacts.
567# TYPE boavizta_duration_of_use_hours gauge
568boavizta_duration_of_use_hours{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1.0
569# HELP boavizta_pe_manufacture_megajoules Energy consumed for manufacture.
570# TYPE boavizta_pe_manufacture_megajoules gauge
571boavizta_pe_manufacture_megajoules{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.3
572# HELP boavizta_pe_use_megajoules Energy consumed during use.
573# TYPE boavizta_pe_use_megajoules gauge
574boavizta_pe_use_megajoules{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.4
575# HELP boavizta_adp_manufacture_kgsbeq Abiotic resources depletion potential of manufacture.
576# TYPE boavizta_adp_manufacture_kgsbeq gauge
577boavizta_adp_manufacture_kgsbeq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.1
578# HELP boavizta_adp_use_kgsbeq Abiotic resources depletion potential of use.
579# TYPE boavizta_adp_use_kgsbeq gauge
580boavizta_adp_use_kgsbeq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.2
581# HELP boavizta_gwp_manufacture_kgco2eq Global Warming Potential of manufacture.
582# TYPE boavizta_gwp_manufacture_kgco2eq gauge
583boavizta_gwp_manufacture_kgco2eq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.5
584# HELP boavizta_gwp_use_kgco2eq Global Warming Potential of use.
585# TYPE boavizta_gwp_use_kgco2eq gauge
586boavizta_gwp_use_kgco2eq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.6
587# HELP boavizta_resource_duration_of_use_hours Use duration considered to estimate impacts.
588# TYPE boavizta_resource_duration_of_use_hours gauge
589boavizta_resource_duration_of_use_hours{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1.0
590# HELP boavizta_resource_pe_embodied_megajoules Energy consumed for manufacture.
591# TYPE boavizta_resource_pe_embodied_megajoules gauge
592boavizta_resource_pe_embodied_megajoules{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.3
593# HELP boavizta_resource_pe_use_megajoules Energy consumed during use.
594# TYPE boavizta_resource_pe_use_megajoules gauge
595boavizta_resource_pe_use_megajoules{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.4
596# HELP boavizta_resource_adp_embodied_kgsbeq Abiotic resources depletion potential of embodied impacts.
597# TYPE boavizta_resource_adp_embodied_kgsbeq gauge
598boavizta_resource_adp_embodied_kgsbeq{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.1
599# HELP boavizta_resource_adp_use_kgsbeq Abiotic resources depletion potential of use.
600# TYPE boavizta_resource_adp_use_kgsbeq gauge
601boavizta_resource_adp_use_kgsbeq{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.2
602# HELP boavizta_resource_gwp_embodied_kgco2eq Global Warming Potential of embodied impacts.
603# TYPE boavizta_resource_gwp_embodied_kgco2eq gauge
604boavizta_resource_gwp_embodied_kgco2eq{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.5
605# HELP boavizta_resource_gwp_use_kgco2eq Global Warming Potential of use.
606# TYPE boavizta_resource_gwp_use_kgco2eq gauge
607boavizta_resource_gwp_use_kgco2eq{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.6
608# HELP boavizta_resource_cpu_load CPU load of instance.
609# TYPE boavizta_resource_cpu_load gauge
610boavizta_resource_cpu_load{awsregion="eu-west-3",country="FRA",resource_type="Instance",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Running",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 100.0
611# HELP boavizta_storage_size_gb Storage size in GB.
612# TYPE boavizta_storage_size_gb gauge
613# EOF
614"#;
615
616        assert_eq!(expected, metrics);
617    }
618
619    #[tokio::test]
620    async fn test_get_all_metrics_for_storage() {
621        let tag1 = CloudResourceTag {
622            key: "tag_key_1".to_string(),
623            value: Some("tag_value_1".to_string()),
624        };
625        let tag2 = CloudResourceTag {
626            key: "tag_key_2".to_string(),
627            value: Some("tag_value_2".to_string()),
628        };
629
630        let cloud_resource: CloudResource = CloudResource {
631            provider: CloudProvider::AWS,
632            id: "inst-1".to_string(),
633            location: UsageLocation::try_from("eu-west-3").unwrap(),
634            resource_details: ResourceDetails::BlockStorage {
635                storage_type: "arbitrary-type".to_string(),
636                usage: Some(StorageUsage { size_gb: 42 }),
637                attached_instances: None,
638            },
639            tags: vec![tag1, tag2],
640        };
641
642        let cloud_resource_with_impacts = CloudResourceWithImpacts {
643            cloud_resource,
644            impacts_values: Some(ImpactsValues {
645                adp_manufacture_kgsbeq: 0.1,
646                adp_use_kgsbeq: 0.2,
647                pe_manufacture_megajoules: 0.3,
648                pe_use_megajoules: 0.4,
649                gwp_manufacture_kgco2eq: 0.5,
650                gwp_use_kgco2eq: 0.6,
651                raw_data: None,
652            }),
653            impacts_duration_hours: 1.0,
654        };
655
656        let estimated_inventory: EstimatedInventory = EstimatedInventory {
657            metadata: EstimationMetadata {
658                description: None,
659                boavizta_api_version: Some("v1.2.3".to_owned()),
660                cloud_scanner_version: Some("4.5.6".to_owned()),
661                estimation_date: None,
662                execution_statistics: None,
663            },
664            impacting_resources: vec![cloud_resource_with_impacts],
665        };
666
667        let summary = ImpactsSummary::new(
668            "eu-west-3".to_string(),
669            "FRA".to_string(),
670            &estimated_inventory,
671            1.0,
672        );
673
674        let metrics = get_all_metrics(&summary, estimated_inventory).unwrap();
675
676        println!("{}", metrics);
677
678        let expected = r#"# HELP boavizta_number_of_resources_total Number of resources detected during the inventory.
679# TYPE boavizta_number_of_resources_total gauge
680boavizta_number_of_resources_total{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1
681# HELP boavizta_number_of_resources_assessed Number of resources that were considered in the estimation of impacts.
682# TYPE boavizta_number_of_resources_assessed gauge
683boavizta_number_of_resources_assessed{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1
684# HELP boavizta_duration_of_use_hours Use duration considered to estimate impacts.
685# TYPE boavizta_duration_of_use_hours gauge
686boavizta_duration_of_use_hours{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1.0
687# HELP boavizta_pe_manufacture_megajoules Energy consumed for manufacture.
688# TYPE boavizta_pe_manufacture_megajoules gauge
689boavizta_pe_manufacture_megajoules{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.3
690# HELP boavizta_pe_use_megajoules Energy consumed during use.
691# TYPE boavizta_pe_use_megajoules gauge
692boavizta_pe_use_megajoules{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.4
693# HELP boavizta_adp_manufacture_kgsbeq Abiotic resources depletion potential of manufacture.
694# TYPE boavizta_adp_manufacture_kgsbeq gauge
695boavizta_adp_manufacture_kgsbeq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.1
696# HELP boavizta_adp_use_kgsbeq Abiotic resources depletion potential of use.
697# TYPE boavizta_adp_use_kgsbeq gauge
698boavizta_adp_use_kgsbeq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.2
699# HELP boavizta_gwp_manufacture_kgco2eq Global Warming Potential of manufacture.
700# TYPE boavizta_gwp_manufacture_kgco2eq gauge
701boavizta_gwp_manufacture_kgco2eq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.5
702# HELP boavizta_gwp_use_kgco2eq Global Warming Potential of use.
703# TYPE boavizta_gwp_use_kgco2eq gauge
704boavizta_gwp_use_kgco2eq{awsregion="eu-west-3",country="FRA",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.6
705# HELP boavizta_resource_duration_of_use_hours Use duration considered to estimate impacts.
706# TYPE boavizta_resource_duration_of_use_hours gauge
707boavizta_resource_duration_of_use_hours{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 1.0
708# HELP boavizta_resource_pe_embodied_megajoules Energy consumed for manufacture.
709# TYPE boavizta_resource_pe_embodied_megajoules gauge
710boavizta_resource_pe_embodied_megajoules{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.3
711# HELP boavizta_resource_pe_use_megajoules Energy consumed during use.
712# TYPE boavizta_resource_pe_use_megajoules gauge
713boavizta_resource_pe_use_megajoules{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.4
714# HELP boavizta_resource_adp_embodied_kgsbeq Abiotic resources depletion potential of embodied impacts.
715# TYPE boavizta_resource_adp_embodied_kgsbeq gauge
716boavizta_resource_adp_embodied_kgsbeq{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.1
717# HELP boavizta_resource_adp_use_kgsbeq Abiotic resources depletion potential of use.
718# TYPE boavizta_resource_adp_use_kgsbeq gauge
719boavizta_resource_adp_use_kgsbeq{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.2
720# HELP boavizta_resource_gwp_embodied_kgco2eq Global Warming Potential of embodied impacts.
721# TYPE boavizta_resource_gwp_embodied_kgco2eq gauge
722boavizta_resource_gwp_embodied_kgco2eq{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.5
723# HELP boavizta_resource_gwp_use_kgco2eq Global Warming Potential of use.
724# TYPE boavizta_resource_gwp_use_kgco2eq gauge
725boavizta_resource_gwp_use_kgco2eq{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 0.6
726# HELP boavizta_resource_cpu_load CPU load of instance.
727# TYPE boavizta_resource_cpu_load gauge
728# HELP boavizta_storage_size_gb Storage size in GB.
729# TYPE boavizta_storage_size_gb gauge
730boavizta_storage_size_gb{awsregion="eu-west-3",country="FRA",resource_type="BlockStorage",resource_id="inst-1",resource_tags="tag_key_1:tag_value_1;tag_key_2:tag_value_2;",resource_state="Unknown",cloud_scanner_version="4.5.6",boaviztapi_version="v1.2.3"} 42
731# EOF
732"#;
733
734        assert_eq!(expected, metrics);
735    }
736}