Skip to content

Commit 9462cd6

Browse files
committed
Add serde style encoding for Summary
Signed-off-by: Palash Nigam <[email protected]>
1 parent 2ab4ac1 commit 9462cd6

File tree

5 files changed

+141
-4
lines changed

5 files changed

+141
-4
lines changed

src/encoding.rs

+15
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,21 @@ impl<'a, 'b> MetricEncoder<'a, 'b> {
131131
)
132132
}
133133

134+
/// Encode a summary.
135+
pub fn encode_summary<S: EncodeLabelSet>(
136+
&mut self,
137+
sum: f64,
138+
count: u64,
139+
quantiles: &[(f64, f64)],
140+
) -> Result<(), std::fmt::Error> {
141+
for_both_mut!(
142+
self,
143+
MetricEncoderInner,
144+
e,
145+
e.encode_summary::<S>(sum, count, quantiles)
146+
)
147+
}
148+
134149
/// Encode a metric family.
135150
pub fn encode_family<'c, 'd, S: EncodeLabelSet>(
136151
&'c mut self,

src/encoding/protobuf.rs

+73
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ impl From<MetricType> for openmetrics_data_model::MetricType {
9999
MetricType::Counter => openmetrics_data_model::MetricType::Counter,
100100
MetricType::Gauge => openmetrics_data_model::MetricType::Gauge,
101101
MetricType::Histogram => openmetrics_data_model::MetricType::Histogram,
102+
MetricType::Summary => openmetrics_data_model::MetricType::Summary,
102103
MetricType::Info => openmetrics_data_model::MetricType::Info,
103104
MetricType::Unknown => openmetrics_data_model::MetricType::Unknown,
104105
}
@@ -247,6 +248,44 @@ impl<'a> MetricEncoder<'a> {
247248

248249
Ok(())
249250
}
251+
252+
pub fn encode_summary<S: EncodeLabelSet>(
253+
&mut self,
254+
sum: f64,
255+
count: u64,
256+
quantile: &[(f64, f64)],
257+
) -> Result<(), std::fmt::Error> {
258+
let quantiles = quantiles
259+
.iter()
260+
.enumerate()
261+
.map(|(_, (quantile, value))| {
262+
Ok(openmetrics_data_model::summary_value::Quantile {
263+
quantile: *quantile,
264+
value: *value,
265+
})
266+
})
267+
.collect::<Result<Vec<_>, std::fmt::Error>>()?;
268+
269+
self.family.push(openmetrics_data_model::Metric {
270+
labels: self.labels.clone(),
271+
metric_points: vec![openmetrics_data_model::MetricPoint {
272+
value: Some(openmetrics_data_model::metric_point::Value::SummaryValue(
273+
openmetrics_data_model::SummaryValue {
274+
count,
275+
created: None,
276+
quantiles,
277+
sum: Some(openmetrics_data_model::summary_value::Sum::DoubleValue(
278+
sum,
279+
)),
280+
},
281+
)),
282+
..Default::default()
283+
}],
284+
});
285+
286+
Ok(())
287+
}
288+
250289
}
251290

252291
impl<S: EncodeLabelSet, V: EncodeExemplarValue> TryFrom<&Exemplar<S, V>>
@@ -403,6 +442,7 @@ mod tests {
403442
use crate::metrics::family::Family;
404443
use crate::metrics::gauge::Gauge;
405444
use crate::metrics::histogram::{exponential_buckets, Histogram};
445+
use crate::metrics::summary::Summary;
406446
use crate::metrics::info::Info;
407447
use crate::registry::Unit;
408448
use std::borrow::Cow;
@@ -643,6 +683,39 @@ mod tests {
643683
}
644684
}
645685

686+
#[test]
687+
fn encode_summary() {
688+
let mut registry = Registry::default();
689+
let summary = Summary::new(5, 10, vec![0.5, 0.9, 0.99], 0.01);
690+
registry.register("my_summary", "My summary", summary.clone());
691+
summary.observe(1.0);
692+
693+
let metric_set = encode(&registry).unwrap();
694+
695+
let family = metric_set.metric_families.first().unwrap();
696+
assert_eq!("my_summary", family.name);
697+
assert_eq!("My summary.", family.help);
698+
699+
assert_eq!(
700+
openmetrics_data_model::MetricType::Summary as i32,
701+
extract_metric_type(&metric_set)
702+
);
703+
704+
match extract_metric_point_value(metric_set) {
705+
openmetrics_data_model::metric_point::Value::SummaryValue(value) => {
706+
assert_eq!(
707+
Some(openmetrics_data_model::summary_value::Sum::DoubleValue(
708+
1.0
709+
)),
710+
value.sum
711+
);
712+
assert_eq!(1, value.count);
713+
assert_eq!(11, value.quantile.len());
714+
}
715+
_ => panic!("wrong value type"),
716+
}
717+
}
718+
646719
#[test]
647720
fn encode_histogram() {
648721
let mut registry = Registry::default();

src/encoding/text.rs

+38-4
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,40 @@ impl<'a, 'b> MetricEncoder<'a, 'b> {
211211
})
212212
}
213213

214+
pub fn encode_summary<S: EncodeLabelSet>(
215+
&mut self,
216+
sum: f64,
217+
count: u64,
218+
quantiles: &[(f64, f64)],
219+
) -> Result<(), std::fmt::Error> {
220+
self.write_name_and_unit()?;
221+
self.write_suffix("sum")?;
222+
self.encode_labels::<()>(None)?;
223+
self.writer.write_str(" ")?;
224+
self.writer.write_str(dtoa::Buffer::new().format(sum))?;
225+
self.newline()?;
226+
227+
self.write_name_and_unit()?;
228+
self.write_suffix("count")?;
229+
self.encode_labels::<()>(None)?;
230+
self.writer.write_str(" ")?;
231+
self.writer.write_str(itoa::Buffer::new().format(count))?;
232+
self.newline()?;
233+
234+
for (_, (quantile, result)) in quantiles.iter().enumerate() {
235+
self.write_name_and_unit()?;
236+
self.encode_labels(Some(&[("quantile", *quantile)]))?;
237+
238+
self.writer.write_str(" ")?;
239+
self.writer
240+
.write_str(result.to_string().as_str())?;
241+
242+
self.newline()?;
243+
}
244+
245+
Ok(())
246+
}
247+
214248
pub fn encode_histogram<S: EncodeLabelSet>(
215249
&mut self,
216250
sum: f64,
@@ -511,6 +545,7 @@ mod tests {
511545
use crate::metrics::family::Family;
512546
use crate::metrics::gauge::Gauge;
513547
use crate::metrics::histogram::{exponential_buckets, Histogram};
548+
use crate::metrics::summary::Summary;
514549
use crate::metrics::info::Info;
515550
use crate::metrics::{counter::Counter, exemplar::CounterWithExemplar};
516551
use pyo3::{prelude::*, types::PyModule};
@@ -732,8 +767,7 @@ mod tests {
732767
summary.observe(0.20);
733768
summary.observe(0.30);
734769

735-
let mut encoded = Vec::new();
736-
770+
let mut encoded = String::new();
737771
encode(&mut encoded, &registry).unwrap();
738772

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

749-
parse_with_python_client(String::from_utf8(encoded).unwrap());
783+
parse_with_python_client(encoded);
750784
}
751785

752786
fn parse_with_python_client(input: String) {

src/metrics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl MetricType {
3838
MetricType::Counter => "counter",
3939
MetricType::Gauge => "gauge",
4040
MetricType::Histogram => "histogram",
41+
MetricType::Summary => "summary",
4142
MetricType::Info => "info",
4243
MetricType::Unknown => "unknown",
4344
}

src/metrics/summary.rs

+14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//!
33
//! See [`Summary`] for details.
44
5+
use crate::encoding::{EncodeMetric, MetricEncoder};
6+
57
use super::{MetricType, TypedMetric};
68
//use owning_ref::OwningRef;
79
//use std::iter::{self, once};
@@ -126,6 +128,18 @@ impl TypedMetric for Summary {
126128
const TYPE: MetricType = MetricType::Summary;
127129
}
128130

131+
impl EncodeMetric for Summary {
132+
fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> {
133+
let (sum, count, quantiles) = self.get();
134+
encoder.encode_summary::<()>(sum, count, &quantiles)
135+
}
136+
137+
fn metric_type(&self) -> MetricType {
138+
Self::TYPE
139+
}
140+
}
141+
142+
129143
#[cfg(test)]
130144
mod tests {
131145
use super::*;

0 commit comments

Comments
 (0)