Skip to content

Commit

Permalink
Add serde style encoding for Summary
Browse files Browse the repository at this point in the history
Signed-off-by: Palash Nigam <npalash25@gmail.com>
  • Loading branch information
palash25 committed Jan 28, 2023
1 parent 2ab4ac1 commit e038f4e
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 4 deletions.
15 changes: 15 additions & 0 deletions src/encoding.rs
Expand Up @@ -131,6 +131,21 @@ impl<'a, 'b> MetricEncoder<'a, 'b> {
)
}

/// Encode a summary.
pub fn encode_summary<S: EncodeLabelSet>(
&mut self,
sum: f64,
count: u64,
quantiles: &[(f64, f64)],
) -> Result<(), std::fmt::Error> {
for_both_mut!(
self,
MetricEncoderInner,
e,
e.encode_summary(sum, count, quantiles)
)
}

/// Encode a metric family.
pub fn encode_family<'c, 'd, S: EncodeLabelSet>(
&'c mut self,
Expand Down
73 changes: 73 additions & 0 deletions src/encoding/protobuf.rs
Expand Up @@ -99,6 +99,7 @@ impl From<MetricType> for openmetrics_data_model::MetricType {
MetricType::Counter => openmetrics_data_model::MetricType::Counter,
MetricType::Gauge => openmetrics_data_model::MetricType::Gauge,
MetricType::Histogram => openmetrics_data_model::MetricType::Histogram,
MetricType::Summary => openmetrics_data_model::MetricType::Summary,
MetricType::Info => openmetrics_data_model::MetricType::Info,
MetricType::Unknown => openmetrics_data_model::MetricType::Unknown,
}
Expand Down Expand Up @@ -247,6 +248,44 @@ impl<'a> MetricEncoder<'a> {

Ok(())
}

pub fn encode_summary<S: EncodeLabelSet>(
&mut self,
sum: f64,
count: u64,
quantile: &[(f64, f64)],
) -> Result<(), std::fmt::Error> {
let quantiles = quantiles
.iter()
.enumerate()
.map(|(_, (quantile, value))| {
Ok(openmetrics_data_model::summary_value::Quantile {
quantile: *quantile,
value: *value,
})
})
.collect::<Result<Vec<_>, std::fmt::Error>>()?;

self.family.push(openmetrics_data_model::Metric {
labels: self.labels.clone(),
metric_points: vec![openmetrics_data_model::MetricPoint {
value: Some(openmetrics_data_model::metric_point::Value::SummaryValue(
openmetrics_data_model::SummaryValue {
count,
created: None,
quantiles,
sum: Some(openmetrics_data_model::summary_value::Sum::DoubleValue(
sum,
)),
},
)),
..Default::default()
}],
});

Ok(())
}

}

impl<S: EncodeLabelSet, V: EncodeExemplarValue> TryFrom<&Exemplar<S, V>>
Expand Down Expand Up @@ -403,6 +442,7 @@ mod tests {
use crate::metrics::family::Family;
use crate::metrics::gauge::Gauge;
use crate::metrics::histogram::{exponential_buckets, Histogram};
use crate::metrics::summary::Summary;
use crate::metrics::info::Info;
use crate::registry::Unit;
use std::borrow::Cow;
Expand Down Expand Up @@ -643,6 +683,39 @@ mod tests {
}
}

#[test]
fn encode_summary() {
let mut registry = Registry::default();
let summary = Summary::new(5, 10, vec![0.5, 0.9, 0.99], 0.01);
registry.register("my_summary", "My summary", summary.clone());
summary.observe(1.0);

let metric_set = encode(&registry).unwrap();

let family = metric_set.metric_families.first().unwrap();
assert_eq!("my_summary", family.name);
assert_eq!("My summary.", family.help);

assert_eq!(
openmetrics_data_model::MetricType::Summary as i32,
extract_metric_type(&metric_set)
);

match extract_metric_point_value(metric_set) {
openmetrics_data_model::metric_point::Value::SummaryValue(value) => {
assert_eq!(
Some(openmetrics_data_model::summary_value::Sum::DoubleValue(
1.0
)),
value.sum
);
assert_eq!(1, value.count);
assert_eq!(11, value.quantile.len());
}
_ => panic!("wrong value type"),
}
}

#[test]
fn encode_histogram() {
let mut registry = Registry::default();
Expand Down
42 changes: 38 additions & 4 deletions src/encoding/text.rs
Expand Up @@ -211,6 +211,40 @@ impl<'a, 'b> MetricEncoder<'a, 'b> {
})
}

pub fn encode_summary<S: EncodeLabelSet>(
&mut self,
sum: f64,
count: u64,
quantiles: &[(f64, f64)],
) -> Result<(), std::fmt::Error> {
self.write_name_and_unit()?;
self.write_suffix("sum")?;
self.encode_labels::<()>(None)?;
self.writer.write_str(" ")?;
self.writer.write_str(dtoa::Buffer::new().format(sum))?;
self.newline()?;

self.write_name_and_unit()?;
self.write_suffix("count")?;
self.encode_labels::<()>(None)?;
self.writer.write_str(" ")?;
self.writer.write_str(itoa::Buffer::new().format(count))?;
self.newline()?;

for (_, (quantile, result)) in quantiles.iter().enumerate() {
self.write_name_and_unit()?;
self.encode_labels(Some(&[("quantile", *quantile)]))?;

self.writer.write_str(" ")?;
self.writer
.write_str(result.to_string().as_str())?;

self.newline()?;
}

Ok(())
}

pub fn encode_histogram<S: EncodeLabelSet>(
&mut self,
sum: f64,
Expand Down Expand Up @@ -511,6 +545,7 @@ mod tests {
use crate::metrics::family::Family;
use crate::metrics::gauge::Gauge;
use crate::metrics::histogram::{exponential_buckets, Histogram};
use crate::metrics::summary::Summary;
use crate::metrics::info::Info;
use crate::metrics::{counter::Counter, exemplar::CounterWithExemplar};
use pyo3::{prelude::*, types::PyModule};
Expand Down Expand Up @@ -732,8 +767,7 @@ mod tests {
summary.observe(0.20);
summary.observe(0.30);

let mut encoded = Vec::new();

let mut encoded = String::new();
encode(&mut encoded, &registry).unwrap();

let expected = "# HELP my_summary My summary.\n".to_owned()
Expand All @@ -744,9 +778,9 @@ mod tests {
+ "my_summary{quantile=\"0.9\"} 0.3\n"
+ "my_summary{quantile=\"0.99\"} 0.3\n"
+ "# EOF\n";
assert_eq!(expected, String::from_utf8(encoded.clone()).unwrap());
assert_eq!(expected, encoded);

parse_with_python_client(String::from_utf8(encoded).unwrap());
parse_with_python_client(encoded);
}

fn parse_with_python_client(input: String) {
Expand Down
1 change: 1 addition & 0 deletions src/metrics.rs
Expand Up @@ -38,6 +38,7 @@ impl MetricType {
MetricType::Counter => "counter",
MetricType::Gauge => "gauge",
MetricType::Histogram => "histogram",
MetricType::Summary => "summary",
MetricType::Info => "info",
MetricType::Unknown => "unknown",
}
Expand Down
14 changes: 14 additions & 0 deletions src/metrics/summary.rs
Expand Up @@ -2,6 +2,8 @@
//!
//! See [`Summary`] for details.

use crate::encoding::{EncodeMetric, MetricEncoder};

use super::{MetricType, TypedMetric};
//use owning_ref::OwningRef;
//use std::iter::{self, once};
Expand Down Expand Up @@ -126,6 +128,18 @@ impl TypedMetric for Summary {
const TYPE: MetricType = MetricType::Summary;
}

impl EncodeMetric for Summary {
fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> {
let (sum, count, quantiles) = self.get();
encoder.encode_summary::<()>(sum, count, &quantiles)
}

fn metric_type(&self) -> MetricType {
Self::TYPE
}
}


#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit e038f4e

Please sign in to comment.