use std::time::Duration;
use aws_sdk_cloudwatch::types::{Dimension, StandardUnit, StatisticSet};
use futures_util::FutureExt;
use common::MockCloudWatchClient;
mod common;
use anyhow::Result;
fn dim(name: &str, value: &str) -> Dimension {
Dimension::builder().name(name).value(value).build()
}
#[tokio::test]
async fn test_flush_on_shutdown() -> Result<()> {
let client = MockCloudWatchClient::default();
tokio::time::pause();
let (tx, rx) = tokio::sync::oneshot::channel();
let backend_fut = metrics_cloudwatch::Builder::new()
.cloudwatch_namespace("test-ns")
.default_dimension("dimension", "default")
.send_interval_secs(1)
.storage_resolution(metrics_cloudwatch::Resolution::Second)
.shutdown_signal(Box::pin(rx.map(|_| ())))
.init_future_mock(client.clone(), metrics::set_global_recorder)
.await?;
let joinhandle = tokio::spawn(backend_fut);
tokio::time::sleep(Duration::from_millis(5)).await;
for i in 0..150 {
metrics::histogram!("test").record(i);
metrics::counter!("count").increment(1);
}
metrics::histogram!("test").record(0.0);
metrics::histogram!("test").record(200.0);
metrics::histogram!("labels", "label" => "1", "@unknown_@_label_is_skipped" => "abc")
.record(111.0);
metrics::histogram!("labels2", "dimension" => "", "label" => "1").record(111.0);
metrics::histogram!("bytes", "@unit" => metrics_cloudwatch::Unit::Bytes).record(200.0);
metrics::gauge!("gauge").set(100.0);
metrics::gauge!("gauge").set(200.0);
tokio::time::sleep(Duration::from_millis(5)).await;
tx.send(()).unwrap();
joinhandle.await?;
let actual = client.put_metric_data.lock().unwrap();
assert_eq!(actual.len(), 1);
let metric_data = actual[0].metric_data.as_ref().unwrap();
assert_eq!(metric_data.len(), 7);
let value_metric = metric_data
.iter()
.find(|m| m.metric_name() == Some("test") && m.counts.as_ref().unwrap().len() == 150)
.unwrap();
assert_eq!(value_metric.counts.as_ref().unwrap().len(), 150);
assert_eq!(value_metric.values.as_ref().unwrap().len(), 150);
assert_eq!(
value_metric.dimensions,
Some(vec![dim("dimension", "default")])
);
let dim_metric = metric_data
.iter()
.find(|m| m.metric_name() == Some("labels"))
.unwrap();
assert_eq!(
dim_metric.dimensions,
Some(vec![dim("dimension", "default"), dim("label", "1")])
);
let dim_metric2 = metric_data
.iter()
.find(|m| m.metric_name() == Some("labels2"))
.unwrap();
assert_eq!(dim_metric2.dimensions, Some(vec![dim("label", "1")]));
let count_metric = metric_data
.iter()
.find(|m| m.metric_name() == Some("test") && m.counts.as_ref().unwrap().len() == 1)
.unwrap();
assert_eq!(count_metric.counts.as_ref().unwrap().len(), 1);
assert_eq!(count_metric.values.as_ref().unwrap().len(), 1);
assert_eq!(
value_metric.dimensions,
Some(vec![dim("dimension", "default")])
);
let count_data = metric_data
.iter()
.find(|m| m.metric_name() == Some("count"))
.unwrap();
assert_eq!(
count_data.statistic_values,
Some(
StatisticSet::builder()
.sample_count(1.0)
.sum(150.0)
.maximum(150.0)
.minimum(150.0)
.build()
)
);
let bytes_data = metric_data
.iter()
.find(|m| m.metric_name() == Some("bytes"))
.unwrap();
assert_eq!(bytes_data.unit(), Some(&StandardUnit::Bytes));
let count_data = metric_data
.iter()
.find(|m| m.metric_name() == Some("gauge"))
.unwrap();
assert_eq!(
count_data.statistic_values,
Some(
StatisticSet::builder()
.sample_count(1.0)
.sum(200.0)
.maximum(200.0)
.minimum(100.0)
.build()
)
);
Ok(())
}