1use std::io::Write;
4
5use protobuf::Message;
6
7use crate::errors::Result;
8use crate::proto::MetricFamily;
9
10use super::{check_metric_family, Encoder};
11
12pub const PROTOBUF_FORMAT: &str = "application/vnd.google.protobuf; \
14 proto=io.prometheus.client.MetricFamily; \
15 encoding=delimited";
16
17#[derive(Debug, Default)]
20pub struct ProtobufEncoder;
21
22impl ProtobufEncoder {
23 pub fn new() -> ProtobufEncoder {
25 ProtobufEncoder
26 }
27}
28
29impl Encoder for ProtobufEncoder {
30 fn encode<W: Write>(&self, metric_families: &[MetricFamily], writer: &mut W) -> Result<()> {
31 for mf in metric_families {
32 check_metric_family(mf)?;
34 mf.write_length_delimited_to_writer(writer)?;
35 }
36 Ok(())
37 }
38
39 fn format_type(&self) -> &str {
40 PROTOBUF_FORMAT
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use crate::counter::CounterVec;
47 use crate::encoder::Encoder;
48 use crate::metrics::Opts;
49 use crate::registry;
50
51 #[rustfmt::skip]
53 #[test]
54 fn test_protobuf_encoder() {
55 let cv = CounterVec::new(Opts::new("test_counter_vec", "help information"),
56 &["labelname"])
57 .unwrap();
58 let reg = registry::Registry::new();
59 reg.register(Box::new(cv.clone())).unwrap();
60
61 cv.get_metric_with_label_values(&["2230"]).unwrap().inc();
62 let mf = reg.gather();
63 let mut writer = Vec::<u8>::new();
64 let encoder = super::ProtobufEncoder::new();
65 let res = encoder.encode(&mf, &mut writer);
66 assert!(res.is_ok());
67
68 let ans = vec![70, 10, 16, 116, 101, 115, 116, 95, 99, 111, 117, 110, 116, 101, 114, 95,
71 118, 101, 99, 18, 16, 104, 101, 108, 112, 32, 105, 110, 102, 111, 114, 109,
72 97, 116, 105, 111, 110, 24, 0, 34, 30, 10, 17, 10, 9, 108, 97, 98, 101,
73 108, 110, 97, 109, 101, 18, 4, 50, 50, 51, 48, 26, 9, 9, 0, 0, 0, 0, 0, 0,
74 240, 63];
75 assert_eq!(ans, writer);
76 }
77}