blob: 6abc93e7b32a0e829b3f9b6ee1f626461f8c151b [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Helper builder for constructing a `MetricEvent`.
use {
cobalt_client::traits::AsEventCodes,
fidl_fuchsia_metrics::{HistogramBucket, MetricEvent, MetricEventPayload},
};
/// Adds the `builder()` method to `MetricEvent`.
pub trait MetricEventExt {
/// Returns a `MetricEventBuilder` for the specified `metric_id`.
///
/// # Examples
///
/// ```
/// assert_eq!(MetricEvent::builder(5).as_event().metric_id, 0);
/// ```
fn builder(metric_id: u32) -> MetricEventBuilder;
}
impl MetricEventExt for MetricEvent {
fn builder(metric_id: u32) -> MetricEventBuilder {
MetricEventBuilder { metric_id, ..MetricEventBuilder::default() }
}
}
/// MetricEventBuilder allows for a chained construction of `MetricEvent` objects.
#[derive(Debug, Default, Clone)]
pub struct MetricEventBuilder {
metric_id: u32,
event_codes: Vec<u32>,
}
impl MetricEventBuilder {
/// Appends the provided `event_code` to the `event_codes` list.
///
/// # Examples
///
/// ```
/// assert_eq!(MetricEvent::builder(6).with_event_code(10).as_event().event_codes, vec![10]);
/// ```
pub fn with_event_code(mut self, event_code: u32) -> MetricEventBuilder {
self.event_codes.push(event_code);
self
}
/// Overrides the list of event_codes with the provided `event_codes`.
///
/// # Examples
///
/// ```
/// assert_eq!(
/// MetricEvent::builder(7).with_event_codes([1, 2, 3]).as_event().event_codes,
/// vec![1,2,3]);
/// ```
pub fn with_event_codes<Codes: AsEventCodes>(
mut self,
event_codes: Codes,
) -> MetricEventBuilder {
self.event_codes = event_codes.as_event_codes();
self
}
/// Writes an `event_code` to a particular `index`. This method is useful when not assigning
/// event codes in order.
///
/// # Examples
///
/// ```
/// assert_eq!(
/// MetricEvent::builder(8).with_event_code_at(1, 10).as_event().event_codes,
/// vec![0, 10]);
/// ```
///
/// # Panics
///
/// Panics if the `value` is greater than or equal to 5.
pub fn with_event_code_at(mut self, index: usize, event_code: u32) -> MetricEventBuilder {
assert!(
index < 5,
"Invalid index passed to MetricEventBuilder::with_event_code. Cobalt events cannot support more than 5 event_codes."
);
while self.event_codes.len() <= index {
self.event_codes.push(0);
}
self.event_codes[index] = event_code;
self
}
/// Constructs a `MetricEvent` with the provided `MetricEventPayload`.
///
/// # Examples
/// ```
/// let payload = MetricEventPayload::Event(fidl_fuchsia_cobalt::Event);
/// assert_eq!(MetricEvent::builder(10).build(payload.clone()).payload, payload);
/// ```
pub fn build(self, payload: MetricEventPayload) -> MetricEvent {
MetricEvent { metric_id: self.metric_id, event_codes: self.event_codes, payload }
}
/// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::Count`.
///
/// # Examples
/// ```
/// asert_eq!(
/// MetricEvent::builder(11).as_occurrence(10).payload,
/// MetricEventPayload::Event(fidl_fuchsia_cobalt::Count(10)));
/// ```
pub fn as_occurrence(self, count: u64) -> MetricEvent {
self.build(MetricEventPayload::Count(count))
}
/// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::IntegerValue`.
///
/// # Examples
/// ```
/// asert_eq!(
/// MetricEvent::builder(12).as_integer(5).payload,
/// MetricEventPayload::IntegerValue(5)));
/// ```
pub fn as_integer(self, integer_value: i64) -> MetricEvent {
self.build(MetricEventPayload::IntegerValue(integer_value))
}
/// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::Histogram`.
///
/// # Examples
/// ```
/// let histogram = vec![HistogramBucket { index: 0, count: 1 }];
/// asert_eq!(
/// MetricEvent::builder(17).as_int_histogram(histogram.clone()).payload,
/// MetricEventPayload::Histogram(histogram));
/// ```
pub fn as_integer_histogram(self, histogram: Vec<HistogramBucket>) -> MetricEvent {
self.build(MetricEventPayload::Histogram(histogram))
}
/// Constructs a `MetricEvent` with a payload type of `MetricEventPayload::StringValue`.
///
/// # Examples
/// ```
/// asert_eq!(
/// MetricEvent::builder(17).as_string("test").payload,
/// MetricEventPayload::StringValue("test".to_string()));
/// ```
pub fn as_string<S: Into<String>>(self, string: S) -> MetricEvent {
self.build(MetricEventPayload::StringValue(string.into()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder_as_occurrence() {
let event = MetricEvent::builder(1).with_event_code(2).as_occurrence(3);
let expected = MetricEvent {
metric_id: 1,
event_codes: vec![2],
payload: MetricEventPayload::Count(3),
};
assert_eq!(event, expected);
}
#[test]
fn test_builder_as_integer() {
let event = MetricEvent::builder(2).with_event_code(3).as_integer(4);
let expected = MetricEvent {
metric_id: 2,
event_codes: vec![3],
payload: MetricEventPayload::IntegerValue(4),
};
assert_eq!(event, expected);
}
#[test]
fn test_as_integer_histogram() {
let event = MetricEvent::builder(7)
.with_event_code(8)
.as_integer_histogram(vec![HistogramBucket { index: 0, count: 1 }]);
let expected = MetricEvent {
metric_id: 7,
event_codes: vec![8],
payload: MetricEventPayload::Histogram(vec![HistogramBucket { index: 0, count: 1 }]),
};
assert_eq!(event, expected);
}
#[test]
fn test_builder_as_string() {
let event = MetricEvent::builder(2).with_event_code(3).as_string("value");
let expected = MetricEvent {
metric_id: 2,
event_codes: vec![3],
payload: MetricEventPayload::StringValue("value".into()),
};
assert_eq!(event, expected);
}
#[test]
#[should_panic(expected = "Invalid index")]
fn test_bad_event_code_at_index() {
MetricEvent::builder(8).with_event_code_at(5, 10).as_occurrence(1);
}
}