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}