prometheus/encoder/
pb.rs

1// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
2
3use std::io::Write;
4
5use protobuf::Message;
6
7use crate::errors::Result;
8use crate::proto::MetricFamily;
9
10use super::{check_metric_family, Encoder};
11
12/// The protocol buffer format of metric family.
13pub const PROTOBUF_FORMAT: &str = "application/vnd.google.protobuf; \
14                                   proto=io.prometheus.client.MetricFamily; \
15                                   encoding=delimited";
16
17/// An implementation of an [`Encoder`] that converts a [`MetricFamily`] proto
18/// message into the binary wire format of protobuf.
19#[derive(Debug, Default)]
20pub struct ProtobufEncoder;
21
22impl ProtobufEncoder {
23    /// Create a new protobuf encoder.
24    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            // Fail-fast checks.
33            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    // TODO: add more tests.
52    #[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        // Generated by a golang demo,
69        // see more: https://gist.github.com/overvenus/bd39bde014b0cba87c9bde20dbea6ce0
70        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}