@@ -29,6 +29,7 @@ use crate::metrics::exemplar::{CounterWithExemplar, Exemplar, HistogramWithExemp
29
29
use crate :: metrics:: family:: { Family , MetricConstructor } ;
30
30
use crate :: metrics:: gauge:: { self , Gauge } ;
31
31
use crate :: metrics:: histogram:: Histogram ;
32
+ use crate :: metrics:: summary:: Summary ;
32
33
use crate :: metrics:: info:: Info ;
33
34
use crate :: metrics:: { MetricType , TypedMetric } ;
34
35
use crate :: registry:: { Registry , Unit } ;
@@ -332,6 +333,23 @@ impl<'a> BucketEncoder<'a> {
332
333
} )
333
334
}
334
335
336
+ /// Encode a quantile. Used for the [`Summary`] metric type.
337
+ pub fn encode_quantile ( & mut self , quantile : f64 ) -> Result < ValueEncoder , std:: io:: Error > {
338
+ if self . opened_curly_brackets {
339
+ self . writer . write_all ( b"," ) ?;
340
+ } else {
341
+ self . writer . write_all ( b"{" ) ?;
342
+ }
343
+
344
+ self . writer . write_all ( b"quantile=\" " ) ?;
345
+ quantile. encode ( self . writer ) ?;
346
+ self . writer . write_all ( b"\" }" ) ?;
347
+
348
+ Ok ( ValueEncoder {
349
+ writer : self . writer ,
350
+ } )
351
+ }
352
+
335
353
/// Signal that the metric type has no bucket.
336
354
pub fn no_bucket ( & mut self ) -> Result < ValueEncoder , std:: io:: Error > {
337
355
if self . opened_curly_brackets {
@@ -581,6 +599,40 @@ fn encode_histogram_with_maybe_exemplars<S: Encode>(
581
599
Ok ( ( ) )
582
600
}
583
601
602
+ /////////////////////////////////////////////////////////////////////////////////
603
+ // Summary
604
+
605
+ impl EncodeMetric for Summary {
606
+ fn encode ( & self , mut encoder : Encoder ) -> Result < ( ) , std:: io:: Error > {
607
+ let ( sum, count, quantiles) = self . get ( ) ;
608
+
609
+ encoder
610
+ . encode_suffix ( "sum" ) ?
611
+ . no_bucket ( ) ?
612
+ . encode_value ( sum) ?
613
+ . no_exemplar ( ) ?;
614
+ encoder
615
+ . encode_suffix ( "count" ) ?
616
+ . no_bucket ( ) ?
617
+ . encode_value ( count) ?
618
+ . no_exemplar ( ) ?;
619
+
620
+ for ( _, ( quantile, result) ) in quantiles. iter ( ) . enumerate ( ) {
621
+ let mut bucket_encoder = encoder. no_suffix ( ) ?;
622
+ let mut value_encoder = bucket_encoder. encode_quantile ( * quantile) ?;
623
+ let mut exemplar_encoder = value_encoder. encode_value ( * result) ?;
624
+ exemplar_encoder. no_exemplar ( ) ?
625
+ }
626
+
627
+ Result :: Ok ( ( ) )
628
+ }
629
+
630
+ fn metric_type ( & self ) -> MetricType {
631
+ Self :: TYPE
632
+ }
633
+ }
634
+
635
+
584
636
/////////////////////////////////////////////////////////////////////////////////
585
637
// Info
586
638
@@ -821,6 +873,30 @@ mod tests {
821
873
parse_with_python_client ( String :: from_utf8 ( encoded) . unwrap ( ) ) ;
822
874
}
823
875
876
+ #[ test]
877
+ fn encode_summary ( ) {
878
+ let mut registry = Registry :: default ( ) ;
879
+ let summary = Summary :: new ( 3 , 10 , vec ! [ 0.5 , 0.9 , 0.99 ] , 0.0 ) ;
880
+ registry. register ( "my_summary" , "My summary" , summary. clone ( ) ) ;
881
+ summary. observe ( 0.10 ) ;
882
+ summary. observe ( 0.20 ) ;
883
+ summary. observe ( 0.30 ) ;
884
+
885
+ let mut encoded = Vec :: new ( ) ;
886
+
887
+ encode ( & mut encoded, & registry) . unwrap ( ) ;
888
+
889
+ let expected = "# HELP my_summary My summary.\n " . to_owned ( )
890
+ + "# TYPE my_summary summary\n "
891
+ + "my_summary_sum 0.6000000000000001\n "
892
+ + "my_summary_count 3\n "
893
+ + "my_summary{quantile=\" 0.5\" } 0.2\n "
894
+ + "my_summary{quantile=\" 0.9\" } 0.3\n "
895
+ + "my_summary{quantile=\" 0.99\" } 0.3\n "
896
+ + "# EOF\n " ;
897
+ assert_eq ! ( expected, String :: from_utf8( encoded. clone( ) ) . unwrap( ) ) ;
898
+ }
899
+
824
900
fn parse_with_python_client ( input : String ) {
825
901
pyo3:: prepare_freethreaded_python ( ) ;
826
902
0 commit comments