fuchsia_cobalt_builders/
metric_event_builder.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Helper builder for constructing a `MetricEvent`.
6
7use cobalt_client::traits::AsEventCodes;
8use fidl_fuchsia_metrics::{HistogramBucket, MetricEvent, MetricEventPayload};
9
10///  Adds the `builder()` method to `MetricEvent`.
11pub trait MetricEventExt {
12    /// Returns a `MetricEventBuilder` for the specified `metric_id`.
13    ///
14    /// # Examples
15    ///
16    /// ```
17    /// assert_eq!(MetricEvent::builder(5).as_event().metric_id, 0);
18    /// ```
19    fn builder(metric_id: u32) -> MetricEventBuilder;
20}
21
22impl MetricEventExt for MetricEvent {
23    fn builder(metric_id: u32) -> MetricEventBuilder {
24        MetricEventBuilder { metric_id, ..MetricEventBuilder::default() }
25    }
26}
27
28/// MetricEventBuilder allows for a chained construction of `MetricEvent` objects.
29#[derive(Debug, Default, Clone)]
30pub struct MetricEventBuilder {
31    metric_id: u32,
32    event_codes: Vec<u32>,
33}
34
35impl MetricEventBuilder {
36    /// Appends the provided `event_code` to the `event_codes` list.
37    ///
38    /// # Examples
39    ///
40    /// ```
41    /// assert_eq!(MetricEvent::builder(6).with_event_code(10).as_event().event_codes, vec![10]);
42    /// ```
43    pub fn with_event_code(mut self, event_code: u32) -> MetricEventBuilder {
44        self.event_codes.push(event_code);
45        self
46    }
47
48    /// Overrides the list of event_codes with the provided `event_codes`.
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// assert_eq!(
54    ///     MetricEvent::builder(7).with_event_codes([1, 2, 3]).as_event().event_codes,
55    ///     vec![1,2,3]);
56    /// ```
57    pub fn with_event_codes<Codes: AsEventCodes>(
58        mut self,
59        event_codes: Codes,
60    ) -> MetricEventBuilder {
61        self.event_codes = event_codes.as_event_codes();
62        self
63    }
64
65    /// Writes an `event_code` to a particular `index`. This method is useful when not assigning
66    /// event codes in order.
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// assert_eq!(
72    ///     MetricEvent::builder(8).with_event_code_at(1, 10).as_event().event_codes,
73    ///     vec![0, 10]);
74    /// ```
75    ///
76    /// # Panics
77    ///
78    /// Panics if the `value`  is greater than or equal to 5.
79    pub fn with_event_code_at(mut self, index: usize, event_code: u32) -> MetricEventBuilder {
80        assert!(
81            index < 5,
82            "Invalid index passed to MetricEventBuilder::with_event_code. Cobalt events cannot support more than 5 event_codes."
83        );
84        while self.event_codes.len() <= index {
85            self.event_codes.push(0);
86        }
87        self.event_codes[index] = event_code;
88        self
89    }
90
91    /// Constructs a `MetricEvent` with the provided `MetricEventPayload`.
92    ///
93    /// # Examples
94    /// ```
95    /// let payload = MetricEventPayload::Event(fidl_fuchsia_cobalt::Event);
96    /// assert_eq!(MetricEvent::builder(10).build(payload.clone()).payload, payload);
97    /// ```
98    pub fn build(self, payload: MetricEventPayload) -> MetricEvent {
99        MetricEvent { metric_id: self.metric_id, event_codes: self.event_codes, payload }
100    }
101
102    /// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::Count`.
103    ///
104    /// # Examples
105    /// ```
106    /// asert_eq!(
107    ///     MetricEvent::builder(11).as_occurrence(10).payload,
108    ///     MetricEventPayload::Event(fidl_fuchsia_cobalt::Count(10)));
109    /// ```
110    pub fn as_occurrence(self, count: u64) -> MetricEvent {
111        self.build(MetricEventPayload::Count(count))
112    }
113
114    /// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::IntegerValue`.
115    ///
116    /// # Examples
117    /// ```
118    /// asert_eq!(
119    ///     MetricEvent::builder(12).as_integer(5).payload,
120    ///     MetricEventPayload::IntegerValue(5)));
121    /// ```
122    pub fn as_integer(self, integer_value: i64) -> MetricEvent {
123        self.build(MetricEventPayload::IntegerValue(integer_value))
124    }
125
126    /// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::Histogram`.
127    ///
128    /// # Examples
129    /// ```
130    /// let histogram = vec![HistogramBucket { index: 0, count: 1 }];
131    /// asert_eq!(
132    ///     MetricEvent::builder(17).as_int_histogram(histogram.clone()).payload,
133    ///     MetricEventPayload::Histogram(histogram));
134    /// ```
135    pub fn as_integer_histogram(self, histogram: Vec<HistogramBucket>) -> MetricEvent {
136        self.build(MetricEventPayload::Histogram(histogram))
137    }
138
139    /// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::StringValue`.
140    ///
141    /// # Examples
142    /// ```
143    /// asert_eq!(
144    ///     MetricEvent::builder(17).as_string("test").payload,
145    ///     MetricEventPayload::StringValue("test".to_string()));
146    /// ```
147    pub fn as_string<S: Into<String>>(self, string: S) -> MetricEvent {
148        self.build(MetricEventPayload::StringValue(string.into()))
149    }
150}
151
152#[cfg(test)]
153mod tests {
154    use super::*;
155
156    #[test]
157    fn test_builder_as_occurrence() {
158        let event = MetricEvent::builder(1).with_event_code(2).as_occurrence(3);
159        let expected = MetricEvent {
160            metric_id: 1,
161            event_codes: vec![2],
162            payload: MetricEventPayload::Count(3),
163        };
164        assert_eq!(event, expected);
165    }
166
167    #[test]
168    fn test_builder_as_integer() {
169        let event = MetricEvent::builder(2).with_event_code(3).as_integer(4);
170        let expected = MetricEvent {
171            metric_id: 2,
172            event_codes: vec![3],
173            payload: MetricEventPayload::IntegerValue(4),
174        };
175        assert_eq!(event, expected);
176    }
177
178    #[test]
179    fn test_as_integer_histogram() {
180        let event = MetricEvent::builder(7)
181            .with_event_code(8)
182            .as_integer_histogram(vec![HistogramBucket { index: 0, count: 1 }]);
183        let expected = MetricEvent {
184            metric_id: 7,
185            event_codes: vec![8],
186            payload: MetricEventPayload::Histogram(vec![HistogramBucket { index: 0, count: 1 }]),
187        };
188        assert_eq!(event, expected);
189    }
190
191    #[test]
192    fn test_builder_as_string() {
193        let event = MetricEvent::builder(2).with_event_code(3).as_string("value");
194        let expected = MetricEvent {
195            metric_id: 2,
196            event_codes: vec![3],
197            payload: MetricEventPayload::StringValue("value".into()),
198        };
199        assert_eq!(event, expected);
200    }
201
202    #[test]
203    #[should_panic(expected = "Invalid index")]
204    fn test_bad_event_code_at_index() {
205        MetricEvent::builder(8).with_event_code_at(5, 10).as_occurrence(1);
206    }
207}