diff --git a/src/api/schema/metrics/errors.rs b/src/api/schema/metrics/errors.rs index ef1772ea69651..1b163e0ac1bfd 100644 --- a/src/api/schema/metrics/errors.rs +++ b/src/api/schema/metrics/errors.rs @@ -14,12 +14,12 @@ impl ErrorsTotal { impl ErrorsTotal { /// Metric timestamp pub async fn timestamp(&self) -> Option> { - self.0.timestamp + self.0.data.timestamp } /// Total error count pub async fn errors_total(&self) -> f64 { - match self.0.value { + match self.0.data.value { MetricValue::Counter { value } => value, _ => 0.00, } diff --git a/src/api/schema/metrics/filter.rs b/src/api/schema/metrics/filter.rs index 2de768e7e2170..31a08e63e07dc 100644 --- a/src/api/schema/metrics/filter.rs +++ b/src/api/schema/metrics/filter.rs @@ -23,7 +23,7 @@ fn sum_metrics<'a, I: IntoIterator>(metrics: I) -> Option { impl<'a> MetricsFilter<'a> for Vec { fn processed_events_total(&self) -> Option { - let sum = sum_metrics( - self.iter() - .filter(|m| m.name.as_str().eq("processed_events_total")), - )?; + let sum = sum_metrics(self.iter().filter(|m| m.name() == "processed_events_total"))?; Some(ProcessedEventsTotal::new(sum)) } fn processed_bytes_total(&self) -> Option { - let sum = sum_metrics( - self.iter() - .filter(|m| m.name.as_str().eq("processed_bytes_total")), - )?; + let sum = sum_metrics(self.iter().filter(|m| m.name() == "processed_bytes_total"))?; Some(ProcessedBytesTotal::new(sum)) } @@ -57,7 +51,7 @@ impl<'a> MetricsFilter<'a> for Vec<&'a Metric> { fn processed_events_total(&self) -> Option { let sum = sum_metrics( self.iter() - .filter(|m| m.name.as_str().eq("processed_events_total")) + .filter(|m| m.name() == "processed_events_total") .copied(), )?; @@ -67,7 +61,7 @@ impl<'a> MetricsFilter<'a> for Vec<&'a Metric> { fn processed_bytes_total(&self) -> Option { let sum = sum_metrics( self.iter() - .filter(|m| m.name.as_str().eq("processed_bytes_total")) + .filter(|m| m.name() == "processed_bytes_total") .copied(), )?; @@ -148,11 +142,11 @@ pub fn component_counter_metrics( let mut iter = metrics.into_iter(); let mut m = iter.next()?; m = iter.fold(m, |mut m1, m2| { - m1.update_value(&m2); + m1.data.update(&m2.data); m1 }); - match m.value { + match m.data.value { MetricValue::Counter { value } if cache.insert(name, value).unwrap_or(0.00) < value => { @@ -175,7 +169,7 @@ pub fn counter_throughput( get_metrics(interval) .filter(filter_fn) - .filter_map(move |m| match m.value { + .filter_map(move |m| match m.data.value { MetricValue::Counter { value } if value > last => { let throughput = value - last; last = value; @@ -212,11 +206,11 @@ pub fn component_counter_throughputs( let mut iter = metrics.into_iter(); let mut m = iter.next()?; m = iter.fold(m, |mut m1, m2| { - m1.update_value(&m2); + m1.data.update(&m2.data); m1 }); - match m.value { + match m.data.value { MetricValue::Counter { value } => { let last = cache.insert(name, value).unwrap_or(0.00); let throughput = value - last; diff --git a/src/api/schema/metrics/host.rs b/src/api/schema/metrics/host.rs index 8ae6f735d4367..2f8d6f82aefdf 100644 --- a/src/api/schema/metrics/host.rs +++ b/src/api/schema/metrics/host.rs @@ -313,8 +313,8 @@ impl HostMetrics { fn filter_host_metric(metrics: &[Metric], name: &str) -> f64 { metrics .iter() - .find(|m| matches!(&m.namespace, Some(n) if n == "host") && m.name == name) - .map(|m| match m.value { + .find(|m| matches!(m.namespace(), Some(n) if n == "host") && m.name() == name) + .map(|m| match m.data.value { MetricValue::Gauge { value } => value, MetricValue::Counter { value } => value, _ => 0.00, diff --git a/src/api/schema/metrics/mod.rs b/src/api/schema/metrics/mod.rs index 4e4bed12e5aee..5d033b040b534 100644 --- a/src/api/schema/metrics/mod.rs +++ b/src/api/schema/metrics/mod.rs @@ -55,7 +55,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream { - get_metrics(interval).filter_map(|m| match m.name.as_str() { + get_metrics(interval).filter_map(|m| match m.name() { "uptime_seconds" => Some(Uptime::new(m)), _ => None, }) @@ -66,7 +66,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream { - get_metrics(interval).filter_map(|m| match m.name.as_str() { + get_metrics(interval).filter_map(|m| match m.name() { "processed_events_total" => Some(ProcessedEventsTotal::new(m)), _ => None, }) @@ -77,7 +77,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream { - counter_throughput(interval, &|m| m.name == "processed_events_total") + counter_throughput(interval, &|m| m.name() == "processed_events_total") .map(|(_, throughput)| throughput as i64) } @@ -86,16 +86,18 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream> { - component_counter_throughputs(interval, &|m| m.name == "processed_events_total").map(|m| { - m.into_iter() - .map(|(m, throughput)| { - ComponentProcessedEventsThroughput::new( - m.tag_value("component_name").unwrap(), - throughput as i64, - ) - }) - .collect() - }) + component_counter_throughputs(interval, &|m| m.name() == "processed_events_total").map( + |m| { + m.into_iter() + .map(|(m, throughput)| { + ComponentProcessedEventsThroughput::new( + m.tag_value("component_name").unwrap(), + throughput as i64, + ) + }) + .collect() + }, + ) } /// Component event processing metrics over `interval`. @@ -103,7 +105,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream> { - component_counter_metrics(interval, &|m| m.name == "processed_events_total").map(|m| { + component_counter_metrics(interval, &|m| m.name() == "processed_events_total").map(|m| { m.into_iter() .map(ComponentProcessedEventsTotal::new) .collect() @@ -115,7 +117,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream { - get_metrics(interval).filter_map(|m| match m.name.as_str() { + get_metrics(interval).filter_map(|m| match m.name() { "processed_bytes_total" => Some(ProcessedBytesTotal::new(m)), _ => None, }) @@ -126,7 +128,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream { - counter_throughput(interval, &|m| m.name == "processed_bytes_total") + counter_throughput(interval, &|m| m.name() == "processed_bytes_total") .map(|(_, throughput)| throughput as i64) } @@ -135,7 +137,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream> { - component_counter_metrics(interval, &|m| m.name == "processed_bytes_total").map(|m| { + component_counter_metrics(interval, &|m| m.name() == "processed_bytes_total").map(|m| { m.into_iter() .map(ComponentProcessedBytesTotal::new) .collect() @@ -147,7 +149,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream> { - component_counter_throughputs(interval, &|m| m.name == "processed_bytes_total").map(|m| { + component_counter_throughputs(interval, &|m| m.name() == "processed_bytes_total").map(|m| { m.into_iter() .map(|(m, throughput)| { ComponentProcessedBytesThroughput::new( @@ -165,7 +167,7 @@ impl MetricsSubscription { #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream { get_metrics(interval) - .filter(|m| m.name.ends_with("_errors_total")) + .filter(|m| m.name().ends_with("_errors_total")) .map(ErrorsTotal::new) } @@ -174,7 +176,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream> { - component_counter_metrics(interval, &|m| m.name.ends_with("_errors_total")) + component_counter_metrics(interval, &|m| m.name().ends_with("_errors_total")) .map(|m| m.into_iter().map(ComponentErrorsTotal::new).collect()) } @@ -183,7 +185,7 @@ impl MetricsSubscription { &self, #[graphql(default = 1000, validator(IntRange(min = "10", max = "60_000")))] interval: i32, ) -> impl Stream { - get_metrics(interval).filter_map(|m| match m.name.as_str() { + get_metrics(interval).filter_map(|m| match m.name() { "uptime_seconds" => Some(MetricType::Uptime(m.into())), "processed_events_total" => Some(MetricType::ProcessedEventsTotal(m.into())), "processed_bytes_total" => Some(MetricType::ProcessedBytesTotal(m.into())), diff --git a/src/api/schema/metrics/processed_bytes.rs b/src/api/schema/metrics/processed_bytes.rs index 5f9ade45b756f..9dc25269bc2b6 100644 --- a/src/api/schema/metrics/processed_bytes.rs +++ b/src/api/schema/metrics/processed_bytes.rs @@ -14,12 +14,12 @@ impl ProcessedBytesTotal { impl ProcessedBytesTotal { /// Metric timestamp pub async fn timestamp(&self) -> Option> { - self.0.timestamp + self.0.data.timestamp } /// Total number of bytes processed pub async fn processed_bytes_total(&self) -> f64 { - match self.0.value { + match self.0.data.value { MetricValue::Counter { value } => value, _ => 0.00, } diff --git a/src/api/schema/metrics/processed_events.rs b/src/api/schema/metrics/processed_events.rs index 274f8846e7778..8f01c17d20e63 100644 --- a/src/api/schema/metrics/processed_events.rs +++ b/src/api/schema/metrics/processed_events.rs @@ -14,12 +14,12 @@ impl ProcessedEventsTotal { impl ProcessedEventsTotal { /// Metric timestamp pub async fn timestamp(&self) -> Option> { - self.0.timestamp + self.0.data.timestamp } /// Total number of events processed pub async fn processed_events_total(&self) -> f64 { - match self.0.value { + match self.0.data.value { MetricValue::Counter { value } => value, _ => 0.00, } diff --git a/src/api/schema/metrics/uptime.rs b/src/api/schema/metrics/uptime.rs index 9eaac434d7147..e234025c4fa03 100644 --- a/src/api/schema/metrics/uptime.rs +++ b/src/api/schema/metrics/uptime.rs @@ -14,12 +14,12 @@ impl Uptime { impl Uptime { /// Metric timestamp pub async fn timestamp(&self) -> Option> { - self.0.timestamp + self.0.data.timestamp } /// Number of seconds the Vector instance has been alive pub async fn seconds(&self) -> f64 { - match self.0.value { + match self.0.data.value { MetricValue::Gauge { value } => value, _ => 0.00, } diff --git a/src/conditions/check_fields.rs b/src/conditions/check_fields.rs index 274406087ac13..e4e7798d936da 100644 --- a/src/conditions/check_fields.rs +++ b/src/conditions/check_fields.rs @@ -75,15 +75,13 @@ impl CheckFieldsPredicate for EqualsPredicate { _ => false, }, }), - Event::Metric(m) => { - m.tags - .as_ref() - .and_then(|t| t.get(&self.target)) - .map_or(false, |v| match &self.arg { - CheckFieldsPredicateArg::String(s) => s.as_bytes() == v.as_bytes(), - _ => false, - }) - } + Event::Metric(m) => m + .tags() + .and_then(|t| t.get(&self.target)) + .map_or(false, |v| match &self.arg { + CheckFieldsPredicateArg::String(s) => s.as_bytes() == v.as_bytes(), + _ => false, + }), } } } @@ -244,8 +242,7 @@ impl CheckFieldsPredicate for NotEqualsPredicate { !self.arg.iter().any(|s| b == s.as_bytes()) }), Event::Metric(m) => m - .tags - .as_ref() + .tags() .and_then(|t| t.get(&self.target)) .map_or(false, |v| { !self.arg.iter().any(|s| v.as_bytes() == s.as_bytes()) @@ -285,8 +282,7 @@ impl CheckFieldsPredicate for RegexPredicate { .map(|field| field.to_string_lossy()) .map_or(false, |field| self.regex.is_match(&field)), Event::Metric(metric) => metric - .tags - .as_ref() + .tags() .and_then(|tags| tags.get(&self.target)) .map_or(false, |field| self.regex.is_match(field)), } @@ -317,10 +313,7 @@ impl CheckFieldsPredicate for ExistsPredicate { fn check(&self, event: &Event) -> bool { (match event { Event::Log(l) => l.get(&self.target).is_some(), - Event::Metric(m) => m - .tags - .as_ref() - .map_or(false, |t| t.contains_key(&self.target)), + Event::Metric(m) => m.tags().map_or(false, |t| t.contains_key(&self.target)), }) == self.arg } } diff --git a/src/conditions/is_log.rs b/src/conditions/is_log.rs index 622149fa269a7..9b944e400b018 100644 --- a/src/conditions/is_log.rs +++ b/src/conditions/is_log.rs @@ -63,14 +63,11 @@ mod test { assert_eq!(cond.check(&Event::from("just a log")), true); assert_eq!( - cond.check(&Event::from(Metric { - name: "test metric".to_string(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - })), + cond.check(&Event::from(Metric::new( + "test metric".to_string(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ))), false ); } diff --git a/src/conditions/is_metric.rs b/src/conditions/is_metric.rs index a9007ed4f4e0c..1c3a4d84200bc 100644 --- a/src/conditions/is_metric.rs +++ b/src/conditions/is_metric.rs @@ -63,14 +63,11 @@ mod test { assert_eq!(cond.check(&Event::from("just a log")), false); assert_eq!( - cond.check(&Event::from(Metric { - name: "test metric".to_string(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - })), + cond.check(&Event::from(Metric::new( + "test metric".to_string(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ))), true ); } diff --git a/src/conditions/remap.rs b/src/conditions/remap.rs index 16d8f7b5003c8..cf9421436781d 100644 --- a/src/conditions/remap.rs +++ b/src/conditions/remap.rs @@ -158,18 +158,19 @@ mod test { // Ok(()), // ), ( - Event::Metric(Metric { - name: "zork".into(), - namespace: Some("zerk".into()), - timestamp: None, - tags: Some({ + Event::Metric( + Metric::new( + "zork".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some("zerk".into())) + .with_tags(Some({ let mut tags = BTreeMap::new(); tags.insert("host".into(), "zoobub".into()); tags - }), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }), + })), + ), r#".name == "zork" && .tags.host == "zoobub" && .kind == "incremental""#, Ok(()), Ok(()), diff --git a/src/event/metric.rs b/src/event/metric.rs index 2cef0eb94c20e..90c7793a66be3 100644 --- a/src/event/metric.rs +++ b/src/event/metric.rs @@ -10,21 +10,41 @@ use std::{ iter::FromIterator, }; -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub struct Metric { + #[serde(flatten)] + pub series: MetricSeries, + #[serde(flatten)] + pub data: MetricData, +} + +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub struct MetricSeries { + #[serde(flatten)] + pub name: MetricName, + #[serde(skip_serializing_if = "Option::is_none")] + pub tags: Option, +} + +pub type MetricTags = BTreeMap; + +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub struct MetricName { pub name: String, #[serde(skip_serializing_if = "Option::is_none")] pub namespace: Option, +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +pub struct MetricData { #[serde(skip_serializing_if = "Option::is_none")] pub timestamp: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub tags: Option>, pub kind: MetricKind, #[serde(flatten)] pub value: MetricValue, } -#[derive(Clone, Copy, Debug, Hash, PartialEq, Deserialize, Serialize, is_enum_variant)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, is_enum_variant)] #[serde(rename_all = "snake_case")] /// A metric may be an incremental value, updating the previous value of /// the metric, or absolute, which sets the reference for future @@ -205,20 +225,142 @@ pub enum StatisticKind { } impl Metric { + pub fn new(name: String, kind: MetricKind, value: MetricValue) -> Self { + Self { + series: MetricSeries { + name: MetricName { + name, + namespace: None, + }, + tags: None, + }, + data: MetricData { + timestamp: None, + kind, + value, + }, + } + } + + pub fn with_namespace(mut self, namespace: Option) -> Self { + self.series.name.namespace = namespace; + self + } + + pub fn with_timestamp(mut self, timestamp: Option>) -> Self { + self.data.timestamp = timestamp; + self + } + + pub fn with_tags(mut self, tags: Option) -> Self { + self.series.tags = tags; + self + } + /// Create a new Metric from this with all the data but marked as absolute. pub fn to_absolute(&self) -> Self { Self { - name: self.name.clone(), - namespace: self.namespace.clone(), + series: self.series.clone(), + data: self.data.to_absolute(), + } + } + + /// Convert the metrics_runtime::Measurement value plus the name and + /// labels from a Key into our internal Metric format. + pub fn from_metric_kv(key: &metrics::Key, handle: &metrics_util::Handle) -> Self { + let value = match handle { + metrics_util::Handle::Counter(_) => MetricValue::Counter { + value: handle.read_counter() as f64, + }, + metrics_util::Handle::Gauge(_) => MetricValue::Gauge { + value: handle.read_gauge() as f64, + }, + metrics_util::Handle::Histogram(_) => { + let values = handle.read_histogram(); + // Each sample in the source measurement has an + // effective sample rate of 1. + let samples = values + .into_iter() + .map(|i| Sample { + value: i as f64, + rate: 1, + }) + .collect(); + MetricValue::Distribution { + samples, + statistic: StatisticKind::Histogram, + } + } + }; + + let labels = key + .labels() + .map(|label| (String::from(label.key()), String::from(label.value()))) + .collect::(); + + Self::new(key.name().to_string(), MetricKind::Absolute, value) + .with_namespace(Some("vector".to_string())) + .with_timestamp(Some(Utc::now())) + .with_tags(if labels.is_empty() { + None + } else { + Some(labels) + }) + } + + pub fn name(&self) -> &str { + &self.series.name.name + } + + pub fn namespace(&self) -> Option<&str> { + self.series.name.namespace.as_deref() + } + + pub fn tags(&self) -> Option<&MetricTags> { + self.series.tags.as_ref() + } + + pub fn tags_mut(&mut self) -> &mut Option { + &mut self.series.tags + } + + /// Returns `true` if `name` tag is present, and matches the provided `value` + pub fn tag_matches(&self, name: &str, value: &str) -> bool { + self.tags() + .filter(|t| t.get(name).filter(|v| *v == value).is_some()) + .is_some() + } + + /// Returns the string value of a tag, if it exists + pub fn tag_value(&self, name: &str) -> Option { + self.tags().and_then(|t| t.get(name).cloned()) + } + + /// Sets or updates the string value of a tag + pub fn set_tag_value(&mut self, name: String, value: String) { + self.tags_mut() + .get_or_insert_with(MetricTags::new) + .insert(name, value); + } + + /// Deletes the tag, if it exists, returns the old tag value. + pub fn delete_tag(&mut self, name: &str) -> Option { + self.series.tags.as_mut().and_then(|tags| tags.remove(name)) + } +} + +impl MetricData { + /// Create new MetricData from this with all the data but marked as absolute. + pub fn to_absolute(&self) -> Self { + Self { timestamp: self.timestamp, - tags: self.tags.clone(), kind: MetricKind::Absolute, value: self.value.clone(), } } - /// Mutate MetricValue, by adding the value from another Metric. - pub fn update_value(&mut self, other: &Self) { + /// Update this MetricData by adding the value from another. + pub fn update(&mut self, other: &Self) { match (&mut self.value, &other.value) { (MetricValue::Counter { ref mut value }, MetricValue::Counter { value: value2 }) => { *value += value2; @@ -273,11 +415,9 @@ impl Metric { /// Add the data from the other metric to this one. The `other` must /// be relative and contain the same value type as this one. pub fn add(&mut self, other: &Self) { - if other.kind.is_absolute() { - return; + if other.kind.is_incremental() { + self.update(other); } - - self.update_value(other) } /// Set all the values of this metric to zero without emptying @@ -326,78 +466,6 @@ impl Metric { } } } - - /// Convert the metrics_runtime::Measurement value plus the name and - /// labels from a Key into our internal Metric format. - pub fn from_metric_kv(key: &metrics::Key, handle: &metrics_util::Handle) -> Self { - let value = match handle { - metrics_util::Handle::Counter(_) => MetricValue::Counter { - value: handle.read_counter() as f64, - }, - metrics_util::Handle::Gauge(_) => MetricValue::Gauge { - value: handle.read_gauge() as f64, - }, - metrics_util::Handle::Histogram(_) => { - let values = handle.read_histogram(); - // Each sample in the source measurement has an - // effective sample rate of 1. - let samples = values - .into_iter() - .map(|i| Sample { - value: i as f64, - rate: 1, - }) - .collect(); - MetricValue::Distribution { - samples, - statistic: StatisticKind::Histogram, - } - } - }; - - let labels = key - .labels() - .map(|label| (String::from(label.key()), String::from(label.value()))) - .collect::>(); - - Self { - name: key.name().to_string(), - namespace: Some("vector".to_string()), - timestamp: Some(Utc::now()), - tags: if labels.is_empty() { - None - } else { - Some(labels) - }, - kind: MetricKind::Absolute, - value, - } - } - - /// Returns `true` if `name` tag is present, and matches the provided `value` - pub fn tag_matches(&self, name: &str, value: &str) -> bool { - self.tags - .as_ref() - .filter(|t| t.get(name).filter(|v| *v == value).is_some()) - .is_some() - } - - /// Returns the string value of a tag, if it exists - pub fn tag_value(&self, name: &str) -> Option { - self.tags.as_ref().and_then(|t| t.get(name).cloned()) - } - - /// Sets or updates the string value of a tag - pub fn set_tag_value(&mut self, name: String, value: String) { - self.tags - .get_or_insert_with(BTreeMap::new) - .insert(name, value); - } - - /// Deletes the tag, if it exists, returns the old tag value. - pub fn delete_tag(&mut self, name: &str) -> Option { - self.tags.as_mut().and_then(|tags| tags.remove(name)) - } } impl Display for Metric { @@ -421,16 +489,16 @@ impl Display for Metric { /// 2020-08-12T20:23:37.248661343Z vector_processed_bytes_total{component_kind="sink",component_type="blackhole"} = 6391 /// ``` fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> { - if let Some(timestamp) = &self.timestamp { + if let Some(timestamp) = &self.data.timestamp { write!(fmt, "{:?} ", timestamp)?; } - if let Some(namespace) = &self.namespace { + if let Some(namespace) = &self.namespace() { write_word(fmt, namespace)?; write!(fmt, "_")?; } - write_word(fmt, &self.name)?; + write_word(fmt, &self.name())?; write!(fmt, "{{")?; - if let Some(tags) = &self.tags { + if let Some(tags) = &self.tags() { write_list(fmt, ",", tags.iter(), |fmt, (tag, value)| { write_word(fmt, tag).and_then(|()| write!(fmt, "={:?}", value)) })?; @@ -438,12 +506,12 @@ impl Display for Metric { write!( fmt, "}} {} ", - match self.kind { + match self.data.kind { MetricKind::Absolute => '=', MetricKind::Incremental => '+', } )?; - match &self.value { + match &self.data.value { MetricValue::Counter { value } => write!(fmt, "{}", value), MetricValue::Gauge { value } => write!(fmt, "{}", value), MetricValue::Set { values } => { @@ -517,21 +585,21 @@ impl Object for Metric { } [Segment::Field(name)] if name.as_str() == "name" => { let value = value.try_bytes().map_err(|e| e.to_string())?; - self.name = String::from_utf8_lossy(&value).into_owned(); + self.series.name.name = String::from_utf8_lossy(&value).into_owned(); Ok(()) } [Segment::Field(namespace)] if namespace.as_str() == "namespace" => { let value = value.try_bytes().map_err(|e| e.to_string())?; - self.namespace = Some(String::from_utf8_lossy(&value).into_owned()); + self.series.name.namespace = Some(String::from_utf8_lossy(&value).into_owned()); Ok(()) } [Segment::Field(timestamp)] if timestamp.as_str() == "timestamp" => { let value = value.try_timestamp().map_err(|e| e.to_string())?; - self.timestamp = Some(value); + self.data.timestamp = Some(value); Ok(()) } [Segment::Field(kind)] if kind.as_str() == "kind" => { - self.kind = MetricKind::try_from(value)?; + self.data.kind = MetricKind::try_from(value)?; Ok(()) } _ => Err(MetricPathError::InvalidPath { @@ -544,16 +612,16 @@ impl Object for Metric { fn get(&self, path: &remap::Path) -> Result, String> { if path.is_root() { - let mut map = BTreeMap::new(); - map.insert("name".to_string(), self.name.clone().into()); - if let Some(ref namespace) = self.namespace { + let mut map = BTreeMap::::new(); + map.insert("name".to_string(), self.series.name.name.clone().into()); + if let Some(ref namespace) = self.series.name.namespace { map.insert("namespace".to_string(), namespace.clone().into()); } - if let Some(timestamp) = self.timestamp { + if let Some(timestamp) = self.data.timestamp { map.insert("timestamp".to_string(), timestamp.into()); } - map.insert("kind".to_string(), self.kind.clone().into()); - if let Some(tags) = &self.tags { + map.insert("kind".to_string(), self.data.kind.into()); + if let Some(tags) = self.tags() { map.insert( "tags".to_string(), tags.iter() @@ -562,31 +630,33 @@ impl Object for Metric { .into(), ); } - map.insert("type".to_string(), self.value.clone().into()); + map.insert("type".to_string(), self.data.value.clone().into()); return Ok(Some(map.into())); } match path.segments() { - [Segment::Field(name)] if name.as_str() == "name" => Ok(Some(self.name.clone().into())), + [Segment::Field(name)] if name.as_str() == "name" => { + Ok(Some(self.name().to_string().into())) + } [Segment::Field(namespace)] if namespace.as_str() == "namespace" => { - Ok(self.namespace.clone().map(Into::into)) + Ok(self.series.name.namespace.clone().map(Into::into)) } [Segment::Field(timestamp)] if timestamp.as_str() == "timestamp" => { - Ok(self.timestamp.map(Into::into)) + Ok(self.data.timestamp.map(Into::into)) } - [Segment::Field(kind)] if kind.as_str() == "kind" => Ok(Some(self.kind.clone().into())), - [Segment::Field(tags)] if tags.as_str() == "tags" => { - Ok(self.tags.as_ref().map(|map| { - let iter = map.iter().map(|(k, v)| (k.to_owned(), v.to_owned().into())); - remap::Value::from_iter(iter) - })) + [Segment::Field(kind)] if kind.as_str() == "kind" => { + Ok(Some(self.data.kind.clone().into())) } + [Segment::Field(tags)] if tags.as_str() == "tags" => Ok(self.tags().map(|map| { + let iter = map.iter().map(|(k, v)| (k.to_owned(), v.to_owned().into())); + remap::Value::from_iter(iter) + })), [Segment::Field(tags), Segment::Field(field)] if tags.as_str() == "tags" => { Ok(self.tag_value(field.as_str()).map(|value| value.into())) } [Segment::Field(type_)] if type_.as_str() == "type" => { - Ok(Some(self.value.clone().into())) + Ok(Some(self.data.value.clone().into())) } _ => Err(MetricPathError::InvalidPath { path: &path.to_string(), @@ -607,15 +677,17 @@ impl Object for Metric { match path.segments() { [Segment::Field(namespace)] if namespace.as_str() == "namespace" => { - Ok(self.namespace.take().map(Into::into)) + Ok(self.series.name.namespace.take().map(Into::into)) } [Segment::Field(timestamp)] if timestamp.as_str() == "timestamp" => { - Ok(self.timestamp.take().map(Into::into)) + Ok(self.data.timestamp.take().map(Into::into)) + } + [Segment::Field(tags)] if tags.as_str() == "tags" => { + Ok(self.series.tags.take().map(|map| { + let iter = map.into_iter().map(|(k, v)| (k, v.into())); + remap::Value::from_iter(iter) + })) } - [Segment::Field(tags)] if tags.as_str() == "tags" => Ok(self.tags.take().map(|map| { - let iter = map.into_iter().map(|(k, v)| (k, v.into())); - remap::Value::from_iter(iter) - })), [Segment::Field(tags), Segment::Field(field)] if tags.as_str() == "tags" => { Ok(self.delete_tag(field.as_str()).map(Into::into)) } @@ -667,7 +739,7 @@ mod test { Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 11) } - fn tags() -> BTreeMap { + fn tags() -> MetricTags { vec![ ("normal_tag".to_owned(), "value".to_owned()), ("true_tag".to_owned(), "true".to_owned()), @@ -679,152 +751,128 @@ mod test { #[test] fn merge_counters() { - let mut counter = Metric { - name: "counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }; + let mut counter = Metric::new( + "counter".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ); - let delta = Metric { - name: "counter".into(), - namespace: Some("vector".to_string()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 2.0 }, - }; + let delta = Metric::new( + "counter".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 2.0 }, + ) + .with_namespace(Some("vector".to_string())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())); - counter.add(&delta); + counter.data.add(&delta.data); assert_eq!( counter, - Metric { - name: "counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 3.0 }, - } + Metric::new( + "counter".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 3.0 }, + ) ) } #[test] fn merge_gauges() { - let mut gauge = Metric { - name: "gauge".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: 1.0 }, - }; + let mut gauge = Metric::new( + "gauge".into(), + MetricKind::Incremental, + MetricValue::Gauge { value: 1.0 }, + ); - let delta = Metric { - name: "gauge".into(), - namespace: Some("vector".to_string()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: -2.0 }, - }; + let delta = Metric::new( + "gauge".into(), + MetricKind::Incremental, + MetricValue::Gauge { value: -2.0 }, + ) + .with_namespace(Some("vector".to_string())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())); - gauge.add(&delta); + gauge.data.add(&delta.data); assert_eq!( gauge, - Metric { - name: "gauge".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: -1.0 }, - } + Metric::new( + "gauge".into(), + MetricKind::Incremental, + MetricValue::Gauge { value: -1.0 }, + ) ) } #[test] fn merge_sets() { - let mut set = Metric { - name: "set".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + let mut set = Metric::new( + "set".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["old".into()].into_iter().collect(), }, - }; + ); - let delta = Metric { - name: "set".into(), - namespace: Some("vector".to_string()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Set { + let delta = Metric::new( + "set".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["new".into()].into_iter().collect(), }, - }; + ) + .with_namespace(Some("vector".to_string())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())); - set.add(&delta); + set.data.add(&delta.data); assert_eq!( set, - Metric { - name: "set".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + Metric::new( + "set".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["old".into(), "new".into()].into_iter().collect() }, - } + ) ) } #[test] fn merge_histograms() { - let mut dist = Metric { - name: "hist".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let mut dist = Metric::new( + "hist".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: samples![1.0 => 10], statistic: StatisticKind::Histogram, }, - }; + ); - let delta = Metric { - name: "hist".into(), - namespace: Some("vector".to_string()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let delta = Metric::new( + "hist".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: samples![1.0 => 20], statistic: StatisticKind::Histogram, }, - }; + ) + .with_namespace(Some("vector".to_string())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())); - dist.add(&delta); + dist.data.add(&delta.data); assert_eq!( dist, - Metric { - name: "hist".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Metric::new( + "hist".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: samples![1.0 => 10, 1.0 => 20], statistic: StatisticKind::Histogram }, - } + ) ) } @@ -833,14 +881,12 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "one".into(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.23 }, - } + Metric::new( + "one".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.23 }, + ) + .with_tags(Some(tags())) ), r#"one{empty_tag="",normal_tag="value",true_tag="true"} = 1.23"# ); @@ -848,14 +894,12 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "two word".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: 2.0 } - } + Metric::new( + "two word".into(), + MetricKind::Incremental, + MetricValue::Gauge { value: 2.0 } + ) + .with_timestamp(Some(ts())) ), r#"2018-11-14T08:09:10.000000011Z "two word"{} + 2"# ); @@ -863,14 +907,12 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "namespace".into(), - namespace: Some("vector".to_string()), - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.23 }, - } + Metric::new( + "namespace".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.23 }, + ) + .with_namespace(Some("vector".to_string())) ), r#"vector_namespace{} = 1.23"# ); @@ -878,14 +920,12 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "namespace".into(), - namespace: Some("vector host".to_string()), - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.23 }, - } + Metric::new( + "namespace".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.23 }, + ) + .with_namespace(Some("vector host".to_string())) ), r#""vector host"_namespace{} = 1.23"# ); @@ -898,14 +938,11 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "three".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Set { values } - } + Metric::new( + "three".into(), + MetricKind::Absolute, + MetricValue::Set { values } + ) ), r#"three{} = "four=4" "thrəë" v1 v2_two"# ); @@ -913,17 +950,14 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "four".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Distribution { + Metric::new( + "four".into(), + MetricKind::Absolute, + MetricValue::Distribution { samples: samples![1.0 => 3, 2.0 => 4], statistic: StatisticKind::Histogram, } - } + ) ), r#"four{} = histogram 3@1 4@2"# ); @@ -931,18 +965,15 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "five".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + Metric::new( + "five".into(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: buckets![51.0 => 53, 52.0 => 54], count: 107, sum: 103.0, } - } + ) ), r#"five{} = count=107 sum=103 53@51 54@52"# ); @@ -950,18 +981,15 @@ mod test { assert_eq!( format!( "{}", - Metric { - name: "six".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + Metric::new( + "six".into(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: quantiles![1.0 => 63.0, 2.0 => 64.0], count: 2, sum: 127.0, } - } + ) ), r#"six{} = count=2 sum=127 1@63 2@64"# ); @@ -969,18 +997,18 @@ mod test { #[test] fn object_metric_all_fields() { - let metric = Metric { - name: "zub".into(), - namespace: Some("zoob".into()), - timestamp: Some(Utc.ymd(2020, 12, 10).and_hms(12, 0, 0)), - tags: Some({ - let mut map = BTreeMap::new(); - map.insert("tig".to_string(), "tog".to_string()); - map - }), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.23 }, - }; + let metric = Metric::new( + "zub".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.23 }, + ) + .with_namespace(Some("zoob".into())) + .with_tags(Some({ + let mut map = MetricTags::new(); + map.insert("tig".to_string(), "tog".to_string()); + map + })) + .with_timestamp(Some(Utc.ymd(2020, 12, 10).and_hms(12, 0, 0))); assert_eq!( Ok(Some( @@ -999,18 +1027,16 @@ mod test { #[test] fn object_metric_fields() { - let mut metric = Metric { - name: "name".into(), - namespace: None, - timestamp: None, - tags: Some({ - let mut map = BTreeMap::new(); - map.insert("tig".to_string(), "tog".to_string()); - map - }), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.23 }, - }; + let mut metric = Metric::new( + "name".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.23 }, + ) + .with_tags(Some({ + let mut map = MetricTags::new(); + map.insert("tig".to_string(), "tog".to_string()); + map + })); let cases = vec![ ( @@ -1051,14 +1077,11 @@ mod test { #[test] fn object_metric_invalid_paths() { - let mut metric = Metric { - name: "name".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.23 }, - }; + let mut metric = Metric::new( + "name".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.23 }, + ); let validpaths_get = vec![ ".name", diff --git a/src/event/mod.rs b/src/event/mod.rs index ac83432ea9fce..2766c0b4c29d4 100644 --- a/src/event/mod.rs +++ b/src/event/mod.rs @@ -237,14 +237,12 @@ impl From for Event { }, }; - Event::Metric(Metric { - name, - namespace, - timestamp, - tags, - kind, - value, - }) + Event::Metric( + Metric::new(name, kind, value) + .with_namespace(namespace) + .with_tags(tags) + .with_timestamp(timestamp), + ) } } } @@ -296,30 +294,24 @@ impl From for proto::EventWrapper { proto::EventWrapper { event: Some(event) } } - Event::Metric(Metric { - name, - namespace, - timestamp, - tags, - kind, - value, - }) => { - let namespace = namespace.unwrap_or_default(); - - let timestamp = timestamp.map(|ts| prost_types::Timestamp { + Event::Metric(Metric { series, data }) => { + let name = series.name.name; + let namespace = series.name.namespace.unwrap_or_default(); + + let timestamp = data.timestamp.map(|ts| prost_types::Timestamp { seconds: ts.timestamp(), nanos: ts.timestamp_subsec_nanos() as i32, }); - let tags = tags.unwrap_or_default(); + let tags = series.tags.unwrap_or_default(); - let kind = match kind { + let kind = match data.kind { MetricKind::Incremental => proto::metric::Kind::Incremental, MetricKind::Absolute => proto::metric::Kind::Absolute, } .into(); - let metric = match value { + let metric = match data.value { MetricValue::Counter { value } => { MetricProto::Counter(proto::Counter { value }) } diff --git a/src/kubernetes/state/instrumenting.rs b/src/kubernetes/state/instrumenting.rs index 1cb4d69aad1e5..dd73dfa93de7e 100644 --- a/src/kubernetes/state/instrumenting.rs +++ b/src/kubernetes/state/instrumenting.rs @@ -108,9 +108,9 @@ mod tests { crate::metrics::capture_metrics(controller) .find(|event| { let metric = event.as_metric(); - metric.name == "k8s_state_ops_total" && metric.tags == tags_to_lookup + metric.name() == "k8s_state_ops_total" && metric.tags() == tags_to_lookup.as_ref() }) - .map(|event| event.into_metric().value) + .map(|event| event.into_metric().data.value) } fn assert_counter_changed( diff --git a/src/metrics.rs b/src/metrics.rs index fe960cadd42cc..a3ced44a35ad6 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -276,7 +276,7 @@ mod tests { let metric = super::capture_metrics(super::get_controller().unwrap()) .map(|e| e.into_metric()) - .find(|metric| metric.name == "labels_injected_total") + .find(|metric| metric.name() == "labels_injected_total") .unwrap(); let expected_tags = Some( @@ -289,7 +289,7 @@ mod tests { .collect(), ); - assert_eq!(metric.tags, expected_tags); + assert_eq!(metric.tags(), expected_tags.as_ref()); } #[test] @@ -300,9 +300,9 @@ mod tests { let capture_value = || { let metric = super::capture_metrics(super::get_controller().unwrap()) .map(|e| e.into_metric()) - .find(|metric| metric.name == super::CARDINALITY_KEY_NAME) + .find(|metric| metric.name() == super::CARDINALITY_KEY_NAME) .unwrap(); - match metric.value { + match metric.data.value { crate::event::MetricValue::Counter { value } => value, _ => panic!("invalid metric value type, expected coutner, got something else"), } diff --git a/src/sinks/aws_cloudwatch_metrics.rs b/src/sinks/aws_cloudwatch_metrics.rs index e2fdfd68f2c36..95195cb4530dd 100644 --- a/src/sinks/aws_cloudwatch_metrics.rs +++ b/src/sinks/aws_cloudwatch_metrics.rs @@ -148,6 +148,8 @@ impl CloudWatchMetricsSvc { .with_flat_map(move |mut event: Event| { let namespace = event .as_mut_metric() + .series + .name .namespace .take() .unwrap_or_else(|| default_namespace.clone()); @@ -161,11 +163,11 @@ impl CloudWatchMetricsSvc { events .into_iter() .filter_map(|event| { - let metric_name = event.name.to_string(); - let timestamp = event.timestamp.map(timestamp_to_string); - let dimensions = event.tags.clone().map(tags_to_dimensions); - match event.kind { - MetricKind::Incremental => match event.value { + let metric_name = event.name().to_string(); + let timestamp = event.data.timestamp.map(timestamp_to_string); + let dimensions = event.series.tags.clone().map(tags_to_dimensions); + match event.data.kind { + MetricKind::Incremental => match event.data.value { MetricValue::Counter { value } => Some(MetricDatum { metric_name, value: Some(value), @@ -193,7 +195,7 @@ impl CloudWatchMetricsSvc { }), _ => None, }, - MetricKind::Absolute => match event.value { + MetricKind::Absolute => match event.data.value { MetricValue::Gauge { value } => Some(MetricDatum { metric_name, value: Some(value), @@ -295,34 +297,32 @@ mod tests { #[test] fn encode_events_basic_counter() { let events = vec![ - Metric { - name: "exception_total".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }, - Metric { - name: "bytes_out".into(), - namespace: None, - timestamp: Some(Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 123456789)), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 2.5 }, - }, - Metric { - name: "healthcheck".into(), - namespace: None, - timestamp: Some(Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 123456789)), - tags: Some( - vec![("region".to_owned(), "local".to_owned())] - .into_iter() - .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }, + Metric::new( + "exception_total".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ), + Metric::new( + "bytes_out".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 2.5 }, + ) + .with_timestamp(Some( + Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 123456789), + )), + Metric::new( + "healthcheck".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_tags(Some( + vec![("region".to_owned(), "local".to_owned())] + .into_iter() + .collect(), + )) + .with_timestamp(Some( + Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 123456789), + )), ]; assert_eq!( @@ -355,14 +355,11 @@ mod tests { #[test] fn encode_events_absolute_gauge() { - let events = vec![Metric { - name: "temperature".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 10.0 }, - }]; + let events = vec![Metric::new( + "temperature".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 10.0 }, + )]; assert_eq!( svc().encode_events(events), @@ -376,17 +373,14 @@ mod tests { #[test] fn encode_events_distribution() { - let events = vec![Metric { - name: "latency".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let events = vec![Metric::new( + "latency".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![11.0 => 100, 12.0 => 50], statistic: StatisticKind::Histogram, }, - }]; + )]; assert_eq!( svc().encode_events(events), @@ -401,16 +395,13 @@ mod tests { #[test] fn encode_events_set() { - let events = vec![Metric { - name: "users".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + let events = vec![Metric::new( + "users".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["alice".into(), "bob".into()].into_iter().collect(), }, - }]; + )]; assert_eq!( svc().encode_events(events), @@ -456,11 +447,13 @@ mod integration_tests { let mut events = Vec::new(); for i in 0..100 { - let event = Event::Metric(Metric { - name: format!("counter-{}", 0), - namespace: None, - timestamp: None, - tags: Some( + let event = Event::Metric( + Metric::new( + format!("counter-{}", 0), + MetricKind::Incremental, + MetricValue::Counter { value: i as f64 }, + ) + .with_tags(Some( vec![ ("region".to_owned(), "us-west-1".to_owned()), ("production".to_owned(), "true".to_owned()), @@ -468,39 +461,36 @@ mod integration_tests { ] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: i as f64 }, - }); + )), + ); events.push(event); } let gauge_name = random_string(10); for i in 0..10 { - let event = Event::Metric(Metric { - name: format!("gauge-{}", gauge_name), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: i as f64 }, - }); + let event = Event::Metric(Metric::new( + format!("gauge-{}", gauge_name), + MetricKind::Absolute, + MetricValue::Gauge { value: i as f64 }, + )); events.push(event); } let distribution_name = random_string(10); for i in 0..10 { - let event = Event::Metric(Metric { - name: format!("distribution-{}", distribution_name), - namespace: None, - timestamp: Some(Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 123456789)), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { - samples: crate::samples![i as f64 => 100], - statistic: StatisticKind::Histogram, - }, - }); + let event = Event::Metric( + Metric::new( + format!("distribution-{}", distribution_name), + MetricKind::Incremental, + MetricValue::Distribution { + samples: crate::samples![i as f64 => 100], + statistic: StatisticKind::Histogram, + }, + ) + .with_timestamp(Some( + Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 123456789), + )), + ); events.push(event); } @@ -519,14 +509,14 @@ mod integration_tests { for namespace in ["ns1", "ns2", "ns3", "ns4"].iter() { for _ in 0..100 { - let event = Event::Metric(Metric { - name: "counter".to_string(), - namespace: Some(namespace.to_string()), - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }); + let event = Event::Metric( + Metric::new( + "counter".to_string(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some(namespace.to_string())), + ); events.push(event); } } diff --git a/src/sinks/console.rs b/src/sinks/console.rs index b9d8e153eddd3..5d5fefec2f94d 100644 --- a/src/sinks/console.rs +++ b/src/sinks/console.rs @@ -190,11 +190,14 @@ mod test { #[test] fn encodes_counter() { - let event = Event::Metric(Metric { - name: "foos".into(), - namespace: Some("vector".into()), - timestamp: Some(Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 11)), - tags: Some( + let event = Event::Metric( + Metric::new( + "foos".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 100.0 }, + ) + .with_namespace(Some("vector".into())) + .with_tags(Some( vec![ ("key2".to_owned(), "value2".to_owned()), ("key1".to_owned(), "value1".to_owned()), @@ -202,28 +205,24 @@ mod test { ] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 100.0 }, - }); + )) + .with_timestamp(Some(Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 11))), + ); assert_eq!( - r#"{"name":"foos","namespace":"vector","timestamp":"2018-11-14T08:09:10.000000011Z","tags":{"Key3":"Value3","key1":"value1","key2":"value2"},"kind":"incremental","counter":{"value":100.0}}"#, + r#"{"name":"foos","namespace":"vector","tags":{"Key3":"Value3","key1":"value1","key2":"value2"},"timestamp":"2018-11-14T08:09:10.000000011Z","kind":"incremental","counter":{"value":100.0}}"#, encode_event(event, &EncodingConfig::from(Encoding::Json)).unwrap() ); } #[test] fn encodes_set() { - let event = Event::Metric(Metric { - name: "users".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + let event = Event::Metric(Metric::new( + "users".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["bob".into()].into_iter().collect(), }, - }); + )); assert_eq!( r#"{"name":"users","kind":"incremental","set":{"values":["bob"]}}"#, encode_event(event, &EncodingConfig::from(Encoding::Json)).unwrap() @@ -232,17 +231,14 @@ mod test { #[test] fn encodes_histogram_without_timestamp() { - let event = Event::Metric(Metric { - name: "glork".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let event = Event::Metric(Metric::new( + "glork".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![10.0 => 1], statistic: StatisticKind::Histogram, }, - }); + )); assert_eq!( r#"{"name":"glork","kind":"incremental","distribution":{"samples":[{"value":10.0,"rate":1}],"statistic":"histogram"}}"#, encode_event(event, &EncodingConfig::from(Encoding::Json)).unwrap() @@ -251,16 +247,13 @@ mod test { #[test] fn encodes_metric_text() { - let event = Event::Metric(Metric { - name: "users".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + let event = Event::Metric(Metric::new( + "users".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["bob".into()].into_iter().collect(), }, - }); + )); assert_eq!( "users{} + bob", encode_event(event, &EncodingConfig::from(Encoding::Text)).unwrap() diff --git a/src/sinks/datadog/metrics.rs b/src/sinks/datadog/metrics.rs index caf589a990cfa..f0b53494b6470 100644 --- a/src/sinks/datadog/metrics.rs +++ b/src/sinks/datadog/metrics.rs @@ -141,7 +141,7 @@ impl DatadogEndpoint { } fn from_metric(event: &Event) -> Self { - match event.as_metric().value { + match event.as_metric().data.value { MetricValue::Distribution { statistic: StatisticKind::Summary, .. @@ -272,7 +272,7 @@ async fn healthcheck(config: DatadogConfig, client: HttpClient) -> crate::Result } } -fn encode_tags(tags: BTreeMap) -> Vec { +fn encode_tags(tags: &BTreeMap) -> Vec { let mut pairs: Vec<_> = tags .iter() .map(|(name, value)| format!("{}:{}", name, value)) @@ -346,15 +346,12 @@ fn encode_events( let series = events .into_iter() .filter_map(|event| { - let fullname = encode_namespace( - event.namespace.as_deref().or(default_namespace), - '.', - &event.name, - ); - let ts = encode_timestamp(event.timestamp); - let tags = event.tags.clone().map(encode_tags); - match event.kind { - MetricKind::Incremental => match event.value { + let fullname = + encode_namespace(event.namespace().or(default_namespace), '.', event.name()); + let ts = encode_timestamp(event.data.timestamp); + let tags = event.tags().map(encode_tags); + match event.data.kind { + MetricKind::Incremental => match event.data.value { MetricValue::Counter { value } => Some(vec![DatadogMetric { metric: fullname, r#type: DatadogMetricType::Count, @@ -432,7 +429,7 @@ fn encode_events( }]), _ => None, }, - MetricKind::Absolute => match event.value { + MetricKind::Absolute => match event.data.value { MetricValue::Gauge { value } => Some(vec![DatadogMetric { metric: fullname, r#type: DatadogMetricType::Gauge, @@ -459,15 +456,12 @@ fn encode_distribution_events( let series = events .into_iter() .filter_map(|event| { - let fullname = encode_namespace( - event.namespace.as_deref().or(default_namespace), - '.', - &event.name, - ); - let ts = encode_timestamp(event.timestamp); - let tags = event.tags.clone().map(encode_tags); - match event.kind { - MetricKind::Incremental => match event.value { + let fullname = + encode_namespace(event.namespace().or(default_namespace), '.', event.name()); + let ts = encode_timestamp(event.data.timestamp); + let tags = event.tags().map(encode_tags); + match event.data.kind { + MetricKind::Incremental => match event.data.value { MetricValue::Distribution { samples, statistic: StatisticKind::Summary, @@ -547,30 +541,28 @@ mod tests { }; let events = vec![ - Metric { - name: "total".into(), - namespace: Some("test".into()), - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.5 }, - }, - Metric { - name: "check".into(), - namespace: Some("test".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }, - Metric { - name: "unsupported".into(), - namespace: Some("test".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.0 }, - }, + Metric::new( + "total".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.5 }, + ) + .with_namespace(Some("test".into())), + Metric::new( + "check".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some("test".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())), + Metric::new( + "unsupported".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some("test".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())), ]; let req = sink .build_request(PartitionInnerBuffer::new(events, DatadogEndpoint::Series)) @@ -586,7 +578,7 @@ mod tests { #[test] fn test_encode_tags() { assert_eq!( - encode_tags(tags()), + encode_tags(&tags()), vec!["empty_tag:", "normal_tag:value", "true_tag:true"] ); } @@ -601,30 +593,29 @@ mod tests { fn encode_counter() { let interval = 60; let events = vec![ - Metric { - name: "total".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.5 }, - }, - Metric { - name: "check".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }, - Metric { - name: "unsupported".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.0 }, - }, + Metric::new( + "total".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.5 }, + ) + .with_namespace(Some("ns".into())) + .with_timestamp(Some(ts())), + Metric::new( + "check".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())), + Metric::new( + "unsupported".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())), ]; let input = encode_events(events, None, interval); let json = serde_json::to_string(&input).unwrap(); @@ -638,22 +629,18 @@ mod tests { #[test] fn encode_gauge() { let events = vec![ - Metric { - name: "unsupported".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: 0.1 }, - }, - Metric { - name: "volume".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: -1.1 }, - }, + Metric::new( + "unsupported".into(), + MetricKind::Incremental, + MetricValue::Gauge { value: 0.1 }, + ) + .with_timestamp(Some(ts())), + Metric::new( + "volume".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: -1.1 }, + ) + .with_timestamp(Some(ts())), ]; let input = encode_events(events, None, 60); let json = serde_json::to_string(&input).unwrap(); @@ -666,16 +653,14 @@ mod tests { #[test] fn encode_set() { - let events = vec![Metric { - name: "users".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + let events = vec![Metric::new( + "users".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["alice".into(), "bob".into()].into_iter().collect(), }, - }]; + ) + .with_timestamp(Some(ts()))]; let input = encode_events(events, Some("ns"), 60); let json = serde_json::to_string(&input).unwrap(); @@ -770,17 +755,15 @@ mod tests { #[test] fn encode_distribution() { // https://docs.datadoghq.com/developers/metrics/metrics_type/?tab=histogram#metric-type-definition - let events = vec![Metric { - name: "requests".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let events = vec![Metric::new( + "requests".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![1.0 => 3, 2.0 => 3, 3.0 => 2], statistic: StatisticKind::Histogram, }, - }]; + ) + .with_timestamp(Some(ts()))]; let input = encode_events(events, None, 60); let json = serde_json::to_string(&input).unwrap(); @@ -793,17 +776,15 @@ mod tests { #[test] fn encode_datadog_distribution() { // https://docs.datadoghq.com/developers/metrics/types/?tab=distribution#definition - let events = vec![Metric { - name: "requests".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let events = vec![Metric::new( + "requests".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![1.0 => 3, 2.0 => 3, 3.0 => 2], statistic: StatisticKind::Summary, }, - }]; + ) + .with_timestamp(Some(ts()))]; let input = encode_distribution_events(events, None, 60); let json = serde_json::to_string(&input).unwrap(); diff --git a/src/sinks/humio/metrics.rs b/src/sinks/humio/metrics.rs index cb9c378001bf1..b2a5be9f27d11 100644 --- a/src/sinks/humio/metrics.rs +++ b/src/sinks/humio/metrics.rs @@ -169,33 +169,35 @@ mod tests { // Make our test metrics. let metrics = vec![ - Event::from(Metric { - name: "metric1".to_string(), - namespace: None, - timestamp: Some(Utc.ymd(2020, 8, 18).and_hms(21, 0, 1)), - tags: Some( + Event::from( + Metric::new( + "metric1".to_string(), + MetricKind::Incremental, + MetricValue::Counter { value: 42.0 }, + ) + .with_tags(Some( vec![("os.host".to_string(), "somehost".to_string())] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 42.0 }, - }), - Event::from(Metric { - name: "metric2".to_string(), - namespace: None, - timestamp: Some(Utc.ymd(2020, 8, 18).and_hms(21, 0, 2)), - tags: Some( + )) + .with_timestamp(Some(Utc.ymd(2020, 8, 18).and_hms(21, 0, 1))), + ), + Event::from( + Metric::new( + "metric2".to_string(), + MetricKind::Absolute, + MetricValue::Distribution { + samples: crate::samples![1.0 => 100, 2.0 => 200, 3.0 => 300], + statistic: StatisticKind::Histogram, + }, + ) + .with_tags(Some( vec![("os.host".to_string(), "somehost".to_string())] .into_iter() .collect(), - ), - kind: MetricKind::Absolute, - value: MetricValue::Distribution { - samples: crate::samples![1.0 => 100, 2.0 => 200, 3.0 => 300], - statistic: StatisticKind::Histogram, - }, - }), + )) + .with_timestamp(Some(Utc.ymd(2020, 8, 18).and_hms(21, 0, 2))), + ), ]; let len = metrics.len(); diff --git a/src/sinks/influxdb/metrics.rs b/src/sinks/influxdb/metrics.rs index 4f1fd2e7598ca..536f350808188 100644 --- a/src/sinks/influxdb/metrics.rs +++ b/src/sinks/influxdb/metrics.rs @@ -193,7 +193,7 @@ fn merge_tags( event: &Metric, tags: Option<&HashMap>, ) -> Option> { - match (&event.tags, tags) { + match (&event.series.tags, tags) { (Some(ref event_tags), Some(ref config_tags)) => { let mut event_tags = event_tags.clone(); event_tags.extend(config_tags.iter().map(|(k, v)| (k.clone(), v.clone()))); @@ -219,14 +219,10 @@ fn encode_events( ) -> String { let mut output = String::new(); for event in events.into_iter() { - let fullname = encode_namespace( - event.namespace.as_deref().or(default_namespace), - '.', - &event.name, - ); - let ts = encode_timestamp(event.timestamp); + let fullname = encode_namespace(event.namespace().or(default_namespace), '.', event.name()); + let ts = encode_timestamp(event.data.timestamp); let tags = merge_tags(&event, tags); - let (metric_type, fields) = get_type_and_fields(event.value, &quantiles); + let (metric_type, fields) = get_type_and_fields(event.data.value, &quantiles); if let Err(error) = influx_line_protocol( protocol_version, @@ -348,22 +344,21 @@ mod tests { #[test] fn test_encode_counter() { let events = vec![ - Metric { - name: "total".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.5 }, - }, - Metric { - name: "check".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }, + Metric::new( + "total".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.5 }, + ) + .with_namespace(Some("ns".into())) + .with_timestamp(Some(ts())), + Metric::new( + "check".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())), ]; let line_protocols = encode_events(ProtocolVersion::V2, events, Some("vector"), None, &[]); @@ -376,14 +371,14 @@ mod tests { #[test] fn test_encode_gauge() { - let events = vec![Metric { - name: "meter".to_owned(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: -1.5 }, - }]; + let events = vec![Metric::new( + "meter".to_owned(), + MetricKind::Incremental, + MetricValue::Gauge { value: -1.5 }, + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V2, events, None, None, &[]); assert_eq!( @@ -394,16 +389,16 @@ mod tests { #[test] fn test_encode_set() { - let events = vec![Metric { - name: "users".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Set { + let events = vec![Metric::new( + "users".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["alice".into(), "bob".into()].into_iter().collect(), }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V2, events, None, None, &[]); assert_eq!( @@ -414,18 +409,18 @@ mod tests { #[test] fn test_encode_histogram_v1() { - let events = vec![Metric { - name: "requests".to_owned(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + let events = vec![Metric::new( + "requests".to_owned(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: crate::buckets![1.0 => 1, 2.1 => 2, 3.0 => 3], count: 6, sum: 12.5, }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V1, events, None, None, &[]); let line_protocols: Vec<&str> = line_protocols.split('\n').collect(); @@ -453,18 +448,18 @@ mod tests { #[test] fn test_encode_histogram() { - let events = vec![Metric { - name: "requests".to_owned(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + let events = vec![Metric::new( + "requests".to_owned(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: crate::buckets![1.0 => 1, 2.1 => 2, 3.0 => 3], count: 6, sum: 12.5, }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V2, events, None, None, &[]); let line_protocols: Vec<&str> = line_protocols.split('\n').collect(); @@ -492,18 +487,18 @@ mod tests { #[test] fn test_encode_summary_v1() { - let events = vec![Metric { - name: "requests_sum".to_owned(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + let events = vec![Metric::new( + "requests_sum".to_owned(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![0.01 => 1.5, 0.5 => 2.0, 0.99 => 3.0], count: 6, sum: 12.0, }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V1, events, None, None, &[]); let line_protocols: Vec<&str> = line_protocols.split('\n').collect(); @@ -531,18 +526,18 @@ mod tests { #[test] fn test_encode_summary() { - let events = vec![Metric { - name: "requests_sum".to_owned(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + let events = vec![Metric::new( + "requests_sum".to_owned(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![0.01 => 1.5, 0.5 => 2.0, 0.99 => 3.0], count: 6, sum: 12.0, }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V2, events, None, None, &[]); let line_protocols: Vec<&str> = line_protocols.split('\n').collect(); @@ -571,24 +566,21 @@ mod tests { #[test] fn test_encode_distribution() { let events = vec![ - Metric { - name: "requests".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Metric::new( + "requests".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![1.0 => 3, 2.0 => 3, 3.0 => 2], statistic: StatisticKind::Histogram, }, - }, - Metric { - name: "dense_stats".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())), + Metric::new( + "dense_stats".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: (0..20) .map(|v| Sample { value: f64::from(v), @@ -597,14 +589,13 @@ mod tests { .collect(), statistic: StatisticKind::Histogram, }, - }, - Metric { - name: "sparse_stats".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + ) + .with_namespace(Some("ns".into())) + .with_timestamp(Some(ts())), + Metric::new( + "sparse_stats".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: (1..5) .map(|v| Sample { value: f64::from(v), @@ -613,7 +604,9 @@ mod tests { .collect(), statistic: StatisticKind::Histogram, }, - }, + ) + .with_namespace(Some("ns".into())) + .with_timestamp(Some(ts())), ]; let line_protocols = encode_events(ProtocolVersion::V2, events, None, None, &[]); @@ -680,17 +673,17 @@ mod tests { #[test] fn test_encode_distribution_empty_stats() { - let events = vec![Metric { - name: "requests".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let events = vec![Metric::new( + "requests".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: vec![], statistic: StatisticKind::Histogram, }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V2, events, None, None, &[]); assert_eq!(line_protocols.len(), 0); @@ -698,17 +691,17 @@ mod tests { #[test] fn test_encode_distribution_zero_counts_stats() { - let events = vec![Metric { - name: "requests".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let events = vec![Metric::new( + "requests".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![1.0 => 0, 2.0 => 0], statistic: StatisticKind::Histogram, }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events(ProtocolVersion::V2, events, None, None, &[]); assert_eq!(line_protocols.len(), 0); @@ -716,17 +709,17 @@ mod tests { #[test] fn test_encode_distribution_summary() { - let events = vec![Metric { - name: "requests".into(), - namespace: Some("ns".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let events = vec![Metric::new( + "requests".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![1.0 => 3, 2.0 => 3, 3.0 => 2], statistic: StatisticKind::Summary, }, - }]; + ) + .with_namespace(Some("ns".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts()))]; let line_protocols = encode_events( ProtocolVersion::V2, @@ -769,22 +762,21 @@ mod tests { crate::test_util::trace_init(); let events = vec![ - Metric { - name: "cpu".into(), - namespace: Some("vector".into()), - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 2.5 }, - }, - Metric { - name: "mem".into(), - namespace: Some("vector".into()), - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1000.0 }, - }, + Metric::new( + "cpu".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 2.5 }, + ) + .with_namespace(Some("vector".into())) + .with_timestamp(Some(ts())), + Metric::new( + "mem".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1000.0 }, + ) + .with_namespace(Some("vector".into())) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())), ]; let mut tags = HashMap::new(); @@ -923,21 +915,22 @@ mod integration_tests { let metric = format!("counter-{}", Utc::now().timestamp_nanos()); let mut events = Vec::new(); for i in 0..10 { - let event = Event::Metric(Metric { - name: metric.to_string(), - namespace: Some("ns".to_string()), - timestamp: None, - tags: Some( + let event = Event::Metric( + Metric::new( + metric.to_string(), + MetricKind::Incremental, + MetricValue::Counter { value: i as f64 }, + ) + .with_namespace(Some("ns".to_string())) + .with_tags(Some( vec![ ("region".to_owned(), "us-west-1".to_owned()), ("production".to_owned(), "true".to_owned()), ] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: i as f64 }, - }); + )), + ); events.push(event); } @@ -1007,20 +1000,21 @@ mod integration_tests { } fn create_event(i: i32) -> Event { - Event::Metric(Metric { - name: format!("counter-{}", i), - namespace: Some("ns".to_string()), - timestamp: None, - tags: Some( + Event::Metric( + Metric::new( + format!("counter-{}", i), + MetricKind::Incremental, + MetricValue::Counter { value: i as f64 }, + ) + .with_namespace(Some("ns".to_string())) + .with_tags(Some( vec![ ("region".to_owned(), "us-west-1".to_owned()), ("production".to_owned(), "true".to_owned()), ] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: i as f64 }, - }) + )), + ) } } diff --git a/src/sinks/kafka.rs b/src/sinks/kafka.rs index d111830ffb7b3..e552307772928 100644 --- a/src/sinks/kafka.rs +++ b/src/sinks/kafka.rs @@ -285,7 +285,7 @@ impl Sink for KafkaSink { Event::Log(log) => log .get(log_schema().timestamp_key()) .and_then(|v| v.as_timestamp()), - Event::Metric(metric) => metric.timestamp.as_ref(), + Event::Metric(metric) => metric.data.timestamp.as_ref(), } .map(|ts| ts.timestamp_millis()); let (key, body) = encode_event(item, &self.key_field, &self.encoding); @@ -403,8 +403,7 @@ fn encode_event( .and_then(|f| match &event { Event::Log(log) => log.get(f).map(|value| value.as_bytes().to_vec()), Event::Metric(metric) => metric - .tags - .as_ref() + .tags() .and_then(|tags| tags.get(f)) .map(|value| value.clone().into_bytes()), }) @@ -479,14 +478,11 @@ mod tests { #[test] fn kafka_encode_event_metric_text() { - let metric = Metric { - name: "kafka-metric".to_owned(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }; + let metric = Metric::new( + "kafka-metric".to_owned(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ); let (key_bytes, bytes) = encode_event( metric.clone().into(), &None, @@ -499,14 +495,11 @@ mod tests { #[test] fn kafka_encode_event_metric_json() { - let metric = Metric { - name: "kafka-metric".to_owned(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }; + let metric = Metric::new( + "kafka-metric".to_owned(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ); let (key_bytes, bytes) = encode_event( metric.clone().into(), &None, diff --git a/src/sinks/prometheus/collector.rs b/src/sinks/prometheus/collector.rs index dcfc840705b33..73e550f4d97df 100644 --- a/src/sinks/prometheus/collector.rs +++ b/src/sinks/prometheus/collector.rs @@ -20,7 +20,7 @@ pub(super) trait MetricCollector { name: &str, suffix: &str, value: f64, - tags: &Option>, + tags: Option<&BTreeMap>, extra: Option<(&str, String)>, ); @@ -34,19 +34,15 @@ pub(super) trait MetricCollector { expired: bool, metric: &Metric, ) { - let name = encode_namespace( - metric.namespace.as_deref().or(default_namespace), - '_', - &metric.name, - ); + let name = encode_namespace(metric.namespace().or(default_namespace), '_', metric.name()); let name = &name; - let timestamp = metric.timestamp.map(|t| t.timestamp_millis()); + let timestamp = metric.data.timestamp.map(|t| t.timestamp_millis()); - if metric.kind.is_absolute() { - let tags = &metric.tags; - self.emit_metadata(&metric.name, &name, &metric.value); + if metric.data.kind.is_absolute() { + let tags = metric.tags(); + self.emit_metadata(metric.name(), &name, &metric.data.value); - match &metric.value { + match &metric.data.value { MetricValue::Counter { value } => { self.emit_value(timestamp, &name, "", *value, tags, None); } @@ -212,7 +208,7 @@ impl MetricCollector for StringCollector { name: &str, suffix: &str, value: f64, - tags: &Option>, + tags: Option<&BTreeMap>, extra: Option<(&str, String)>, ) { let result = self @@ -237,7 +233,7 @@ impl MetricCollector for StringCollector { impl StringCollector { fn encode_tags( result: &mut String, - tags: &Option>, + tags: Option<&BTreeMap>, extra: Option<(&str, String)>, ) { match (tags, extra) { @@ -278,7 +274,7 @@ pub(super) struct TimeSeries { impl TimeSeries { fn make_labels( - tags: &Option>, + tags: Option<&BTreeMap>, name: &str, suffix: &str, extra: Option<(&str, String)>, @@ -287,7 +283,7 @@ impl TimeSeries { // contains all the labels from the source metric, plus the name // label for the actual metric name. For convenience below, an // optional extra tag is added. - let mut labels = tags.clone().unwrap_or_default(); + let mut labels = tags.cloned().unwrap_or_default(); labels.insert(METRIC_NAME_LABEL.into(), [name, suffix].join("")); if let Some((name, value)) = extra { labels.insert(name.into(), value); @@ -333,7 +329,7 @@ impl MetricCollector for TimeSeries { name: &str, suffix: &str, value: f64, - tags: &Option>, + tags: Option<&BTreeMap>, extra: Option<(&str, String)>, ) { self.buffer @@ -468,14 +464,12 @@ vector_hits{code="200"} 10 } fn encode_counter() -> T::Output { - let metric = Metric { - name: "hits".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 10.0 }, - }; + let metric = Metric::new( + "hits".to_owned(), + MetricKind::Absolute, + MetricValue::Counter { value: 10.0 }, + ) + .with_tags(Some(tags())); encode_one::(Some("vector"), &[], &[], false, &metric) } @@ -499,14 +493,12 @@ vector_temperature{code="200"} -1.1 } fn encode_gauge() -> T::Output { - let metric = Metric { - name: "temperature".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: -1.1 }, - }; + let metric = Metric::new( + "temperature".to_owned(), + MetricKind::Absolute, + MetricValue::Gauge { value: -1.1 }, + ) + .with_tags(Some(tags())); encode_one::(Some("vector"), &[], &[], false, &metric) } @@ -530,16 +522,13 @@ vector_users 1 } fn encode_set() -> T::Output { - let metric = Metric { - name: "users".to_owned(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Set { + let metric = Metric::new( + "users".to_owned(), + MetricKind::Absolute, + MetricValue::Set { values: vec!["foo".into()].into_iter().collect(), }, - }; + ); encode_one::(Some("vector"), &[], &[], false, &metric) } @@ -563,16 +552,13 @@ vector_users 0 } fn encode_expired_set() -> T::Output { - let metric = Metric { - name: "users".to_owned(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Set { + let metric = Metric::new( + "users".to_owned(), + MetricKind::Absolute, + MetricValue::Set { values: vec!["foo".into()].into_iter().collect(), }, - }; + ); encode_one::(Some("vector"), &[], &[], true, &metric) } @@ -610,17 +596,14 @@ vector_requests_count 8 } fn encode_distribution() -> T::Output { - let metric = Metric { - name: "requests".to_owned(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Distribution { + let metric = Metric::new( + "requests".to_owned(), + MetricKind::Absolute, + MetricValue::Distribution { samples: crate::samples![1.0 => 3, 2.0 => 3, 3.0 => 2], statistic: StatisticKind::Histogram, }, - }; + ); encode_one::(Some("vector"), &[0.0, 2.5, 5.0], &[], false, &metric) } @@ -658,18 +641,15 @@ vector_requests_count 6 } fn encode_histogram() -> T::Output { - let metric = Metric { - name: "requests".to_owned(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + let metric = Metric::new( + "requests".to_owned(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: crate::buckets![1.0 => 1, 2.1 => 2, 3.0 => 3], count: 6, sum: 12.5, }, - }; + ); encode_one::(Some("vector"), &[], &[], false, &metric) } @@ -705,18 +685,16 @@ ns_requests_count{code="200"} 6 } fn encode_summary() -> T::Output { - let metric = Metric { - name: "requests".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + let metric = Metric::new( + "requests".to_owned(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![0.01 => 1.5, 0.5 => 2.0, 0.99 => 3.0], count: 6, sum: 12.0, }, - }; + ) + .with_tags(Some(tags())); encode_one::(Some("ns"), &[], &[], false, &metric) } @@ -762,17 +740,15 @@ ns_requests_avg{code="200"} 1.875 } fn encode_distribution_summary() -> T::Output { - let metric = Metric { - name: "requests".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Distribution { + let metric = Metric::new( + "requests".to_owned(), + MetricKind::Absolute, + MetricValue::Distribution { samples: crate::samples![1.0 => 3, 2.0 => 3, 3.0 => 2], statistic: StatisticKind::Summary, }, - }; + ) + .with_tags(Some(tags())); encode_one::( Some("ns"), &[], @@ -803,17 +779,15 @@ temperature 2 1234567890123 fn encode_timestamp() -> T::Output { use chrono::{DateTime, NaiveDateTime, Utc}; - let metric = Metric { - name: "temperature".to_owned(), - namespace: None, - timestamp: Some(DateTime::::from_utc( - NaiveDateTime::from_timestamp(1234567890, 123456789), - Utc, - )), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 2.0 }, - }; + let metric = Metric::new( + "temperature".to_owned(), + MetricKind::Absolute, + MetricValue::Counter { value: 2.0 }, + ) + .with_timestamp(Some(DateTime::::from_utc( + NaiveDateTime::from_timestamp(1234567890, 123456789), + Utc, + ))); encode_one::(None, &[], &[], false, &metric) } } diff --git a/src/sinks/prometheus/exporter.rs b/src/sinks/prometheus/exporter.rs index 272c716a91338..fefe8afb99a4c 100644 --- a/src/sinks/prometheus/exporter.rs +++ b/src/sinks/prometheus/exporter.rs @@ -303,21 +303,21 @@ impl StreamSink for PrometheusExporter { .drain(..) .map(|(MetricEntry(mut metric), is_incremental_set)| { if is_incremental_set { - metric.reset(); + metric.data.reset(); } (MetricEntry(metric), is_incremental_set) }) .collect(); } - match item.kind { + match item.data.kind { MetricKind::Incremental => { let mut new = MetricEntry(item.to_absolute()); if let Some((MetricEntry(mut existing), _)) = metrics.map.remove_entry(&new) { - existing.add(&item); + existing.data.add(&item.data); new = MetricEntry(existing); } - metrics.map.insert(new, item.value.is_set()); + metrics.map.insert(new, item.data.value.is_set()); } MetricKind::Absolute => { let new = MetricEntry(item); @@ -336,7 +336,7 @@ impl StreamSink for PrometheusExporter { mod tests { use super::*; use crate::{ - event::{Metric, MetricValue}, + event::metric::{Metric, MetricData, MetricSeries, MetricValue}, http::HttpClient, test_util::{random_string, trace_init}, tls::MaybeTlsSettings, @@ -401,19 +401,13 @@ mod tests { pub fn create_metric(name: Option, value: MetricValue) -> (String, Event) { let name = name.unwrap_or_else(|| format!("vector_set_{}", random_string(16))); - let event = Metric { - name: name.clone(), - namespace: None, - timestamp: None, - tags: Some( + let event = Metric::new(name.clone(), MetricKind::Incremental, value) + .with_tags(Some( vec![("some_tag".to_owned(), "some_value".to_owned())] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value, - } - .into(); + )) + .into(); (name, event) } @@ -428,40 +422,50 @@ mod tests { let mut sink = PrometheusExporter::new(config, cx.acker()); - let m1 = Metric { - name: "absolute".to_string(), - namespace: None, - timestamp: None, - tags: Some( - vec![("tag1".to_owned(), "value1".to_owned())] - .into_iter() - .collect(), - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 32. }, - }; + let m1 = Metric::new( + "absolute".to_string(), + MetricKind::Absolute, + MetricValue::Counter { value: 32. }, + ) + .with_tags(Some( + vec![("tag1".to_owned(), "value1".to_owned())] + .into_iter() + .collect(), + )); let m2 = Metric { - tags: Some( - vec![("tag1".to_owned(), "value2".to_owned())] - .into_iter() - .collect(), - ), - ..m1.clone() + series: MetricSeries { + tags: Some( + vec![("tag1".to_owned(), "value2".to_owned())] + .into_iter() + .collect(), + ), + ..m1.series.clone() + }, + data: m1.data.clone(), }; let metrics = vec![ Event::Metric(Metric { - value: MetricValue::Counter { value: 32. }, - ..m1.clone() + series: m1.series.clone(), + data: MetricData { + value: MetricValue::Counter { value: 32. }, + ..m1.data.clone() + }, }), Event::Metric(Metric { - value: MetricValue::Counter { value: 33. }, - ..m2.clone() + series: m2.series.clone(), + data: MetricData { + value: MetricValue::Counter { value: 33. }, + ..m2.data.clone() + }, }), Event::Metric(Metric { - value: MetricValue::Counter { value: 40. }, - ..m1.clone() + series: m1.series.clone(), + data: MetricData { + value: MetricValue::Counter { value: 40. }, + ..m1.data.clone() + }, }), ]; @@ -472,12 +476,12 @@ mod tests { let map = &sink.metrics.read().unwrap().map; assert_eq!( - map.get_full(&MetricEntry(m1)).unwrap().1 .0.value, + map.get_full(&MetricEntry(m1)).unwrap().1 .0.data.value, MetricValue::Counter { value: 40. } ); assert_eq!( - map.get_full(&MetricEntry(m2)).unwrap().1 .0.value, + map.get_full(&MetricEntry(m2)).unwrap().1 .0.data.value, MetricValue::Counter { value: 33. } ); } diff --git a/src/sinks/prometheus/remote_write.rs b/src/sinks/prometheus/remote_write.rs index 8f385bb27220f..4befedab36a37 100644 --- a/src/sinks/prometheus/remote_write.rs +++ b/src/sinks/prometheus/remote_write.rs @@ -325,21 +325,18 @@ mod tests { } pub(super) fn create_event(name: String, value: f64) -> Event { - Event::Metric(Metric { - name, - namespace: None, - timestamp: Some(chrono::Utc::now()), - tags: Some( - vec![ - ("region".to_owned(), "us-west-1".to_owned()), - ("production".to_owned(), "true".to_owned()), - ] - .into_iter() - .collect(), - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - }) + Event::Metric( + Metric::new(name, MetricKind::Absolute, MetricValue::Gauge { value }) + .with_tags(Some( + vec![ + ("region".to_owned(), "us-west-1".to_owned()), + ("production".to_owned(), "true".to_owned()), + ] + .into_iter() + .collect(), + )) + .with_timestamp(Some(chrono::Utc::now())), + ) } } @@ -400,7 +397,7 @@ mod integration_tests { let metric = event.into_metric(); let result = query( url, - &format!(r#"SELECT * FROM "{}".."{}""#, database, &metric.name), + &format!(r#"SELECT * FROM "{}".."{}""#, database, metric.name()), ) .await; @@ -408,17 +405,18 @@ mod integration_tests { assert_eq!(metrics.len(), 1); let output = &metrics[0]; - match metric.value { + match metric.data.value { MetricValue::Gauge { value } => { assert_eq!(output["value"], Value::Number((value as u32).into())) } _ => panic!("Unhandled metric value, fix the test"), } - for (tag, value) in metric.tags.unwrap() { - assert_eq!(output[&tag], Value::String(value)); + for (tag, value) in metric.tags().unwrap() { + assert_eq!(output[&tag[..]], Value::String(value.to_string())); } let timestamp = strip_timestamp( metric + .data .timestamp .unwrap() .format("%Y-%m-%dT%H:%M:%S%.3fZ") diff --git a/src/sinks/sematext/metrics.rs b/src/sinks/sematext/metrics.rs index 6e84f4b92063c..dc0a072f6c95f 100644 --- a/src/sinks/sematext/metrics.rs +++ b/src/sinks/sematext/metrics.rs @@ -17,11 +17,7 @@ use http::{StatusCode, Uri}; use hyper::{Body, Request}; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; -use std::{ - collections::{BTreeMap, HashMap}, - future::ready, - task::Poll, -}; +use std::{collections::HashMap, future::ready, task::Poll}; use tower::Service; #[derive(Clone)] @@ -197,22 +193,24 @@ fn encode_events(token: &str, default_namespace: &str, events: Vec) -> S let mut output = String::new(); for event in events.into_iter() { let namespace = event + .series + .name .namespace - .unwrap_or_else(|| default_namespace.to_string()); - let label = event.name; - let ts = encode_timestamp(event.timestamp); + .unwrap_or_else(|| default_namespace.into()); + let label = event.series.name.name; + let ts = encode_timestamp(event.data.timestamp); // Authentication in Sematext is by inserting the token as a tag. - let mut tags = event.tags.clone().unwrap_or_else(BTreeMap::new); + let mut tags = event.series.tags.clone().unwrap_or_default(); tags.insert("token".into(), token.into()); - let (metric_type, fields) = match event.value { + let (metric_type, fields) = match event.data.value { MetricValue::Counter { value } => ("counter", to_fields(label, value)), MetricValue::Gauge { value } => ("gauge", to_fields(label, value)), _ => { emit!(SematextMetricsInvalidMetricReceived { - value: event.value, - kind: event.kind, + value: event.data.value, + kind: event.data.kind, }); continue; @@ -260,14 +258,13 @@ mod tests { #[test] fn test_encode_counter_event() { - let events = vec![Metric { - name: "pool.used".into(), - namespace: Some("jvm".into()), - timestamp: Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 0)), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 42.0 }, - }]; + let events = vec![Metric::new( + "pool.used".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 42.0 }, + ) + .with_namespace(Some("jvm".into())) + .with_timestamp(Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 0)))]; assert_eq!( "jvm,metric_type=counter,token=aaa pool.used=42 1597784400000000000", @@ -277,14 +274,12 @@ mod tests { #[test] fn test_encode_counter_event_no_namespace() { - let events = vec![Metric { - name: "used".into(), - namespace: None, - timestamp: Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 0)), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 42.0 }, - }]; + let events = vec![Metric::new( + "used".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 42.0 }, + ) + .with_timestamp(Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 0)))]; assert_eq!( "ns,metric_type=counter,token=aaa used=42 1597784400000000000", @@ -295,22 +290,20 @@ mod tests { #[test] fn test_encode_counter_multiple_events() { let events = vec![ - Metric { - name: "pool.used".into(), - namespace: Some("jvm".into()), - timestamp: Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 0)), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 42.0 }, - }, - Metric { - name: "pool.committed".into(), - namespace: Some("jvm".into()), - timestamp: Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 1)), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 18874368.0 }, - }, + Metric::new( + "pool.used".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 42.0 }, + ) + .with_namespace(Some("jvm".into())) + .with_timestamp(Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 0))), + Metric::new( + "pool.committed".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 18874368.0 }, + ) + .with_namespace(Some("jvm".into())) + .with_timestamp(Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, 1))), ]; assert_eq!( @@ -361,18 +354,20 @@ mod tests { let mut events = Vec::new(); for (i, (namespace, metric, val)) in metrics.iter().enumerate() { - let event = Event::from(Metric { - name: metric.to_string(), - namespace: Some(namespace.to_string()), - timestamp: Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, i as u32)), - tags: Some( + let event = Event::from( + Metric::new( + metric.to_string(), + MetricKind::Incremental, + MetricValue::Counter { value: *val as f64 }, + ) + .with_namespace(Some(namespace.to_string())) + .with_tags(Some( vec![("os.host".to_owned(), "somehost".to_owned())] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: *val as f64 }, - }); + )) + .with_timestamp(Some(Utc.ymd(2020, 8, 18).and_hms_nano(21, 0, 0, i as u32))), + ); events.push(event); } diff --git a/src/sinks/statsd.rs b/src/sinks/statsd.rs index 3d369432d82dc..18400ec84cb42 100644 --- a/src/sinks/statsd.rs +++ b/src/sinks/statsd.rs @@ -2,7 +2,7 @@ use crate::sinks::util::unix::UnixSinkConfig; use crate::{ config::{DataType, GenerateConfig, SinkConfig, SinkContext, SinkDescription}, - event::metric::{Metric, MetricKind, MetricValue, StatisticKind}, + event::metric::{Metric, MetricKind, MetricTags, MetricValue, StatisticKind}, internal_events::StatsdInvalidMetricReceived, sinks::util::{ encode_namespace, @@ -15,7 +15,6 @@ use crate::{ use futures::{future, stream, FutureExt, SinkExt, StreamExt, TryFutureExt}; use serde::{Deserialize, Serialize}; use std::{ - collections::BTreeMap, fmt::Display, net::{IpAddr, Ipv4Addr, SocketAddr}, task::{Context, Poll}, @@ -135,7 +134,7 @@ impl SinkConfig for StatsdSinkConfig { } } -fn encode_tags(tags: &BTreeMap) -> String { +fn encode_tags(tags: &MetricTags) -> String { let parts: Vec<_> = tags .iter() .map(|(name, value)| { @@ -157,7 +156,7 @@ fn push_event( metric_type: &str, sample_rate: Option, ) { - buf.push(format!("{}:{}|{}", metric.name, val, metric_type)); + buf.push(format!("{}:{}|{}", metric.name(), val, metric_type)); if let Some(sample_rate) = sample_rate { if sample_rate != 1 { @@ -165,7 +164,7 @@ fn push_event( } }; - if let Some(t) = &metric.tags { + if let Some(t) = metric.tags() { buf.push(format!("#{}", encode_tags(t))); }; } @@ -174,12 +173,12 @@ fn encode_event(event: Event, default_namespace: Option<&str>) -> Option let mut buf = Vec::new(); let metric = event.as_metric(); - match &metric.value { + match &metric.data.value { MetricValue::Counter { value } => { push_event(&mut buf, &metric, value, "c", None); } MetricValue::Gauge { value } => { - match metric.kind { + match metric.data.kind { MetricKind::Incremental => { push_event(&mut buf, &metric, format!("{:+}", value), "g", None) } @@ -208,19 +207,15 @@ fn encode_event(event: Event, default_namespace: Option<&str>) -> Option } _ => { emit!(StatsdInvalidMetricReceived { - value: &metric.value, - kind: &metric.kind, + value: &metric.data.value, + kind: &metric.data.kind, }); return None; } }; - let message = encode_namespace( - metric.namespace.as_deref().or(default_namespace), - '.', - buf.join("|"), - ); + let message = encode_namespace(metric.namespace().or(default_namespace), '.', buf.join("|")); let mut body: Vec = message.into_bytes(); body.push(b'\n'); @@ -260,7 +255,7 @@ mod test { crate::test_util::test_generate_config::(); } - fn tags() -> BTreeMap { + fn tags() -> MetricTags { vec![ ("normal_tag".to_owned(), "value".to_owned()), ("true_tag".to_owned(), "true".to_owned()), @@ -300,14 +295,12 @@ mod test { #[cfg(feature = "sources-statsd")] #[test] fn test_encode_counter() { - let metric1 = Metric { - name: "counter".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.5 }, - }; + let metric1 = Metric::new( + "counter".to_owned(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.5 }, + ) + .with_tags(Some(tags())); let event = Event::Metric(metric1.clone()); let frame = &encode_event(event, None).unwrap(); let metric2 = parse(from_utf8(&frame).unwrap().trim()).unwrap(); @@ -317,14 +310,11 @@ mod test { #[cfg(feature = "sources-statsd")] #[test] fn test_encode_absolute_counter() { - let metric1 = Metric { - name: "counter".to_owned(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.5 }, - }; + let metric1 = Metric::new( + "counter".to_owned(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.5 }, + ); let event = Event::Metric(metric1); let frame = &encode_event(event, None).unwrap(); // The statsd parser will parse the counter as Incremental, @@ -335,14 +325,12 @@ mod test { #[cfg(feature = "sources-statsd")] #[test] fn test_encode_gauge() { - let metric1 = Metric { - name: "gauge".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: -1.5 }, - }; + let metric1 = Metric::new( + "gauge".to_owned(), + MetricKind::Incremental, + MetricValue::Gauge { value: -1.5 }, + ) + .with_tags(Some(tags())); let event = Event::Metric(metric1.clone()); let frame = &encode_event(event, None).unwrap(); let metric2 = parse(from_utf8(&frame).unwrap().trim()).unwrap(); @@ -352,14 +340,12 @@ mod test { #[cfg(feature = "sources-statsd")] #[test] fn test_encode_absolute_gauge() { - let metric1 = Metric { - name: "gauge".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.5 }, - }; + let metric1 = Metric::new( + "gauge".to_owned(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.5 }, + ) + .with_tags(Some(tags())); let event = Event::Metric(metric1.clone()); let frame = &encode_event(event, None).unwrap(); let metric2 = parse(from_utf8(&frame).unwrap().trim()).unwrap(); @@ -369,17 +355,15 @@ mod test { #[cfg(feature = "sources-statsd")] #[test] fn test_encode_distribution() { - let metric1 = Metric { - name: "distribution".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let metric1 = Metric::new( + "distribution".to_owned(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![1.5 => 1], statistic: StatisticKind::Histogram, }, - }; + ) + .with_tags(Some(tags())); let event = Event::Metric(metric1.clone()); let frame = &encode_event(event, None).unwrap(); let metric2 = parse(from_utf8(&frame).unwrap().trim()).unwrap(); @@ -389,16 +373,14 @@ mod test { #[cfg(feature = "sources-statsd")] #[test] fn test_encode_set() { - let metric1 = Metric { - name: "set".to_owned(), - namespace: None, - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Set { + let metric1 = Metric::new( + "set".to_owned(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["abc".to_owned()].into_iter().collect(), }, - }; + ) + .with_tags(Some(tags())); let event = Event::Metric(metric1.clone()); let frame = &encode_event(event, None).unwrap(); let metric2 = parse(from_utf8(&frame).unwrap().trim()).unwrap(); @@ -429,25 +411,26 @@ mod test { let (sink, _healthcheck) = config.build(context).await.unwrap(); let events = vec![ - Event::Metric(Metric { - name: "counter".to_owned(), - namespace: Some("vector".into()), - timestamp: None, - tags: Some(tags()), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.5 }, - }), - Event::Metric(Metric { - name: "histogram".to_owned(), - namespace: Some("vector".into()), - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { - samples: crate::samples![2.0 => 100], - statistic: StatisticKind::Histogram, - }, - }), + Event::Metric( + Metric::new( + "counter".to_owned(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.5 }, + ) + .with_namespace(Some("vector".into())) + .with_tags(Some(tags())), + ), + Event::Metric( + Metric::new( + "histogram".to_owned(), + MetricKind::Incremental, + MetricValue::Distribution { + samples: crate::samples![2.0 => 100], + statistic: StatisticKind::Histogram, + }, + ) + .with_namespace(Some("vector".into())), + ), ]; let (mut tx, rx) = mpsc::channel(1); diff --git a/src/sinks/util/adaptive_concurrency/tests.rs b/src/sinks/util/adaptive_concurrency/tests.rs index b4d794df5228c..8a5508608b9a0 100644 --- a/src/sinks/util/adaptive_concurrency/tests.rs +++ b/src/sinks/util/adaptive_concurrency/tests.rs @@ -404,25 +404,25 @@ async fn run_test(params: TestParams) -> TestResults { let metrics = capture_metrics(&controller) .map(Event::into_metric) - .map(|event| (event.name.clone(), event)) + .map(|event| (event.name().to_string(), event)) .collect::>(); // Ensure basic statistics are captured, don't actually examine them assert!( - matches!(metrics.get("adaptive_concurrency_observed_rtt").unwrap().value, + matches!(metrics.get("adaptive_concurrency_observed_rtt").unwrap().data.value, MetricValue::Distribution { .. }) ); assert!( - matches!(metrics.get("adaptive_concurrency_averaged_rtt").unwrap().value, + matches!(metrics.get("adaptive_concurrency_averaged_rtt").unwrap().data.value, MetricValue::Distribution { .. }) ); if params.concurrency == Concurrency::Adaptive { assert!( - matches!(metrics.get("adaptive_concurrency_limit").unwrap().value, + matches!(metrics.get("adaptive_concurrency_limit").unwrap().data.value, MetricValue::Distribution { .. }) ); } assert!( - matches!(metrics.get("adaptive_concurrency_in_flight").unwrap().value, + matches!(metrics.get("adaptive_concurrency_in_flight").unwrap().data.value, MetricValue::Distribution { .. }) ); diff --git a/src/sinks/util/buffer/metrics.rs b/src/sinks/util/buffer/metrics.rs index 6ae80f5e617ea..7fa3b263aebe3 100644 --- a/src/sinks/util/buffer/metrics.rs +++ b/src/sinks/util/buffer/metrics.rs @@ -1,5 +1,5 @@ use crate::{ - event::metric::{Metric, MetricKind, MetricValue, Sample}, + event::metric::{Metric, MetricData, MetricKind, MetricValue, Sample}, sinks::util::batch::{Batch, BatchConfig, BatchError, BatchSettings, BatchSize, PushResult}, Event, }; @@ -19,20 +19,11 @@ impl Eq for MetricEntry {} impl Hash for MetricEntry { fn hash(&self, state: &mut H) { let metric = &self.0; - discriminant(&metric.value).hash(state); - metric.name.hash(state); - metric.namespace.hash(state); - metric.kind.hash(state); - - if let Some(tags) = &metric.tags { - let mut tags: Vec<_> = tags.iter().collect(); - tags.sort(); - for tag in tags { - tag.hash(state); - } - } + metric.series.hash(state); + metric.data.kind.hash(state); + discriminant(&metric.data.value).hash(state); - match &metric.value { + match &metric.data.value { MetricValue::AggregatedHistogram { buckets, .. } => { for bucket in buckets { bucket.upper_limit.to_bits().hash(state); @@ -53,12 +44,10 @@ impl PartialEq for MetricEntry { // This differs from a straightforward implementation of `eq` by // comparing only the "shape" bits (name, tags, and type) while // allowing the contained values to be different. - self.name == other.name - && self.namespace == other.namespace - && self.kind == other.kind - && self.tags == other.tags - && discriminant(&self.value) == discriminant(&other.value) - && match (&self.value, &other.value) { + self.series == other.series + && self.data.kind == other.data.kind + && discriminant(&self.data.value) == discriminant(&other.data.value) + && match (&self.data.value, &other.data.value) { ( MetricValue::AggregatedHistogram { buckets: buckets1, .. @@ -176,31 +165,35 @@ impl Batch for MetricBuffer { } else { let item = item.into_metric(); - match (item.kind, &item.value) { + match (item.data.kind, &item.data.value) { (MetricKind::Absolute, MetricValue::Counter { value }) => { let value = *value; let item = MetricEntry(item); if let Some(MetricEntry(Metric { - value: MetricValue::Counter { value: value0, .. }, + data: + MetricData { + value: MetricValue::Counter { value: value0, .. }, + .. + }, .. })) = self.state.get(&item) { // Counters are disaggregated. We take the previous value from the state // and emit the difference between previous and current as a Counter let delta = MetricEntry(Metric { - name: item.name.clone(), - namespace: item.namespace.clone(), - timestamp: item.timestamp, - tags: item.tags.clone(), - kind: MetricKind::Incremental, - value: MetricValue::Counter { - value: value - value0, + series: item.series.clone(), + data: MetricData { + timestamp: item.data.timestamp, + kind: MetricKind::Incremental, + value: MetricValue::Counter { + value: value - value0, + }, }, }); // The resulting Counters could be added up normally if let Some(MetricEntry(mut existing)) = self.metrics.take(&delta) { - existing.add(&item); + existing.data.add(&item.data); self.metrics.insert(MetricEntry(existing)); } else { self.metrics.insert(delta); @@ -213,7 +206,7 @@ impl Batch for MetricBuffer { (MetricKind::Incremental, MetricValue::Gauge { .. }) => { let new = MetricEntry(item.to_absolute()); if let Some(MetricEntry(mut existing)) = self.metrics.take(&new) { - existing.add(&item); + existing.data.add(&item.data); self.metrics.insert(MetricEntry(existing)); } else { // If the metric is not present in active batch, @@ -224,15 +217,15 @@ impl Batch for MetricBuffer { } else { // Otherwise we start from zero value Metric { - name: item.name.to_string(), - namespace: item.namespace.clone(), - timestamp: item.timestamp, - tags: item.tags.clone(), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, + series: item.series.clone(), + data: MetricData { + timestamp: item.data.timestamp, + kind: MetricKind::Absolute, + value: MetricValue::Gauge { value: 0.0 }, + }, } }; - initial.add(&item); + initial.data.add(&item.data); self.metrics.insert(MetricEntry(initial)); } } @@ -242,7 +235,7 @@ impl Batch for MetricBuffer { _ => { let new = MetricEntry(item); if let Some(MetricEntry(mut existing)) = self.metrics.take(&new) { - existing.add(&new); + existing.data.add(&new.data); self.metrics.insert(MetricEntry(existing)); } else { self.metrics.insert(new); @@ -260,9 +253,8 @@ impl Batch for MetricBuffer { fn fresh(&self) -> Self { let mut state = self.state.clone(); for entry in self.metrics.iter() { - if (entry.0.value.is_gauge() || entry.0.value.is_counter()) - && entry.0.kind.is_absolute() - { + let data = &entry.0.data; + if (data.value.is_gauge() || data.value.is_counter()) && data.kind.is_absolute() { state.replace(entry.clone()); } } @@ -275,9 +267,9 @@ impl Batch for MetricBuffer { .into_iter() .map(|e| { let mut metric = e.0; - if let MetricValue::Distribution { samples, statistic } = metric.value { + if let MetricValue::Distribution { samples, statistic } = metric.data.value { let samples = compress_distribution(samples); - metric.value = MetricValue::Distribution { samples, statistic }; + metric.data.value = MetricValue::Distribution { samples, statistic }; }; metric }) @@ -617,52 +609,40 @@ mod test { } fn sample_counter(num: usize, tagstr: &str, kind: MetricKind, value: f64) -> Metric { - Metric { - name: format!("counter-{}", num), - namespace: None, - timestamp: None, - tags: Some(tag(tagstr)), + Metric::new( + format!("counter-{}", num), kind, - value: MetricValue::Counter { value }, - } + MetricValue::Counter { value }, + ) + .with_tags(Some(tag(tagstr))) } fn sample_gauge(num: usize, kind: MetricKind, value: f64) -> Metric { - Metric { - name: format!("gauge-{}", num), - namespace: None, - timestamp: None, - tags: Some(tag("staging")), - kind, - value: MetricValue::Gauge { value }, - } + Metric::new(format!("gauge-{}", num), kind, MetricValue::Gauge { value }) + .with_tags(Some(tag("staging"))) } fn sample_set(num: usize, values: &[T]) -> Metric { - Metric { - name: format!("set-{}", num), - namespace: None, - timestamp: None, - tags: Some(tag("production")), - kind: MetricKind::Incremental, - value: MetricValue::Set { + Metric::new( + format!("set-{}", num), + MetricKind::Incremental, + MetricValue::Set { values: values.iter().map(|s| s.to_string()).collect(), }, - } + ) + .with_tags(Some(tag("production"))) } fn sample_distribution_histogram(num: u32, rate: u32) -> Metric { - Metric { - name: format!("dist-{}", num), - namespace: None, - timestamp: None, - tags: Some(tag("production")), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Metric::new( + format!("dist-{}", num), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![num as f64 => rate], statistic: StatisticKind::Histogram, }, - } + ) + .with_tags(Some(tag("production"))) } fn sample_aggregated_histogram( @@ -672,13 +652,10 @@ mod test { cfactor: u32, sum: f64, ) -> Metric { - Metric { - name: format!("buckets-{}", num), - namespace: None, - timestamp: None, - tags: Some(tag("production")), + Metric::new( + format!("buckets-{}", num), kind, - value: MetricValue::AggregatedHistogram { + MetricValue::AggregatedHistogram { buckets: crate::buckets![ 1.0 => cfactor, 2.0f64.powf(bpower) => cfactor * 2, @@ -687,17 +664,15 @@ mod test { count: 6 * cfactor, sum, }, - } + ) + .with_tags(Some(tag("production"))) } fn sample_aggregated_summary(factor: u32) -> Metric { - Metric { - name: format!("quantiles-{}", factor), - namespace: None, - timestamp: None, - tags: Some(tag("production")), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + Metric::new( + format!("quantiles-{}", factor), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![ 0.0 => factor as f64, 0.5 => factor as f64 * 2.0, @@ -706,6 +681,7 @@ mod test { count: 6 * factor, sum: 10.0, }, - } + ) + .with_tags(Some(tag("production"))) } } diff --git a/src/sources/apache_metrics/mod.rs b/src/sources/apache_metrics/mod.rs index 07992cd0981b5..7b330ba4408aa 100644 --- a/src/sources/apache_metrics/mod.rs +++ b/src/sources/apache_metrics/mod.rs @@ -189,14 +189,14 @@ fn apache_metrics( Utc::now(), Some(&tags), ) - .chain(vec![Ok(Metric { - name: "up".into(), - namespace: namespace.clone(), - timestamp: Some(Utc::now()), - tags: Some(tags.clone()), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - })]); + .chain(vec![Ok(Metric::new( + "up".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(namespace.clone()) + .with_tags(Some(tags.clone())) + .with_timestamp(Some(Utc::now())))]); let metrics = results .filter_map(|res| match res { @@ -223,14 +223,14 @@ fn apache_metrics( url: &sanitized_url, }); Some( - stream::iter(vec![Metric { - name: "up".into(), - namespace: namespace.clone(), - timestamp: Some(Utc::now()), - tags: Some(tags.clone()), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }]) + stream::iter(vec![Metric::new( + "up".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(namespace.clone()) + .with_tags(Some(tags.clone())) + .with_timestamp(Some(Utc::now()))]) .map(Event::Metric) .map(Ok), ) @@ -241,14 +241,14 @@ fn apache_metrics( url: &sanitized_url }); Some( - stream::iter(vec![Metric { - name: "up".into(), - namespace: namespace.clone(), - timestamp: Some(Utc::now()), - tags: Some(tags.clone()), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }]) + stream::iter(vec![Metric::new( + "up".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(namespace.clone()) + .with_tags(Some(tags.clone())) + .with_timestamp(Some(Utc::now()))]) .map(Event::Metric) .map(Ok), ) @@ -365,11 +365,11 @@ Scoreboard: ____S_____I______R____I_______KK___D__C__G_L____________W___________ .map(|e| e.into_metric()) .collect::>(); - match metrics.iter().find(|m| m.name == "up") { + match metrics.iter().find(|m| m.name() == "up") { Some(m) => { - assert_eq!(m.value, MetricValue::Gauge { value: 1.0 }); + assert_eq!(m.data.value, MetricValue::Gauge { value: 1.0 }); - match &m.tags { + match m.tags() { Some(tags) => { assert_eq!( tags.get("endpoint"), @@ -434,8 +434,8 @@ Scoreboard: ____S_____I______R____I_______KK___D__C__G_L____________W___________ // we still publish `up=1` for bad status codes following the pattern of the Prometheus exporter: // // https://github.com/Lusitaniae/apache_exporter/blob/712a6796fb84f741ef3cd562dc11418f2ee8b741/apache_exporter.go#L200 - match metrics.iter().find(|m| m.name == "up") { - Some(m) => assert_eq!(m.value, MetricValue::Gauge { value: 1.0 }), + match metrics.iter().find(|m| m.name() == "up") { + Some(m) => assert_eq!(m.data.value, MetricValue::Gauge { value: 1.0 }), None => error!(message = "Could not find up metric in.", metrics = ?metrics), } } @@ -470,8 +470,8 @@ Scoreboard: ____S_____I______R____I_______KK___D__C__G_L____________W___________ .map(|e| e.into_metric()) .collect::>(); - match metrics.iter().find(|m| m.name == "up") { - Some(m) => assert_eq!(m.value, MetricValue::Gauge { value: 0.0 }), + match metrics.iter().find(|m| m.name() == "up") { + Some(m) => assert_eq!(m.data.value, MetricValue::Gauge { value: 0.0 }), None => error!(message = "Could not find up metric in.", metrics = ?metrics), } } diff --git a/src/sources/apache_metrics/parser.rs b/src/sources/apache_metrics/parser.rs index 9821c314b70a6..fe466d9a007db 100644 --- a/src/sources/apache_metrics/parser.rs +++ b/src/sources/apache_metrics/parser.rs @@ -152,192 +152,222 @@ fn line_to_metrics<'a>( ) -> Option + 'a>, ParseError>> { StatusFieldStatistic::from_key_value(key, value).map(move |result| { result.map(move |statistic| match statistic { - StatusFieldStatistic::ServerUptimeSeconds(value) => Box::new(iter::once(Metric { - name: "uptime_seconds_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: tags.cloned(), - kind: MetricKind::Absolute, - value: MetricValue::Counter { - value: value as f64, - }, - })), - StatusFieldStatistic::TotalAccesses(value) => Box::new(iter::once(Metric { - name: "access_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: tags.cloned(), - kind: MetricKind::Absolute, - value: MetricValue::Counter { - value: value as f64, - }, - })), - StatusFieldStatistic::TotalKBytes(value) => Box::new(iter::once(Metric { - name: "sent_bytes_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: tags.cloned(), - kind: MetricKind::Absolute, - value: MetricValue::Counter { - value: (value * 1024) as f64, - }, - })), - StatusFieldStatistic::TotalDuration(value) => Box::new(iter::once(Metric { - name: "duration_seconds_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: tags.cloned(), - kind: MetricKind::Absolute, - value: MetricValue::Counter { - value: value as f64, - }, - })), - StatusFieldStatistic::CPUUser(value) => Box::new(iter::once(Metric { - name: "cpu_seconds_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + StatusFieldStatistic::ServerUptimeSeconds(value) => Box::new(iter::once( + Metric::new( + "uptime_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Counter { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags(tags.cloned()) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::TotalAccesses(value) => Box::new(iter::once( + Metric::new( + "access_total".into(), + MetricKind::Absolute, + MetricValue::Counter { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags(tags.cloned()) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::TotalKBytes(value) => Box::new(iter::once( + Metric::new( + "sent_bytes_total".into(), + MetricKind::Absolute, + MetricValue::Counter { + value: (value * 1024) as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags(tags.cloned()) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::TotalDuration(value) => Box::new(iter::once( + Metric::new( + "duration_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Counter { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags(tags.cloned()) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::CPUUser(value) => Box::new(iter::once( + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("type".to_string(), "user".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - })) + }) + .with_timestamp(Some(now)), + )) as Box>, - StatusFieldStatistic::CPUSystem(value) => Box::new(iter::once(Metric { - name: "cpu_seconds_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + StatusFieldStatistic::CPUSystem(value) => Box::new(iter::once( + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("type".to_string(), "system".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - })) + }) + .with_timestamp(Some(now)), + )) as Box>, - StatusFieldStatistic::CPUChildrenUser(value) => Box::new(iter::once(Metric { - name: "cpu_seconds_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + StatusFieldStatistic::CPUChildrenUser(value) => Box::new(iter::once( + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("type".to_string(), "children_user".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - })) + }) + .with_timestamp(Some(now)), + )) as Box>, - StatusFieldStatistic::CPUChildrenSystem(value) => Box::new(iter::once(Metric { - name: "cpu_seconds_total".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + StatusFieldStatistic::CPUChildrenSystem(value) => Box::new(iter::once( + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("type".to_string(), "children_system".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - })) + }) + .with_timestamp(Some(now)), + )) as Box>, - StatusFieldStatistic::CPULoad(value) => Box::new(iter::once(Metric { - name: "cpu_load".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: tags.cloned(), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - })) + StatusFieldStatistic::CPULoad(value) => Box::new(iter::once( + Metric::new( + "cpu_load".into(), + MetricKind::Absolute, + MetricValue::Gauge { value }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags(tags.cloned()) + .with_timestamp(Some(now)), + )) as Box>, - StatusFieldStatistic::IdleWorkers(value) => Box::new(iter::once(Metric { - name: "workers".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + StatusFieldStatistic::IdleWorkers(value) => Box::new(iter::once( + Metric::new( + "workers".into(), + MetricKind::Absolute, + MetricValue::Gauge { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("state".to_string(), "idle".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { - value: value as f64, - }, - })) + }) + .with_timestamp(Some(now)), + )) as Box>, - StatusFieldStatistic::BusyWorkers(value) => Box::new(iter::once(Metric { - name: "workers".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + StatusFieldStatistic::BusyWorkers(value) => Box::new(iter::once( + Metric::new( + "workers".into(), + MetricKind::Absolute, + MetricValue::Gauge { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("state".to_string(), "busy".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { - value: value as f64, - }, - })), - StatusFieldStatistic::ConnsTotal(value) => Box::new(iter::once(Metric { - name: "connections".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + }) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::ConnsTotal(value) => Box::new(iter::once( + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("state".to_string(), "total".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { - value: value as f64, - }, - })), - StatusFieldStatistic::ConnsAsyncWriting(value) => Box::new(iter::once(Metric { - name: "connections".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + }) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::ConnsAsyncWriting(value) => Box::new(iter::once( + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("state".to_string(), "writing".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { - value: value as f64, - }, - })), - StatusFieldStatistic::ConnsAsyncClosing(value) => Box::new(iter::once(Metric { - name: "connections".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + }) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::ConnsAsyncClosing(value) => Box::new(iter::once( + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("state".to_string(), "closing".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { - value: value as f64, - }, - })), - StatusFieldStatistic::ConnsAsyncKeepAlive(value) => Box::new(iter::once(Metric { - name: "connections".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { + }) + .with_timestamp(Some(now)), + )), + StatusFieldStatistic::ConnsAsyncKeepAlive(value) => Box::new(iter::once( + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { + value: value as f64, + }, + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ let mut tags = tags.cloned().unwrap_or_default(); tags.insert("state".to_string(), "keepalive".to_string()); Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { - value: value as f64, - }, - })), + }) + .with_timestamp(Some(now)), + )), StatusFieldStatistic::Scoreboard(value) => { let scores = value.chars().fold(HashMap::new(), |mut m, c| { *m.entry(c).or_insert(0u32) += 1; @@ -375,20 +405,20 @@ fn score_to_metric( state: &str, count: u32, ) -> Metric { - Metric { - name: "scoreboard".into(), - namespace: namespace.map(str::to_string), - timestamp: Some(now), - tags: { - let mut tags = tags.cloned().unwrap_or_default(); - tags.insert("state".to_string(), state.to_string()); - Some(tags) - }, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: count.into(), }, - } + ) + .with_namespace(namespace.map(str::to_string)) + .with_tags({ + let mut tags = tags.cloned().unwrap_or_default(); + tags.insert("state".to_string(), state.to_string()); + Some(tags) + }) + .with_timestamp(Some(now)) } #[derive(Debug)] @@ -508,155 +538,154 @@ Scoreboard: ____S_____I______R____I_______KK___D__C__G_L____________W___________ (metrics, errors) }, ); - metrics.sort_by(|a, b| (&a.name, &a.tags).cmp(&(&b.name, &b.tags))); + metrics.sort_by(|a, b| (a.name(), a.tags()).cmp(&(b.name(), b.tags()))); assert_eq!( metrics, vec![ - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "closing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "keepalive"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "total"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "writing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "closing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "dnslookup"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "finishing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "idle_cleanup"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 2.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "keepalive"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 2.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "logging"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "open"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 325.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "reading"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "sending"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "starting"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "waiting"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 64.0 }, - }, - Metric { - name: "uptime_seconds_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 12.0 }, - }, - Metric { - name: "workers".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "busy"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "workers".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "idle"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 74.0 }, - }, + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "closing"})) + .with_timestamp(Some(now)), + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "keepalive"})) + .with_timestamp(Some(now)), + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "total"})) + .with_timestamp(Some(now)), + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "writing"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "closing"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "dnslookup"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "finishing"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 2.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "idle_cleanup"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 2.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "keepalive"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "logging"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 325.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "open"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "reading"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "sending"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "starting"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 64.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "waiting"})) + .with_timestamp(Some(now)), + Metric::new( + "uptime_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 12.0 }, + ) + .with_namespace(Some("apache".into())) + .with_timestamp(Some(now)), + Metric::new( + "workers".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "busy"})) + .with_timestamp(Some(now)), + Metric::new( + "workers".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 74.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "idle"})) + .with_timestamp(Some(now)), ] ); assert_eq!(errors.len(), 0); @@ -718,219 +747,214 @@ Scoreboard: ____S_____I______R____I_______KK___D__C__G_L____________W___________ (metrics, errors) }, ); - metrics.sort_by(|a, b| (&a.name, &a.tags).cmp(&(&b.name, &b.tags))); + metrics.sort_by(|a, b| (a.name(), a.tags()).cmp(&(b.name(), b.tags()))); assert_eq!( metrics, vec![ - Metric { - name: "access_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 30.0 }, - }, - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "closing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "keepalive"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "total"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "writing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "cpu_load".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.846154 }, - }, - Metric { - name: "cpu_seconds_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"type" => "children_system"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "cpu_seconds_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"type" => "children_user"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.0 }, - }, - Metric { - name: "cpu_seconds_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"type" => "system"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.02 }, - }, - Metric { - name: "cpu_seconds_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"type" => "user"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.2 }, - }, - Metric { - name: "duration_seconds_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 11.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "closing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "dnslookup"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "finishing"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "idle_cleanup"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 2.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "keepalive"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 2.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "logging"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "open"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 325.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "reading"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "sending"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "starting"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "scoreboard".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "waiting"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 64.0 }, - }, - Metric { - name: "sent_bytes_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 222208.0 }, - }, - Metric { - name: "uptime_seconds_total".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 26.0 }, - }, - Metric { - name: "workers".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "busy"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "workers".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "idle"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 74.0 }, - }, + Metric::new( + "access_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 30.0 }, + ) + .with_namespace(Some("apache".into())) + .with_timestamp(Some(now)), + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "closing"})) + .with_timestamp(Some(now)), + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "keepalive"})) + .with_timestamp(Some(now)), + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "total"})) + .with_timestamp(Some(now)), + Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "writing"})) + .with_timestamp(Some(now)), + Metric::new( + "cpu_load".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.846154 }, + ) + .with_namespace(Some("apache".into())) + .with_timestamp(Some(now)), + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"type" => "children_system"})) + .with_timestamp(Some(now)), + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"type" => "children_user"})) + .with_timestamp(Some(now)), + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.02 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"type" => "system"})) + .with_timestamp(Some(now)), + Metric::new( + "cpu_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.2 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"type" => "user"})) + .with_timestamp(Some(now)), + Metric::new( + "duration_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 11.0 }, + ) + .with_namespace(Some("apache".into())) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "closing"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "dnslookup"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "finishing"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 2.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "idle_cleanup"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 2.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "keepalive"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "logging"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 325.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "open"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "reading"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "sending"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "starting"})) + .with_timestamp(Some(now)), + Metric::new( + "scoreboard".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 64.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "waiting"})) + .with_timestamp(Some(now)), + Metric::new( + "sent_bytes_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 222208.0 }, + ) + .with_namespace(Some("apache".into())) + .with_timestamp(Some(now)), + Metric::new( + "uptime_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 26.0 }, + ) + .with_namespace(Some("apache".into())) + .with_timestamp(Some(now)), + Metric::new( + "workers".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "busy"})) + .with_timestamp(Some(now)), + Metric::new( + "workers".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 74.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "idle"})) + .with_timestamp(Some(now)), ] ); assert_eq!(errors.len(), 0); @@ -955,18 +979,18 @@ ConnsTotal: 1 (metrics, errors) }, ); - metrics.sort_by(|a, b| (&a.name, &a.tags).cmp(&(&b.name, &b.tags))); + metrics.sort_by(|a, b| (a.name(), a.tags()).cmp(&(b.name(), b.tags()))); assert_eq!( metrics, - vec![Metric { - name: "connections".into(), - namespace: Some("apache".into()), - timestamp: Some(now), - tags: Some(map! {"state" => "total"}), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - },] + vec![Metric::new( + "connections".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_namespace(Some("apache".into())) + .with_tags(Some(map! {"state" => "total"})) + .with_timestamp(Some(now)),] ); assert_eq!(errors.len(), 1); } diff --git a/src/sources/aws_ecs_metrics/mod.rs b/src/sources/aws_ecs_metrics/mod.rs index a819c7a028e84..df9f0751acb7c 100644 --- a/src/sources/aws_ecs_metrics/mod.rs +++ b/src/sources/aws_ecs_metrics/mod.rs @@ -539,13 +539,13 @@ mod test { match metrics .iter() - .find(|m| m.name == "network_receive_bytes_total") + .find(|m| m.name() == "network_receive_bytes_total") { Some(m) => { - assert_eq!(m.value, MetricValue::Counter { value: 329932716.0 }); - assert_eq!(m.namespace, Some("awsecs".into())); + assert_eq!(m.data.value, MetricValue::Counter { value: 329932716.0 }); + assert_eq!(m.namespace(), Some("awsecs")); - match &m.tags { + match m.tags() { Some(tags) => { assert_eq!(tags.get("device"), Some(&"eth1".to_string())); } diff --git a/src/sources/aws_ecs_metrics/parser.rs b/src/sources/aws_ecs_metrics/parser.rs index 26a0277985ce2..290ccf44ba29d 100644 --- a/src/sources/aws_ecs_metrics/parser.rs +++ b/src/sources/aws_ecs_metrics/parser.rs @@ -122,14 +122,14 @@ fn counter( value: f64, tags: BTreeMap, ) -> Metric { - Metric { - name: format!("{}_{}", prefix, name), - namespace, - timestamp: Some(timestamp), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value }, - tags: Some(tags), - } + Metric::new( + format!("{}_{}", prefix, name), + MetricKind::Absolute, + MetricValue::Counter { value }, + ) + .with_namespace(namespace) + .with_tags(Some(tags)) + .with_timestamp(Some(timestamp)) } fn gauge( @@ -140,14 +140,14 @@ fn gauge( value: f64, tags: BTreeMap, ) -> Metric { - Metric { - name: format!("{}_{}", prefix, name), - namespace, - timestamp: Some(timestamp), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - tags: Some(tags), - } + Metric::new( + format!("{}_{}", prefix, name), + MetricKind::Absolute, + MetricValue::Gauge { value }, + ) + .with_namespace(namespace) + .with_tags(Some(tags)) + .with_timestamp(Some(timestamp)) } fn blkio_tags(item: &BlockIoStat, tags: &BTreeMap) -> BTreeMap { @@ -537,46 +537,46 @@ mod test { assert_eq!( parse(json.as_bytes(), namespace()).unwrap(), vec![ - Metric { - name: "blkio_recursive_io_service_bytes_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ("device".into(), "202:26368".into()), - ("op".into(), "read".into()), - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }, - Metric { - name: "blkio_recursive_io_service_bytes_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ("device".into(), "202:26368".into()), - ("op".into(), "write".into()), - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 520192.0 }, - }, + Metric::new( + "blkio_recursive_io_service_bytes_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ("device".into(), "202:26368".into()), + ("op".into(), "read".into()), + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "blkio_recursive_io_service_bytes_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 520192.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ("device".into(), "202:26368".into()), + ("op".into(), "write".into()), + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ], ); } @@ -615,196 +615,196 @@ mod test { assert_eq!( parse(json.as_bytes(), namespace()).unwrap(), vec![ - Metric { - name: "cpu_online_cpus".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 2.0 }, - }, - Metric { - name: "cpu_usage_system_jiffies_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { + Metric::new( + "cpu_online_cpus".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 2.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_usage_system_jiffies_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 2007130000000.0 }, - }, - Metric { - name: "cpu_usage_usermode_jiffies_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 510000000.0 }, - }, - Metric { - name: "cpu_usage_kernelmode_jiffies_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 190000000.0 }, - }, - Metric { - name: "cpu_usage_total_jiffies_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_usage_usermode_jiffies_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 510000000.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_usage_kernelmode_jiffies_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 190000000.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_usage_total_jiffies_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 2324920942.0 }, - }, - Metric { - name: "cpu_throttling_periods_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }, - Metric { - name: "cpu_throttled_periods_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }, - Metric { - name: "cpu_throttled_time_seconds_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }, - Metric { - name: "cpu_usage_percpu_jiffies_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ("cpu".into(), "0".into()), - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_throttling_periods_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_throttled_periods_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_throttled_time_seconds_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_usage_percpu_jiffies_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1095931487.0 }, - }, - Metric { - name: "cpu_usage_percpu_jiffies_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ("cpu".into(), "1".into()), - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ("cpu".into(), "0".into()), + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), + Metric::new( + "cpu_usage_percpu_jiffies_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1228989455.0 }, - }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ("cpu".into(), "1".into()), + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ], ); } @@ -864,101 +864,101 @@ mod test { assert_eq!( metrics .iter() - .find(|m| m.name == "memory_used_bytes") + .find(|m| m.name() == "memory_used_bytes") .unwrap(), - &Metric { - name: "memory_used_bytes".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 40120320.0 }, - }, + &Metric::new( + "memory_used_bytes".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 40120320.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ); assert_eq!( metrics .iter() - .find(|m| m.name == "memory_max_used_bytes") + .find(|m| m.name() == "memory_max_used_bytes") .unwrap(), - &Metric { - name: "memory_max_used_bytes".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 47177728.0 }, - }, + &Metric::new( + "memory_max_used_bytes".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 47177728.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ); assert_eq!( metrics .iter() - .find(|m| m.name == "memory_active_anonymous_bytes") + .find(|m| m.name() == "memory_active_anonymous_bytes") .unwrap(), - &Metric { - name: "memory_active_anonymous_bytes".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 34885632.0 }, - }, + &Metric::new( + "memory_active_anonymous_bytes".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 34885632.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ); assert_eq!( metrics .iter() - .find(|m| m.name == "memory_total_page_faults_total") + .find(|m| m.name() == "memory_total_page_faults_total") .unwrap(), - &Metric { - name: "memory_total_page_faults_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 31131.0 }, - }, + &Metric::new( + "memory_total_page_faults_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 31131.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ); } @@ -990,53 +990,53 @@ mod test { assert_eq!( metrics .iter() - .find(|m| m.name == "network_receive_bytes_total") + .find(|m| m.name() == "network_receive_bytes_total") .unwrap(), - &Metric { - name: "network_receive_bytes_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ("device".into(), "eth1".into()), - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 329932716.0 }, - }, + &Metric::new( + "network_receive_bytes_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 329932716.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ("device".into(), "eth1".into()), + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ); assert_eq!( metrics .iter() - .find(|m| m.name == "network_transmit_bytes_total") + .find(|m| m.name() == "network_transmit_bytes_total") .unwrap(), - &Metric { - name: "network_transmit_bytes_total".into(), - namespace: namespace(), - timestamp: Some(ts()), - tags: Some( - vec![ - ("device".into(), "eth1".into()), - ( - "container_id".into(), - "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() - ), - ("container_name".into(), "vector2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 2001229.0 }, - }, + &Metric::new( + "network_transmit_bytes_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 2001229.0 }, + ) + .with_namespace(namespace()) + .with_tags(Some( + vec![ + ("device".into(), "eth1".into()), + ( + "container_id".into(), + "0cf54b87-f0f0-4044-b9d6-20dc54d5c414-4057181352".into() + ), + ("container_name".into(), "vector2".into()) + ] + .into_iter() + .collect() + )) + .with_timestamp(Some(ts())), ); } } diff --git a/src/sources/host_metrics.rs b/src/sources/host_metrics.rs index c18928dfda8ec..94b6efa3e2ae1 100644 --- a/src/sources/host_metrics.rs +++ b/src/sources/host_metrics.rs @@ -193,7 +193,7 @@ impl HostMetricsConfig { } if let Ok(hostname) = &hostname { for metric in &mut metrics { - (metric.tags.as_mut().unwrap()).insert("host".into(), hostname.into()); + (metric.series.tags.as_mut().unwrap()).insert("host".into(), hostname.into()); } } emit!(HostMetricsEventReceived { @@ -650,14 +650,14 @@ impl HostMetricsConfig { value: f64, tags: BTreeMap, ) -> Metric { - Metric { - name: name.into(), - namespace: self.namespace.0.clone(), - timestamp: Some(timestamp), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value }, - tags: Some(tags), - } + Metric::new( + name.into(), + MetricKind::Absolute, + MetricValue::Counter { value }, + ) + .with_namespace(self.namespace.0.clone()) + .with_tags(Some(tags)) + .with_timestamp(Some(timestamp)) } fn gauge( @@ -667,14 +667,14 @@ impl HostMetricsConfig { value: f64, tags: BTreeMap, ) -> Metric { - Metric { - name: name.into(), - namespace: self.namespace.0.clone(), - timestamp: Some(timestamp), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - tags: Some(tags), - } + Metric::new( + name.into(), + MetricKind::Absolute, + MetricValue::Gauge { value }, + ) + .with_namespace(self.namespace.0.clone()) + .with_tags(Some(tags)) + .with_timestamp(Some(timestamp)) } } @@ -686,7 +686,7 @@ async fn filter_result(result: Result, message: &'static str) -> Op fn add_collector(collector: &str, mut metrics: Vec) -> Vec { for metric in &mut metrics { - (metric.tags.as_mut().unwrap()).insert("collector".into(), collector.into()); + (metric.series.tags.as_mut().unwrap()).insert("collector".into(), collector.into()); } metrics } @@ -904,7 +904,7 @@ mod tests { let hostname = crate::get_hostname().expect("Broken hostname"); assert!(!metrics.any(|event| event .into_metric() - .tags + .tags() .expect("Missing tags") .get("host") .expect("Missing \"host\" tag") @@ -920,14 +920,14 @@ mod tests { .capture_metrics() .await; - assert!(metrics.all(|event| event.into_metric().namespace.as_deref() == Some("other"))); + assert!(metrics.all(|event| event.into_metric().namespace() == Some("other"))); } #[tokio::test] async fn uses_default_namespace() { let mut metrics = HostMetricsConfig::default().capture_metrics().await; - assert!(metrics.all(|event| event.into_metric().namespace.as_deref() == Some("host"))); + assert!(metrics.all(|event| event.into_metric().namespace() == Some("host"))); } #[tokio::test] @@ -1070,7 +1070,7 @@ mod tests { // All metrics are named network_* assert!(!metrics .iter() - .any(|metric| !metric.name.starts_with("network_"))); + .any(|metric| !metric.name().starts_with("network_"))); // They should all have a "device" tag assert_eq!(count_tag(&metrics, "device"), metrics.len()); @@ -1103,26 +1103,25 @@ mod tests { // All metrics are named load* assert!(!metrics .iter() - .any(|metric| !metric.name.starts_with("load"))); + .any(|metric| !metric.name().starts_with("load"))); } fn all_counters(metrics: &[Metric]) -> bool { !metrics .iter() - .any(|metric| !matches!(metric.value, MetricValue::Counter { .. })) + .any(|metric| !matches!(metric.data.value, MetricValue::Counter { .. })) } fn all_gauges(metrics: &[Metric]) -> bool { !metrics .iter() - .any(|metric| !matches!(metric.value, MetricValue::Gauge { .. })) + .any(|metric| !matches!(metric.data.value, MetricValue::Gauge { .. })) } fn all_tags_match(metrics: &[Metric], tag: &str, matches: impl Fn(&str) -> bool) -> bool { !metrics.iter().any(|metric| { metric - .tags - .as_ref() + .tags() .unwrap() .get(tag) .map(|value| !matches(value)) @@ -1131,7 +1130,10 @@ mod tests { } fn count_name(metrics: &[Metric], name: &str) -> usize { - metrics.iter().filter(|metric| metric.name == name).count() + metrics + .iter() + .filter(|metric| metric.name() == name) + .count() } fn count_tag(metrics: &[Metric], tag: &str) -> usize { @@ -1139,8 +1141,7 @@ mod tests { .iter() .filter(|metric| { metric - .tags - .as_ref() + .tags() .expect("Metric is missing tags") .contains_key(tag) }) @@ -1150,7 +1151,7 @@ mod tests { fn collect_tag_values(metrics: &[Metric], tag: &str) -> HashSet { metrics .iter() - .filter_map(|metric| metric.tags.as_ref().unwrap().get(tag).cloned()) + .filter_map(|metric| metric.tags().unwrap().get(tag).cloned()) .collect::>() } diff --git a/src/sources/internal_metrics.rs b/src/sources/internal_metrics.rs index 31c7df78db852..f6093bfea5a69 100644 --- a/src/sources/internal_metrics.rs +++ b/src/sources/internal_metrics.rs @@ -105,29 +105,32 @@ mod tests { let output = capture_metrics(&controller) .map(|event| { let m = event.into_metric(); - (m.name.clone(), m) + (m.name().to_string(), m) }) .collect::>(); - assert_eq!(MetricValue::Gauge { value: 2.0 }, output["foo"].value); - assert_eq!(MetricValue::Counter { value: 7.0 }, output["bar"].value); + assert_eq!(MetricValue::Gauge { value: 2.0 }, output["foo"].data.value); + assert_eq!( + MetricValue::Counter { value: 7.0 }, + output["bar"].data.value + ); assert_eq!( MetricValue::Distribution { samples: crate::samples![5.0 => 1, 6.0 => 1], statistic: StatisticKind::Histogram }, - output["baz"].value + output["baz"].data.value ); assert_eq!( MetricValue::Distribution { samples: crate::samples![7.0 => 1, 8.0 => 1], statistic: StatisticKind::Histogram }, - output["quux"].value + output["quux"].data.value ); let mut labels = BTreeMap::new(); labels.insert(String::from("host"), String::from("foo")); - assert_eq!(Some(labels), output["quux"].tags); + assert_eq!(Some(&labels), output["quux"].tags()); } } diff --git a/src/sources/mongodb_metrics/mod.rs b/src/sources/mongodb_metrics/mod.rs index 61148688dbc3f..f74f0bd62c6b2 100644 --- a/src/sources/mongodb_metrics/mod.rs +++ b/src/sources/mongodb_metrics/mod.rs @@ -288,14 +288,10 @@ impl MongoDBMetrics { value: MetricValue, tags: BTreeMap, ) -> Metric { - Metric { - name: name.into(), - namespace: self.namespace.clone(), - timestamp: Some(Utc::now()), - tags: Some(tags), - kind: MetricKind::Absolute, - value, - } + Metric::new(name.into(), MetricKind::Absolute, value) + .with_namespace(self.namespace.clone()) + .with_tags(Some(tags)) + .with_timestamp(Some(Utc::now())) } async fn collect(&self) -> stream::BoxStream<'static, Metric> { @@ -1084,12 +1080,12 @@ mod integration_tests { for event in events { let metric = event.into_metric(); // validate namespace - assert!(metric.namespace == Some(namespace.to_string())); + assert!(metric.namespace() == Some(namespace)); // validate timestamp - let timestamp = metric.timestamp.expect("existed timestamp"); + let timestamp = metric.data.timestamp.expect("existed timestamp"); assert!((timestamp - Utc::now()).num_seconds() < 1); // validate basic tags - let tags = metric.tags.expect("existed tags"); + let tags = metric.tags().expect("existed tags"); assert_eq!(tags.get("endpoint").map(String::as_ref), Some(endpoint)); assert_eq!(tags.get("host"), Some(&host)); } diff --git a/src/sources/nginx_metrics/mod.rs b/src/sources/nginx_metrics/mod.rs index 963bc372a8a71..7f1e4573bae3f 100644 --- a/src/sources/nginx_metrics/mod.rs +++ b/src/sources/nginx_metrics/mod.rs @@ -221,14 +221,10 @@ impl NginxMetrics { } fn create_metric(&self, name: &str, value: MetricValue) -> Metric { - Metric { - name: name.into(), - namespace: self.namespace.clone(), - timestamp: Some(Utc::now()), - tags: Some(self.tags.clone()), - kind: MetricKind::Absolute, - value, - } + Metric::new(name.into(), MetricKind::Absolute, value) + .with_namespace(self.namespace.clone()) + .with_tags(Some(self.tags.clone())) + .with_timestamp(Some(Utc::now())) } } diff --git a/src/sources/postgresql_metrics.rs b/src/sources/postgresql_metrics.rs index d40189d707546..ee2df456ba679 100644 --- a/src/sources/postgresql_metrics.rs +++ b/src/sources/postgresql_metrics.rs @@ -734,14 +734,10 @@ impl PostgresqlMetrics { value: MetricValue, tags: BTreeMap, ) -> Metric { - Metric { - name: name.into(), - namespace: self.namespace.clone(), - timestamp: Some(Utc::now()), - tags: Some(tags), - kind: MetricKind::Absolute, - value, - } + Metric::new(name.into(), MetricKind::Absolute, value) + .with_namespace(self.namespace.clone()) + .with_tags(Some(tags)) + .with_timestamp(Some(Utc::now())) } } @@ -918,8 +914,9 @@ mod integration_tests { events .iter() .map(|e| e.as_metric()) - .find(|e| e.name == "up") + .find(|e| e.name() == "up") .unwrap() + .data .value, gauge!(1) ); @@ -928,15 +925,12 @@ mod integration_tests { for event in &events { let metric = event.as_metric(); - assert_eq!(metric.namespace, Some("postgresql".to_owned())); + assert_eq!(metric.namespace(), Some("postgresql")); assert_eq!( - metric.tags.as_ref().unwrap().get("endpoint").unwrap(), + metric.tags().unwrap().get("endpoint").unwrap(), &tags_endpoint ); - assert_eq!( - metric.tags.as_ref().unwrap().get("host").unwrap(), - &tags_host - ); + assert_eq!(metric.tags().unwrap().get("host").unwrap(), &tags_host); } // test metrics from different queries @@ -946,7 +940,7 @@ mod integration_tests { "pg_stat_bgwriter_checkpoints_timed_total", ]; for name in names { - assert!(events.iter().any(|e| e.as_metric().name == name)); + assert!(events.iter().any(|e| e.as_metric().name() == name)); } events @@ -1000,7 +994,7 @@ mod integration_tests { for event in events { let metric = event.into_metric(); - if let Some(db) = metric.tags.unwrap().get("db") { + if let Some(db) = metric.tags().unwrap().get("db") { assert!(db == "vector" || db == "postgres"); } } @@ -1019,7 +1013,7 @@ mod integration_tests { for event in events { let metric = event.into_metric(); - if let Some(db) = metric.tags.unwrap().get("db") { + if let Some(db) = metric.tags().unwrap().get("db") { assert!(db != "vector" && db != "postgres"); } } @@ -1049,7 +1043,7 @@ mod integration_tests { for event in events { let metric = event.into_metric(); - if let Some(db) = metric.tags.unwrap().get("db") { + if let Some(db) = metric.tags().unwrap().get("db") { assert!(db == "template1"); } } diff --git a/src/sources/prometheus/parser.rs b/src/sources/prometheus/parser.rs index 9b9b13f709a1c..03eb3f6f637d3 100644 --- a/src/sources/prometheus/parser.rs +++ b/src/sources/prometheus/parser.rs @@ -38,32 +38,28 @@ pub fn parse(packet: &str) -> Result, ParserError> { match group.metrics { GroupKind::Counter(vec) => { for metric in vec { - let counter = Metric { - name: group.name.clone(), - namespace: None, - timestamp: None, - tags: has_values_or_none(metric.labels), - kind: MetricKind::Absolute, - value: MetricValue::Counter { + let counter = Metric::new( + group.name.clone(), + MetricKind::Absolute, + MetricValue::Counter { value: metric.value, }, - }; + ) + .with_tags(has_values_or_none(metric.labels)); result.push(counter); } } GroupKind::Gauge(vec) | GroupKind::Untyped(vec) => { for metric in vec { - let gauge = Metric { - name: group.name.clone(), - namespace: None, - timestamp: None, - tags: has_values_or_none(metric.labels), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { + let gauge = Metric::new( + group.name.clone(), + MetricKind::Absolute, + MetricValue::Gauge { value: metric.value, }, - }; + ) + .with_tags(has_values_or_none(metric.labels)); result.push(gauge); } @@ -95,18 +91,16 @@ pub fn parse(packet: &str) -> Result, ParserError> { for i in (1..aggregate.buckets.len()).rev() { aggregate.buckets[i].count -= aggregate.buckets[i - 1].count; } - let hist = Metric { - name: group.name.clone(), - namespace: None, - timestamp: None, - tags: has_values_or_none(tags), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + let hist = Metric::new( + group.name.clone(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: aggregate.buckets, count: aggregate.count, sum: aggregate.sum, }, - }; + ) + .with_tags(has_values_or_none(tags)); result.push(hist); } @@ -133,18 +127,16 @@ pub fn parse(packet: &str) -> Result, ParserError> { } for (tags, aggregate) in aggregates { - let summary = Metric { - name: group.name.clone(), - namespace: None, - timestamp: None, - tags: has_values_or_none(tags), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + let summary = Metric::new( + group.name.clone(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: aggregate.quantiles, count: aggregate.count, sum: aggregate.sum, }, - }; + ) + .with_tags(has_values_or_none(tags)); result.push(summary); } @@ -183,14 +175,11 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "uptime".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 123.0 }, - }]), + Ok(vec![Metric::new( + "uptime".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 123.0 }, + )]), ); } @@ -211,7 +200,7 @@ mod test { name{labelname="val1",basename="basevalue"} NaN "##; - match parse(exp).unwrap()[0].value { + match parse(exp).unwrap()[0].data.value { MetricValue::Counter { value } => { assert!(value.is_nan()); } @@ -236,52 +225,46 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "name".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("labelname".into(), "val2".into()), - ("basename".into(), "base\"v\\al\nue".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.23 }, - }, - Metric { - name: "name2".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("labelname".into(), "val2".into()), - ("basename".into(), "basevalue2".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { + Metric::new( + "name".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.23 }, + ) + .with_tags(Some( + vec![ + ("labelname".into(), "val2".into()), + ("basename".into(), "base\"v\\al\nue".into()) + ] + .into_iter() + .collect() + )), + Metric::new( + "name2".into(), + MetricKind::Absolute, + MetricValue::Counter { value: std::f64::INFINITY }, - }, - Metric { - name: "name2".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![("labelname".into(), "val1".into()),] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { + ) + .with_tags(Some( + vec![ + ("labelname".into(), "val2".into()), + ("basename".into(), "basevalue2".into()) + ] + .into_iter() + .collect() + )), + Metric::new( + "name2".into(), + MetricKind::Absolute, + MetricValue::Counter { value: std::f64::NEG_INFINITY }, - }, + ) + .with_tags(Some( + vec![("labelname".into(), "val1".into()),] + .into_iter() + .collect() + )), ]), ); } @@ -298,36 +281,32 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "http_requests_total".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("method".into(), "post".into()), - ("code".into(), "200".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1027.0 }, - }, - Metric { - name: "http_requests_total".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("method".into(), "post".into()), - ("code".into(), "400".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 3.0 }, - } + Metric::new( + "http_requests_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1027.0 }, + ) + .with_tags(Some( + vec![ + ("method".into(), "post".into()), + ("code".into(), "200".into()) + ] + .into_iter() + .collect() + )), + Metric::new( + "http_requests_total".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 3.0 }, + ) + .with_tags(Some( + vec![ + ("method".into(), "post".into()), + ("code".into(), "400".into()) + ] + .into_iter() + .collect() + )) ]), ); } @@ -342,14 +321,11 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "latency".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 123.0 }, - }]), + Ok(vec![Metric::new( + "latency".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 123.0 }, + )]), ); } @@ -361,14 +337,11 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "metric_without_timestamp_and_labels".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 12.47 }, - }]), + Ok(vec![Metric::new( + "metric_without_timestamp_and_labels".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 12.47 }, + )]), ); } @@ -380,14 +353,11 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "no_labels".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 3.0 }, - }]), + Ok(vec![Metric::new( + "no_labels".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 3.0 }, + )]), ); } @@ -399,23 +369,21 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "msdos_file_access_time_seconds".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("path".into(), "C:\\DIR\\FILE.TXT".into()), - ("error".into(), "Cannot find file:\n\"FILE.TXT\"".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { + Ok(vec![Metric::new( + "msdos_file_access_time_seconds".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1458255915.0 }, - }]), + ) + .with_tags(Some( + vec![ + ("path".into(), "C:\\DIR\\FILE.TXT".into()), + ("error".into(), "Cannot find file:\n\"FILE.TXT\"".into()) + ] + .into_iter() + .collect() + )),]), ); } @@ -428,14 +396,12 @@ mod test { "##; assert_eq!( parse(exp), - Ok(vec![Metric { - name: "name".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"tag" => "}"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }]), + Ok(vec![Metric::new( + "name".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"tag" => "}"}))]), ); } @@ -448,14 +414,12 @@ mod test { "##; assert_eq!( parse(exp), - Ok(vec![Metric { - name: "name".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"tag" => "a,b"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }]), + Ok(vec![Metric::new( + "name".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"tag" => "a,b"}))]), ); } @@ -468,14 +432,12 @@ mod test { "##; assert_eq!( parse(exp), - Ok(vec![Metric { - name: "name".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"tag" => "\\n"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }]), + Ok(vec![Metric::new( + "name".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"tag" => "\\n"}))]), ); } @@ -488,14 +450,12 @@ mod test { "##; assert_eq!( parse(exp), - Ok(vec![Metric { - name: "name".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"tag" => " * "}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 }, - }]), + Ok(vec![Metric::new( + "name".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"tag" => " * "}))]), ); } @@ -507,21 +467,19 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "telemetry_scrape_size_bytes_count".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("registry".into(), "default".into()), - ("content_type".into(), "text/plain; version=0.0.4".into()) - ] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1890.0 }, - }]), + Ok(vec![Metric::new( + "telemetry_scrape_size_bytes_count".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1890.0 }, + ) + .with_tags(Some( + vec![ + ("registry".into(), "default".into()), + ("content_type".into(), "text/plain; version=0.0.4".into()) + ] + .into_iter() + .collect() + ))]), ); } @@ -551,20 +509,18 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "something_weird".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![("problem".into(), "division by zero".into())] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { + Ok(vec![Metric::new( + "something_weird".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: std::f64::INFINITY }, - }]), + ) + .with_tags(Some( + vec![("problem".into(), "division by zero".into())] + .into_iter() + .collect() + ))]), ); } @@ -579,26 +535,24 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "latency".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![("env".into(), "production".into())] - .into_iter() - .collect() - ), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }, - Metric { - name: "latency".into(), - namespace: None, - timestamp: None, - tags: Some(vec![("env".into(), "testing".into())].into_iter().collect()), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 2.0 }, - } + Metric::new( + "latency".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_tags(Some( + vec![("env".into(), "production".into())] + .into_iter() + .collect() + )), + Metric::new( + "latency".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 2.0 }, + ) + .with_tags(Some( + vec![("env".into(), "testing".into())].into_iter().collect() + )) ]), ); } @@ -617,30 +571,21 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "uptime".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 123.0 }, - }, - Metric { - name: "temperature".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: -1.5 }, - }, - Metric { - name: "launch_count".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 10.0 }, - } + Metric::new( + "uptime".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 123.0 }, + ), + Metric::new( + "temperature".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: -1.5 }, + ), + Metric::new( + "launch_count".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 10.0 }, + ) ]), ); } @@ -679,38 +624,26 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "uptime".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 123.0 }, - }, - Metric { - name: "last_downtime".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 4.0 }, - }, - Metric { - name: "temperature".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: -1.5 }, - }, - Metric { - name: "temperature_7_days_average".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 0.1 }, - } + Metric::new( + "uptime".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 123.0 }, + ), + Metric::new( + "last_downtime".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 4.0 }, + ), + Metric::new( + "temperature".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: -1.5 }, + ), + Metric::new( + "temperature_7_days_average".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 0.1 }, + ) ]), ); } @@ -732,20 +665,17 @@ mod test { assert_eq!( parse(exp), - Ok(vec![Metric { - name: "http_request_duration_seconds".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + Ok(vec![Metric::new( + "http_request_duration_seconds".into(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: crate::buckets![ 0.05 => 24054, 0.1 => 9390, 0.2 => 66948, 0.5 => 28997, 1.0 => 4599 ], count: 144320, sum: 53423.0, }, - }]), + )]), ); } @@ -798,13 +728,8 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "gitlab_runner_job_duration_seconds".into(), - namespace: None, - timestamp: None, - tags: Some(vec![("runner".into(), "z".into())].into_iter().collect()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + Metric::new( + "gitlab_runner_job_duration_seconds".into(), MetricKind::Absolute, MetricValue::AggregatedHistogram { buckets: crate::buckets![ 30.0 => 327, 60.0 => 147, @@ -820,14 +745,9 @@ mod test { count: 536, sum: 19690.129384881966, }, - }, - Metric { - name: "gitlab_runner_job_duration_seconds".into(), - namespace: None, - timestamp: None, - tags: Some(vec![("runner".into(), "x".into())].into_iter().collect()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + ).with_tags(Some(vec![("runner".into(), "z".into())].into_iter().collect())), + Metric::new( + "gitlab_runner_job_duration_seconds".into(), MetricKind::Absolute, MetricValue::AggregatedHistogram { buckets: crate::buckets![ 30.0 => 1, 60.0 => 0, @@ -843,14 +763,9 @@ mod test { count: 1, sum: 28.975436316, }, - }, - Metric { - name: "gitlab_runner_job_duration_seconds".into(), - namespace: None, - timestamp: None, - tags: Some(vec![("runner".into(), "y".into())].into_iter().collect()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + ).with_tags(Some(vec![("runner".into(), "x".into())].into_iter().collect())), + Metric::new( + "gitlab_runner_job_duration_seconds".into(), MetricKind::Absolute, MetricValue::AggregatedHistogram { buckets: crate::buckets![ 30.0 => 285, 60.0 => 880, 300.0 => 1906, 600.0 => 80, 1800.0 => 101, 3600.0 => 3, 7200.0 => 0, 10800.0 => 0, 18000.0 => 0, 36000.0 => 0 @@ -858,7 +773,7 @@ mod test { count: 3255, sum: 381111.7498891335, }, - } + ).with_tags(Some(vec![("runner".into(), "y".into())].into_iter().collect())) ]), ); } @@ -889,13 +804,10 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "rpc_duration_seconds".into(), - namespace: None, - timestamp: None, - tags: Some(vec![("service".into(), "a".into())].into_iter().collect()), - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + Metric::new( + "rpc_duration_seconds".into(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![ 0.01 => 3102.0, 0.05 => 3272.0, @@ -906,14 +818,14 @@ mod test { count: 2693, sum: 1.7560473e+07, }, - }, - Metric { - name: "go_gc_duration_seconds".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + ) + .with_tags(Some( + vec![("service".into(), "a".into())].into_iter().collect() + )), + Metric::new( + "go_gc_duration_seconds".into(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![ 0.0 => 0.009460965, 0.25 => 0.009793382, @@ -924,7 +836,7 @@ mod test { count: 602767, sum: 4668.551713715, }, - }, + ), ]), ); } @@ -954,102 +866,82 @@ mod test { assert_eq!( parse(exp), Ok(vec![ - Metric { - name: "nginx_server_bytes".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"direction" => "in", "host" => "*"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 263719.0 } - }, - Metric { - name: "nginx_server_bytes".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"direction" => "in", "host" => "_"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 255061.0 } - }, - Metric { - name: "nginx_server_bytes".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"direction" => "in", "host" => "nginx-vts-status"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 8658.0 } - }, - Metric { - name: "nginx_server_bytes".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"direction" => "out", "host" => "*"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 944199.0 } - }, - Metric { - name: "nginx_server_bytes".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"direction" => "out", "host" => "_"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 360775.0 } - }, - Metric { - name: "nginx_server_bytes".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"direction" => "out", "host" => "nginx-vts-status"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 583424.0 } - }, - Metric { - name: "nginx_server_cache".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"host" => "*", "status" => "bypass"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 } - }, - Metric { - name: "nginx_server_cache".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"host" => "*", "status" => "expired"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 } - }, - Metric { - name: "nginx_server_cache".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"host" => "*", "status" => "hit"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 } - }, - Metric { - name: "nginx_server_cache".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"host" => "*", "status" => "miss"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 } - }, - Metric { - name: "nginx_server_cache".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"host" => "*", "status" => "revalidated"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 } - }, - Metric { - name: "nginx_server_cache".into(), - namespace: None, - timestamp: None, - tags: Some(map! {"host" => "*", "status" => "scarce"}), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.0 } - } + Metric::new( + "nginx_server_bytes".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 263719.0 }, + ) + .with_tags(Some(map! {"direction" => "in", "host" => "*"})), + Metric::new( + "nginx_server_bytes".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 255061.0 }, + ) + .with_tags(Some(map! {"direction" => "in", "host" => "_"})), + Metric::new( + "nginx_server_bytes".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 8658.0 }, + ) + .with_tags(Some( + map! {"direction" => "in", "host" => "nginx-vts-status"} + )), + Metric::new( + "nginx_server_bytes".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 944199.0 }, + ) + .with_tags(Some(map! {"direction" => "out", "host" => "*"})), + Metric::new( + "nginx_server_bytes".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 360775.0 }, + ) + .with_tags(Some(map! {"direction" => "out", "host" => "_"})), + Metric::new( + "nginx_server_bytes".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 583424.0 }, + ) + .with_tags(Some( + map! {"direction" => "out", "host" => "nginx-vts-status"} + )), + Metric::new( + "nginx_server_cache".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"host" => "*", "status" => "bypass"})), + Metric::new( + "nginx_server_cache".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"host" => "*", "status" => "expired"})), + Metric::new( + "nginx_server_cache".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"host" => "*", "status" => "hit"})), + Metric::new( + "nginx_server_cache".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"host" => "*", "status" => "miss"})), + Metric::new( + "nginx_server_cache".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"host" => "*", "status" => "revalidated"})), + Metric::new( + "nginx_server_cache".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.0 }, + ) + .with_tags(Some(map! {"host" => "*", "status" => "scarce"})) ]) ); } diff --git a/src/sources/prometheus/remote_write.rs b/src/sources/prometheus/remote_write.rs index 1ddd8b3594684..98a0b8762bd5c 100644 --- a/src/sources/prometheus/remote_write.rs +++ b/src/sources/prometheus/remote_write.rs @@ -130,15 +130,10 @@ fn decode_timeseries(timeseries: proto::TimeSeries) -> Option { emit!(PrometheusNoNameError); @@ -228,7 +223,7 @@ mod test { let mut output = test_util::collect_ready(rx).await; // The MetricBuffer used by the sink may reorder the metrics, so // put them back into order before comparing. - output.sort_unstable_by_key(|event| event.as_metric().name.clone()); + output.sort_unstable_by_key(|event| event.as_metric().name().to_owned()); assert_eq!(events, output); } @@ -237,14 +232,14 @@ mod test { (0..10) .map(|num| { let timestamp = Utc::now().trunc_subsecs(3); - Event::Metric(Metric { - name: format!("gauge_{}", num), - namespace: None, - timestamp: Some(timestamp), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: num as f64 }, - }) + Event::Metric( + Metric::new( + format!("gauge_{}", num), + MetricKind::Absolute, + MetricValue::Gauge { value: num as f64 }, + ) + .with_timestamp(Some(timestamp)), + ) }) .collect() } diff --git a/src/sources/prometheus/scrape.rs b/src/sources/prometheus/scrape.rs index 40435a8481ba9..14e483b3fa83e 100644 --- a/src/sources/prometheus/scrape.rs +++ b/src/sources/prometheus/scrape.rs @@ -429,24 +429,24 @@ mod integration_tests { let find_metric = |name: &str| { metrics .iter() - .find(|metric| metric.name == name) + .find(|metric| metric.name() == name) .unwrap_or_else(|| panic!("Missing metric {:?}", name)) }; // Sample some well-known metrics let build = find_metric("prometheus_build_info"); - assert!(matches!(build.kind, MetricKind::Absolute)); - assert!(matches!(build.value, MetricValue::Gauge { ..})); - assert!(build.tags.as_ref().unwrap().contains_key("branch")); - assert!(build.tags.as_ref().unwrap().contains_key("version")); + assert!(matches!(build.data.kind, MetricKind::Absolute)); + assert!(matches!(build.data.value, MetricValue::Gauge { ..})); + assert!(build.tags().unwrap().contains_key("branch")); + assert!(build.tags().unwrap().contains_key("version")); let queries = find_metric("prometheus_engine_queries"); - assert!(matches!(queries.kind, MetricKind::Absolute)); - assert!(matches!(queries.value, MetricValue::Gauge { .. })); + assert!(matches!(queries.data.kind, MetricKind::Absolute)); + assert!(matches!(queries.data.value, MetricValue::Gauge { .. })); let go_info = find_metric("go_info"); - assert!(matches!(go_info.kind, MetricKind::Absolute)); - assert!(matches!(go_info.value, MetricValue::Gauge { .. })); - assert!(go_info.tags.as_ref().unwrap().contains_key("version")); + assert!(matches!(go_info.data.kind, MetricKind::Absolute)); + assert!(matches!(go_info.data.value, MetricValue::Gauge { .. })); + assert!(go_info.tags().unwrap().contains_key("version")); } } diff --git a/src/sources/statsd/parser.rs b/src/sources/statsd/parser.rs index 30f0a19448d36..b537f33454e32 100644 --- a/src/sources/statsd/parser.rs +++ b/src/sources/statsd/parser.rs @@ -56,30 +56,23 @@ pub fn parse(packet: &str) -> Result { let metric = match metric_type { "c" => { let val: f64 = parts[0].parse()?; - Metric { + Metric::new( name, - namespace: None, - timestamp: None, - tags, - kind: MetricKind::Incremental, - value: MetricValue::Counter { + MetricKind::Incremental, + MetricValue::Counter { value: val * sample_rate, }, - } + ) + .with_tags(tags) } unit @ "h" | unit @ "ms" | unit @ "d" => { let val: f64 = parts[0].parse()?; - Metric { - name, - namespace: None, - timestamp: None, - tags, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Metric::new( + name, MetricKind::Incremental, MetricValue::Distribution { samples: crate::samples![convert_to_base_units(unit, val) => sample_rate as u32], statistic: convert_to_statistic(unit), }, - } + ).with_tags(tags) } "g" => { let value = if parts[0] @@ -94,36 +87,26 @@ pub fn parse(packet: &str) -> Result { }; match parse_direction(parts[0])? { - None => Metric { + None => Metric::new(name, MetricKind::Absolute, MetricValue::Gauge { value }) + .with_tags(tags), + Some(sign) => Metric::new( name, - namespace: None, - timestamp: None, - tags, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value }, - }, - Some(sign) => Metric { - name, - namespace: None, - timestamp: None, - tags, - kind: MetricKind::Incremental, - value: MetricValue::Gauge { + MetricKind::Incremental, + MetricValue::Gauge { value: value * sign, }, - }, + ) + .with_tags(tags), } } - "s" => Metric { + "s" => Metric::new( name, - namespace: None, - timestamp: None, - tags, - kind: MetricKind::Incremental, - value: MetricValue::Set { + MetricKind::Incremental, + MetricValue::Set { values: vec![parts[0].into()].into_iter().collect(), }, - }, + ) + .with_tags(tags), other => return Err(ParseError::UnknownMetricType(other.into())), }; Ok(metric) @@ -246,14 +229,11 @@ mod test { fn basic_counter() { assert_eq!( parse("foo:1|c"), - Ok(Metric { - name: "foo".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }), + Ok(Metric::new( + "foo".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + )), ); } @@ -261,21 +241,19 @@ mod test { fn tagged_counter() { assert_eq!( parse("foo:1|c|#tag1,tag2:value"), - Ok(Metric { - name: "foo".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("tag1".to_owned(), "true".to_owned()), - ("tag2".to_owned(), "value".to_owned()), - ] - .into_iter() - .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }), + Ok(Metric::new( + "foo".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_tags(Some( + vec![ + ("tag1".to_owned(), "true".to_owned()), + ("tag2".to_owned(), "value".to_owned()), + ] + .into_iter() + .collect(), + ))), ); } @@ -283,14 +261,11 @@ mod test { fn sampled_counter() { assert_eq!( parse("bar:2|c|@0.1"), - Ok(Metric { - name: "bar".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 20.0 }, - }), + Ok(Metric::new( + "bar".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 20.0 }, + )), ); } @@ -298,14 +273,11 @@ mod test { fn zero_sampled_counter() { assert_eq!( parse("bar:2|c|@0"), - Ok(Metric { - name: "bar".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 2.0 }, - }), + Ok(Metric::new( + "bar".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 2.0 }, + )), ); } @@ -313,17 +285,14 @@ mod test { fn sampled_timer() { assert_eq!( parse("glork:320|ms|@0.1"), - Ok(Metric { - name: "glork".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Ok(Metric::new( + "glork".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![0.320 => 10], statistic: StatisticKind::Histogram }, - }), + )), ); } @@ -331,25 +300,23 @@ mod test { fn sampled_tagged_histogram() { assert_eq!( parse("glork:320|h|@0.1|#region:us-west1,production,e:"), - Ok(Metric { - name: "glork".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("region".to_owned(), "us-west1".to_owned()), - ("production".to_owned(), "true".to_owned()), - ("e".to_owned(), "".to_owned()), - ] - .into_iter() - .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Ok(Metric::new( + "glork".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![320.0 => 10], statistic: StatisticKind::Histogram }, - }), + ) + .with_tags(Some( + vec![ + ("region".to_owned(), "us-west1".to_owned()), + ("production".to_owned(), "true".to_owned()), + ("e".to_owned(), "".to_owned()), + ] + .into_iter() + .collect(), + ))), ); } @@ -357,25 +324,23 @@ mod test { fn sampled_distribution() { assert_eq!( parse("glork:320|d|@0.1|#region:us-west1,production,e:"), - Ok(Metric { - name: "glork".into(), - namespace: None, - timestamp: None, - tags: Some( - vec![ - ("region".to_owned(), "us-west1".to_owned()), - ("production".to_owned(), "true".to_owned()), - ("e".to_owned(), "".to_owned()), - ] - .into_iter() - .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Ok(Metric::new( + "glork".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![320.0 => 10], statistic: StatisticKind::Summary }, - }), + ) + .with_tags(Some( + vec![ + ("region".to_owned(), "us-west1".to_owned()), + ("production".to_owned(), "true".to_owned()), + ("e".to_owned(), "".to_owned()), + ] + .into_iter() + .collect(), + ))), ); } @@ -383,14 +348,11 @@ mod test { fn simple_gauge() { assert_eq!( parse("gaugor:333|g"), - Ok(Metric { - name: "gaugor".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 333.0 }, - }), + Ok(Metric::new( + "gaugor".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 333.0 }, + )), ); } @@ -398,25 +360,19 @@ mod test { fn signed_gauge() { assert_eq!( parse("gaugor:-4|g"), - Ok(Metric { - name: "gaugor".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: -4.0 }, - }), + Ok(Metric::new( + "gaugor".into(), + MetricKind::Incremental, + MetricValue::Gauge { value: -4.0 }, + )), ); assert_eq!( parse("gaugor:+10|g"), - Ok(Metric { - name: "gaugor".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Gauge { value: 10.0 }, - }), + Ok(Metric::new( + "gaugor".into(), + MetricKind::Incremental, + MetricValue::Gauge { value: 10.0 }, + )), ); } @@ -424,16 +380,13 @@ mod test { fn sets() { assert_eq!( parse("uniques:765|s"), - Ok(Metric { - name: "uniques".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + Ok(Metric::new( + "uniques".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["765".into()].into_iter().collect() }, - }), + )), ); } diff --git a/src/sources/vector.rs b/src/sources/vector.rs index 14fe58023d84a..fc23bf4034e70 100644 --- a/src/sources/vector.rs +++ b/src/sources/vector.rs @@ -172,14 +172,11 @@ mod test { Event::from("sink"), Event::from("and"), Event::from("source"), - Event::Metric(Metric { - name: String::from("also test a metric"), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.0 }, - }), + Event::Metric(Metric::new( + String::from("also test a metric"), + MetricKind::Absolute, + MetricValue::Counter { value: 1.0 }, + )), ]; sink.run(stream::iter(events.clone())).await.unwrap(); diff --git a/src/transforms/add_tags.rs b/src/transforms/add_tags.rs index 16cd2c1dc8627..d0e76b527cab9 100644 --- a/src/transforms/add_tags.rs +++ b/src/transforms/add_tags.rs @@ -68,7 +68,7 @@ impl AddTags { impl FunctionTransform for AddTags { fn transform(&mut self, output: &mut Vec, mut event: Event) { if !self.tags.is_empty() { - let tags = &mut event.as_mut_metric().tags; + let tags = &mut event.as_mut_metric().series.tags; if tags.is_none() { *tags = Some(BTreeMap::new()); @@ -114,14 +114,11 @@ mod tests { #[test] fn add_tags() { - let event = Event::Metric(Metric { - name: "bar".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 10.0 }, - }); + let event = Event::Metric(Metric::new( + "bar".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 10.0 }, + )); let map: IndexMap = vec![ ("region".into(), "us-east-1".into()), @@ -132,7 +129,7 @@ mod tests { let mut transform = AddTags::new(map, true); let metric = transform.transform_one(event).unwrap().into_metric(); - let tags = metric.tags.unwrap(); + let tags = metric.tags().unwrap(); assert_eq!(tags.len(), 2); assert_eq!(tags.get("region"), Some(&"us-east-1".to_owned())); @@ -143,14 +140,14 @@ mod tests { fn add_tags_override() { let mut tags = BTreeMap::new(); tags.insert("region".to_string(), "us-east-1".to_string()); - let event = Event::Metric(Metric { - name: "bar".into(), - namespace: None, - timestamp: None, - tags: Some(tags), - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 10.0 }, - }); + let event = Event::Metric( + Metric::new( + "bar".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 10.0 }, + ) + .with_tags(Some(tags)), + ); let map: IndexMap = vec![("region".to_string(), "overridden".to_string())] .into_iter() @@ -159,7 +156,7 @@ mod tests { let mut transform = AddTags::new(map, false); let metric = transform.transform_one(event).unwrap().into_metric(); - let tags = metric.tags.unwrap(); + let tags = metric.tags().unwrap(); assert_eq!(tags.get("region"), Some(&"us-east-1".to_owned())); } diff --git a/src/transforms/log_to_metric.rs b/src/transforms/log_to_metric.rs index 835fd26774b3c..d254fa9bd7c20 100644 --- a/src/transforms/log_to_metric.rs +++ b/src/transforms/log_to_metric.rs @@ -229,14 +229,14 @@ fn to_metric(config: &MetricConfig, event: &Event) -> Result { let value = parse_field(&log, &hist.field)?; @@ -251,17 +251,17 @@ fn to_metric(config: &MetricConfig, event: &Event) -> Result 1], statistic: StatisticKind::Histogram, }, - }) + ) + .with_namespace(namespace) + .with_tags(tags) + .with_timestamp(timestamp)) } MetricConfig::Summary(summary) => { let value = parse_field(&log, &summary.field)?; @@ -276,17 +276,17 @@ fn to_metric(config: &MetricConfig, event: &Event) -> Result 1], statistic: StatisticKind::Summary, }, - }) + ) + .with_namespace(namespace) + .with_tags(tags) + .with_timestamp(timestamp)) } MetricConfig::Gauge(gauge) => { let value = parse_field(&log, &gauge.field)?; @@ -301,14 +301,12 @@ fn to_metric(config: &MetricConfig, event: &Event) -> Result { let value = log @@ -328,16 +326,16 @@ fn to_metric(config: &MetricConfig, event: &Event) -> Result 1], statistic: StatisticKind::Histogram }, - } + ) + .with_timestamp(Some(ts())) ); } @@ -789,17 +768,15 @@ mod tests { assert_eq!( metric.into_metric(), - Metric { - name: "response_time".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + Metric::new( + "response_time".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![2.5 => 1], statistic: StatisticKind::Summary }, - } + ) + .with_timestamp(Some(ts())) ); } } diff --git a/src/transforms/lua/v2/interop/event.rs b/src/transforms/lua/v2/interop/event.rs index bff9154f9ef50..b2fba3ddbe19e 100644 --- a/src/transforms/lua/v2/interop/event.rs +++ b/src/transforms/lua/v2/interop/event.rs @@ -81,14 +81,11 @@ mod test { #[test] fn to_lua_metric() { - let event = Event::Metric(Metric { - name: "example counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.57721566 }, - }); + let event = Event::Metric(Metric::new( + "example counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.57721566 }, + )); let assertions = vec![ "type(event) == 'table'", @@ -132,14 +129,11 @@ mod test { } } }"#; - let expected = Event::Metric(Metric { - name: "example counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.57721566 }, - }); + let expected = Event::Metric(Metric::new( + "example counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.57721566 }, + )); Lua::new().context(|ctx| { let event = ctx.load(lua_event).eval::().unwrap(); diff --git a/src/transforms/lua/v2/interop/metric.rs b/src/transforms/lua/v2/interop/metric.rs index e08395bd574e1..88606ae961b7d 100644 --- a/src/transforms/lua/v2/interop/metric.rs +++ b/src/transforms/lua/v2/interop/metric.rs @@ -59,16 +59,16 @@ impl<'a> ToLua<'a> for Metric { fn to_lua(self, ctx: LuaContext<'a>) -> LuaResult { let tbl = ctx.create_table()?; - tbl.set("name", self.name)?; - if let Some(ts) = self.timestamp { + tbl.set("name", self.name())?; + if let Some(ts) = self.data.timestamp { tbl.set("timestamp", timestamp_to_table(ctx, ts)?)?; } - if let Some(tags) = self.tags { + if let Some(tags) = self.series.tags { tbl.set("tags", tags)?; } - tbl.set("kind", self.kind)?; + tbl.set("kind", self.data.kind)?; - match self.value { + match self.data.value { MetricValue::Counter { value } => { let counter = ctx.create_table()?; counter.set("value", value)?; @@ -198,14 +198,9 @@ impl<'a> FromLua<'a> for Metric { }); }; - Ok(Metric { - name, - namespace: None, - timestamp, - tags, - kind, - value, - }) + Ok(Metric::new(name, kind, value) + .with_tags(tags) + .with_timestamp(timestamp)) } } @@ -228,18 +223,17 @@ mod test { #[test] fn to_lua_counter_full() { - let metric = Metric { - name: "example counter".into(), - namespace: None, - timestamp: Some(Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 11)), - tags: Some( - vec![("example tag".to_string(), "example value".to_string())] - .into_iter() - .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }; + let metric = Metric::new( + "example counter".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_tags(Some( + vec![("example tag".to_string(), "example value".to_string())] + .into_iter() + .collect(), + )) + .with_timestamp(Some(Utc.ymd(2018, 11, 14).and_hms_nano(8, 9, 10, 11))); let assertions = vec![ "type(metric) == 'table'", "metric.name == 'example counter'", @@ -261,14 +255,11 @@ mod test { #[test] fn to_lua_counter_minimal() { - let metric = Metric { - name: "example counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.57721566 }, - }; + let metric = Metric::new( + "example counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.57721566 }, + ); let assertions = vec![ "metric.timestamp == nil", "metric.tags == nil", @@ -280,32 +271,26 @@ mod test { #[test] fn to_lua_gauge() { - let metric = Metric { - name: "example gauge".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.6180339 }, - }; + let metric = Metric::new( + "example gauge".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.6180339 }, + ); let assertions = vec!["metric.gauge.value == 1.6180339", "metric.counter == nil"]; assert_metric(metric, assertions); } #[test] fn to_lua_set() { - let metric = Metric { - name: "example set".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + let metric = Metric::new( + "example set".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["value".into(), "another value".into()] .into_iter() .collect(), }, - }; + ); let assertions = vec![ "type(metric.set) == 'table'", "type(metric.set.values) == 'table'", @@ -318,17 +303,14 @@ mod test { #[test] fn to_lua_distribution() { - let metric = Metric { - name: "example distribution".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Distribution { + let metric = Metric::new( + "example distribution".into(), + MetricKind::Incremental, + MetricValue::Distribution { samples: crate::samples![1.0 => 10, 1.0 => 20], statistic: StatisticKind::Histogram, }, - }; + ); let assertions = vec![ "type(metric.distribution) == 'table'", "#metric.distribution.values == 2", @@ -343,18 +325,15 @@ mod test { #[test] fn to_lua_aggregated_histogram() { - let metric = Metric { - name: "example histogram".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::AggregatedHistogram { + let metric = Metric::new( + "example histogram".into(), + MetricKind::Incremental, + MetricValue::AggregatedHistogram { buckets: crate::buckets![1.0 => 20, 2.0 => 10, 4.0 => 45, 8.0 => 12], count: 87, sum: 975.2, }, - }; + ); let assertions = vec![ "type(metric.aggregated_histogram) == 'table'", "#metric.aggregated_histogram.buckets == 4", @@ -371,20 +350,17 @@ mod test { #[test] fn to_lua_aggregated_summary() { - let metric = Metric { - name: "example summary".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::AggregatedSummary { + let metric = Metric::new( + "example summary".into(), + MetricKind::Incremental, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![ 0.1 => 2.0, 0.25 => 3.0, 0.5 => 5.0, 0.75 => 8.0, 0.9 => 7.0, 0.99 => 9.0, 1.0 => 10.0 ], count: 197, sum: 975.2, }, - }; + ); let assertions = vec![ "type(metric.aggregated_summary) == 'table'", "#metric.aggregated_summary.quantiles == 7", @@ -405,14 +381,11 @@ mod test { value = 0.57721566 } }"#; - let expected = Metric { - name: "example counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 0.57721566 }, - }; + let expected = Metric::new( + "example counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 0.57721566 }, + ); Lua::new().context(|ctx| { assert_eq!(ctx.load(value).eval::().unwrap(), expected); }); @@ -438,18 +411,17 @@ mod test { value = 1 } }"#; - let expected = Metric { - name: "example counter".into(), - namespace: None, - timestamp: Some(Utc.ymd(2018, 11, 14).and_hms(8, 9, 10)), - tags: Some( - vec![("example tag".to_string(), "example value".to_string())] - .into_iter() - .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }; + let expected = Metric::new( + "example counter".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_tags(Some( + vec![("example tag".to_string(), "example value".to_string())] + .into_iter() + .collect(), + )) + .with_timestamp(Some(Utc.ymd(2018, 11, 14).and_hms(8, 9, 10))); Lua::new().context(|ctx| { assert_eq!(ctx.load(value).eval::().unwrap(), expected); }); @@ -463,14 +435,11 @@ mod test { value = 1.6180339 } }"#; - let expected = Metric { - name: "example gauge".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.6180339 }, - }; + let expected = Metric::new( + "example gauge".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.6180339 }, + ); Lua::new().context(|ctx| { assert_eq!(ctx.load(value).eval::().unwrap(), expected); }); @@ -484,18 +453,15 @@ mod test { values = { "value", "another value" } } }"#; - let expected = Metric { - name: "example set".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Set { + let expected = Metric::new( + "example set".into(), + MetricKind::Absolute, + MetricValue::Set { values: vec!["value".into(), "another value".into()] .into_iter() .collect(), }, - }; + ); Lua::new().context(|ctx| { assert_eq!(ctx.load(value).eval::().unwrap(), expected); }); @@ -511,17 +477,14 @@ mod test { statistic = "histogram" } }"#; - let expected = Metric { - name: "example distribution".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Distribution { + let expected = Metric::new( + "example distribution".into(), + MetricKind::Absolute, + MetricValue::Distribution { samples: crate::samples![1.0 => 10, 1.0 => 20], statistic: StatisticKind::Histogram, }, - }; + ); Lua::new().context(|ctx| { assert_eq!(ctx.load(value).eval::().unwrap(), expected); }); @@ -537,18 +500,15 @@ mod test { sum = 975.2 } }"#; - let expected = Metric { - name: "example histogram".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + let expected = Metric::new( + "example histogram".into(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: crate::buckets![1.0 => 20, 2.0 => 10, 4.0 => 45, 8.0 => 12], count: 87, sum: 975.2, }, - }; + ); Lua::new().context(|ctx| { assert_eq!(ctx.load(value).eval::().unwrap(), expected); }); @@ -565,20 +525,17 @@ mod test { sum = 975.2 } }"#; - let expected = Metric { - name: "example summary".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + let expected = Metric::new( + "example summary".into(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![ 0.1 => 2.0, 0.25 => 3.0, 0.5 => 5.0, 0.75 => 8.0, 0.9 => 7.0, 0.99 => 9.0, 1.0 => 10.0 ], count: 197, sum: 975.2, }, - }; + ); Lua::new().context(|ctx| { assert_eq!(ctx.load(value).eval::().unwrap(), expected); }); diff --git a/src/transforms/lua/v2/mod.rs b/src/transforms/lua/v2/mod.rs index 0403c1d6fb3c1..8525c671e1a9a 100644 --- a/src/transforms/lua/v2/mod.rs +++ b/src/transforms/lua/v2/mod.rs @@ -784,27 +784,21 @@ mod tests { ) .unwrap(); - let event = Event::Metric(Metric { - name: "example counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.0 }, - }); + let event = Event::Metric(Metric::new( + "example counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.0 }, + )); let in_stream = Box::pin(stream::iter(vec![event])); let mut out_stream = transform.transform(in_stream); let output = out_stream.next().await.unwrap(); - let expected = Event::Metric(Metric { - name: "example counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 2.0 }, - }); + let expected = Event::Metric(Metric::new( + "example counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 2.0 }, + )); assert_eq!(output, expected); Ok(()) diff --git a/src/transforms/metric_to_log.rs b/src/transforms/metric_to_log.rs index f34b8408e1f62..5bce6bd257138 100644 --- a/src/transforms/metric_to_log.rs +++ b/src/transforms/metric_to_log.rs @@ -139,14 +139,13 @@ mod tests { #[test] fn transform_counter() { - let counter = Metric { - name: "counter".into(), - namespace: None, - timestamp: Some(ts()), - tags: Some(tags()), - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.0 }, - }; + let counter = Metric::new( + "counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.0 }, + ) + .with_tags(Some(tags())) + .with_timestamp(Some(ts())); let log = do_transform(counter).unwrap(); let collected: Vec<_> = log.all_fields().collect(); @@ -166,14 +165,12 @@ mod tests { #[test] fn transform_gauge() { - let gauge = Metric { - name: "gauge".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Gauge { value: 1.0 }, - }; + let gauge = Metric::new( + "gauge".into(), + MetricKind::Absolute, + MetricValue::Gauge { value: 1.0 }, + ) + .with_timestamp(Some(ts())); let log = do_transform(gauge).unwrap(); let collected: Vec<_> = log.all_fields().collect(); @@ -191,16 +188,14 @@ mod tests { #[test] fn transform_set() { - let set = Metric { - name: "set".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Set { + let set = Metric::new( + "set".into(), + MetricKind::Absolute, + MetricValue::Set { values: vec!["one".into(), "two".into()].into_iter().collect(), }, - }; + ) + .with_timestamp(Some(ts())); let log = do_transform(set).unwrap(); let collected: Vec<_> = log.all_fields().collect(); @@ -219,17 +214,15 @@ mod tests { #[test] fn transform_distribution() { - let distro = Metric { - name: "distro".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Distribution { + let distro = Metric::new( + "distro".into(), + MetricKind::Absolute, + MetricValue::Distribution { samples: crate::samples![1.0 => 10, 2.0 => 20], statistic: StatisticKind::Histogram, }, - }; + ) + .with_timestamp(Some(ts())); let log = do_transform(distro).unwrap(); let collected: Vec<_> = log.all_fields().collect(); @@ -266,18 +259,16 @@ mod tests { #[test] fn transform_histogram() { - let histo = Metric { - name: "histo".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedHistogram { + let histo = Metric::new( + "histo".into(), + MetricKind::Absolute, + MetricValue::AggregatedHistogram { buckets: crate::buckets![1.0 => 10, 2.0 => 20], count: 30, sum: 50.0, }, - }; + ) + .with_timestamp(Some(ts())); let log = do_transform(histo).unwrap(); let collected: Vec<_> = log.all_fields().collect(); @@ -312,18 +303,16 @@ mod tests { #[test] fn transform_summary() { - let summary = Metric { - name: "summary".into(), - namespace: None, - timestamp: Some(ts()), - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::AggregatedSummary { + let summary = Metric::new( + "summary".into(), + MetricKind::Absolute, + MetricValue::AggregatedSummary { quantiles: crate::quantiles![50.0 => 10.0, 90.0 => 20.0], count: 30, sum: 50.0, }, - }; + ) + .with_timestamp(Some(ts())); let log = do_transform(summary).unwrap(); let collected: Vec<_> = log.all_fields().collect(); diff --git a/src/transforms/remap.rs b/src/transforms/remap.rs index d36d40bced700..d51a59de3557c 100644 --- a/src/transforms/remap.rs +++ b/src/transforms/remap.rs @@ -147,14 +147,11 @@ mod tests { #[test] fn check_remap_metric() { - let metric = Event::Metric(Metric { - name: "counter".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Absolute, - value: MetricValue::Counter { value: 1.0 }, - }); + let metric = Event::Metric(Metric::new( + "counter".into(), + MetricKind::Absolute, + MetricValue::Counter { value: 1.0 }, + )); let conf = RemapConfig { source: r#".tags.host = "zoobub" @@ -169,18 +166,19 @@ mod tests { let result = tform.transform_one(metric).unwrap(); assert_eq!( result, - Event::Metric(Metric { - name: "zork".into(), - namespace: Some("zerk".into()), - timestamp: None, - tags: Some({ + Event::Metric( + Metric::new( + "zork".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 1.0 }, + ) + .with_namespace(Some("zerk".into())) + .with_tags(Some({ let mut tags = BTreeMap::new(); tags.insert("host".into(), "zoobub".into()); tags - }), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 1.0 }, - }) + })) + ) ); } } diff --git a/src/transforms/remove_tags.rs b/src/transforms/remove_tags.rs index 2fd3ac4bf63ec..8393dab402b0d 100644 --- a/src/transforms/remove_tags.rs +++ b/src/transforms/remove_tags.rs @@ -54,7 +54,7 @@ impl RemoveTags { impl FunctionTransform for RemoveTags { fn transform(&mut self, output: &mut Vec, mut event: Event) { - let tags = &mut event.as_mut_metric().tags; + let tags = &mut event.as_mut_metric().series.tags; if let Some(map) = tags { for tag in &self.tags { @@ -86,11 +86,13 @@ mod tests { #[test] fn remove_tags() { - let event = Event::Metric(Metric { - name: "foo".into(), - namespace: None, - timestamp: None, - tags: Some( + let event = Event::Metric( + Metric::new( + "foo".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 10.0 }, + ) + .with_tags(Some( vec![ ("env".to_owned(), "production".to_owned()), ("region".to_owned(), "us-east-1".to_owned()), @@ -98,14 +100,12 @@ mod tests { ] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 10.0 }, - }); + )), + ); let mut transform = RemoveTags::new(vec!["region".into(), "host".into()]); let metric = transform.transform_one(event).unwrap().into_metric(); - let tags = metric.tags.unwrap(); + let tags = metric.tags().unwrap(); assert_eq!(tags.len(), 1); assert!(tags.contains_key("env")); @@ -115,41 +115,38 @@ mod tests { #[test] fn remove_all_tags() { - let event = Event::Metric(Metric { - name: "foo".into(), - namespace: None, - timestamp: None, - tags: Some( + let event = Event::Metric( + Metric::new( + "foo".into(), + MetricKind::Incremental, + MetricValue::Counter { value: 10.0 }, + ) + .with_tags(Some( vec![("env".to_owned(), "production".to_owned())] .into_iter() .collect(), - ), - kind: MetricKind::Incremental, - value: MetricValue::Counter { value: 10.0 }, - }); + )), + ); let mut transform = RemoveTags::new(vec!["env".into()]); let metric = transform.transform_one(event).unwrap().into_metric(); - assert!(metric.tags.is_none()); + assert!(metric.tags().is_none()); } #[test] fn remove_tags_from_none() { - let event = Event::Metric(Metric { - name: "foo".into(), - namespace: None, - timestamp: None, - tags: None, - kind: MetricKind::Incremental, - value: MetricValue::Set { + let event = Event::Metric(Metric::new( + "foo".into(), + MetricKind::Incremental, + MetricValue::Set { values: vec!["bar".into()].into_iter().collect(), }, - }); + )); let mut transform = RemoveTags::new(vec!["env".into()]); let metric = transform.transform_one(event).unwrap().into_metric(); - assert!(metric.tags.is_none()); + assert!(metric.tags().is_none()); } } diff --git a/src/transforms/tag_cardinality_limit.rs b/src/transforms/tag_cardinality_limit.rs index 3491bee56619c..2fda01d0c5f90 100644 --- a/src/transforms/tag_cardinality_limit.rs +++ b/src/transforms/tag_cardinality_limit.rs @@ -217,8 +217,8 @@ impl TagCardinalityLimit { } fn transform_one(&mut self, mut event: Event) -> Option { - match event.as_mut_metric().tags { - Some(ref mut tags_map) => { + match event.as_mut_metric().tags_mut() { + Some(tags_map) => { match self.config.limit_exceeded_action { LimitExceededAction::DropEvent => { for (key, value) in tags_map { @@ -280,14 +280,14 @@ mod tests { } fn make_metric(tags: BTreeMap) -> Event { - Event::Metric(Metric { - name: "event".into(), - namespace: None, - timestamp: None, - tags: Some(tags), - kind: metric::MetricKind::Incremental, - value: metric::MetricValue::Counter { value: 1.0 }, - }) + Event::Metric( + Metric::new( + "event".into(), + metric::MetricKind::Incremental, + metric::MetricValue::Counter { value: 1.0 }, + ) + .with_tags(Some(tags)), + ) } fn make_transform_hashset( @@ -390,21 +390,10 @@ mod tests { assert_eq!(new_event2, event2); // The third event should have been modified to remove "tag1" assert_ne!(new_event3, event3); - assert!(!new_event3 - .as_metric() - .tags - .as_ref() - .unwrap() - .contains_key("tag1")); + assert!(!new_event3.as_metric().tags().unwrap().contains_key("tag1")); assert_eq!( "val1", - new_event3 - .as_metric() - .tags - .as_ref() - .unwrap() - .get("tag2") - .unwrap() + new_event3.as_metric().tags().unwrap().get("tag2").unwrap() ); } diff --git a/tests/support/mod.rs b/tests/support/mod.rs index 663c2e90fef82..c47396453a439 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -210,7 +210,7 @@ impl FunctionTransform for MockTransform { v.push_str(&self.suffix); log.insert(vector::config::log_schema().message_key(), Value::from(v)); } - Event::Metric(metric) => match metric.value { + Event::Metric(metric) => match metric.data.value { MetricValue::Counter { ref mut value } => { *value += self.increase; }