blob: 7ccf3accbdfb0467913552ca8aaecc90f96f0210 [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 `CobaltEvent`.
use {
cobalt_client::traits::AsEventCodes,
fidl_fuchsia_cobalt::{CobaltEvent, CountEvent, EventPayload, HistogramBucket},
};
/// Adds the `builder()` method to `CobaltEvent`.
pub trait CobaltEventExt {
/// Returns a `CobaltEventBuilder` for the specified `metric_id`.
///
/// # Examples
///
/// ```
/// assert_eq!(CobaltEvent::builder(5).as_event().metric_id, 0);
/// ```
fn builder(metric_id: u32) -> CobaltEventBuilder;
}
impl CobaltEventExt for CobaltEvent {
fn builder(metric_id: u32) -> CobaltEventBuilder {
CobaltEventBuilder { metric_id, ..CobaltEventBuilder::default() }
}
}
/// CobaltEventBuilder allows for a chained construction of `CobaltEvent` objects.
#[derive(Debug, Default, Clone)]
pub struct CobaltEventBuilder {
metric_id: u32,
event_codes: Vec<u32>,
component: Option<String>,
}
impl CobaltEventBuilder {
/// Appends the provided `event_code` to the `event_codes` list.
///
/// # Examples
///
/// ```
/// assert_eq!(CobaltEvent::builder(6).with_event_code(10).as_event().event_codes, vec![10]);
/// ```
pub fn with_event_code(mut self, event_code: u32) -> CobaltEventBuilder {
self.event_codes.push(event_code);
self
}
/// Overrides the list of event_codes with the provided `event_codes`.
///
/// # Examples
///
/// ```
/// assert_eq!(
/// CobaltEvent::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,
) -> CobaltEventBuilder {
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!(
/// CobaltEvent::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) -> CobaltEventBuilder {
assert!(
index < 5,
"Invalid index passed to CobaltEventBuilder::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
}
/// Adds the provided `component` string to the resulting `CobaltEvent`.
///
/// # Examples
///
/// ```
/// assert_eq!(
/// CobaltEvent::builder(9).with_component("Comp").as_event.component,
/// Some("Comp".to_owned()));
/// ```
pub fn with_component<S: Into<String>>(mut self, component: S) -> CobaltEventBuilder {
self.component = Some(component.into());
self
}
/// Constructs a `CobaltEvent` with the provided `EventPayload`.
///
/// # Examples
/// ```
/// let payload = EventPayload::Event(fidl_fuchsia_cobalt::Event);
/// assert_eq!(CobaltEvent::builder(10).build(payload.clone()).payload, payload);
/// ```
pub fn build(self, payload: EventPayload) -> CobaltEvent {
CobaltEvent {
metric_id: self.metric_id,
event_codes: self.event_codes,
component: self.component,
payload,
}
}
/// Constructs a `CobaltEvent` with a payload type of `EventPayload::Event`.
///
/// # Examples
/// ```
/// asert_eq!(
/// CobaltEvent::builder(11).as_event().payload,
/// EventPayload::Event(fidl_fuchsia_cobalt::Event));
/// ```
pub fn as_event(self) -> CobaltEvent {
self.build(EventPayload::Event(fidl_fuchsia_cobalt::Event))
}
/// Constructs a `CobaltEvent` with a payload type of `EventPayload::EventCount`.
///
/// # Examples
/// ```
/// asert_eq!(
/// CobaltEvent::builder(12).as_count_event(5, 10).payload,
/// EventPayload::EventCount(CountEvent { period_duration_micros: 5, count: 10 }));
/// ```
pub fn as_count_event(self, period_duration_micros: i64, count: i64) -> CobaltEvent {
self.build(EventPayload::EventCount(CountEvent { period_duration_micros, count }))
}
/// Constructs a `CobaltEvent` with a payload type of `EventPayload::ElapsedMicros`.
///
/// # Examples
/// ```
/// asert_eq!(
/// CobaltEvent::builder(13).as_elapsed_time(30).payload,
/// EventPayload::ElapsedMicros(30));
/// ```
pub fn as_elapsed_time(self, elapsed_micros: i64) -> CobaltEvent {
self.build(EventPayload::ElapsedMicros(elapsed_micros))
}
/// Constructs a `CobaltEvent` with a payload type of `EventPayload::Fps`.
///
/// # Examples
/// ```
/// asert_eq!(
/// CobaltEvent::builder(14).as_frame_rate(99.).payload,
/// EventPayload::Fps(99.));
/// ```
pub fn as_frame_rate(self, fps: f32) -> CobaltEvent {
self.build(EventPayload::Fps(fps))
}
/// Constructs a `CobaltEvent` with a payload type of `EventPayload::MemoryBytesUsed`.
///
/// # Examples
/// ```
/// asert_eq!(
/// CobaltEvent::builder(15).as_memory_usage(1000).payload,
/// EventPayload::MemoryBytesUsed(1000));
/// ```
pub fn as_memory_usage(self, memory_bytes_used: i64) -> CobaltEvent {
self.build(EventPayload::MemoryBytesUsed(memory_bytes_used))
}
/// Constructs a `CobaltEvent` with a payload type of `EventPayload::IntHistogram`.
///
/// # Examples
/// ```
/// let histogram = vec![HistogramBucket { index: 0, count: 1 }];
/// asert_eq!(
/// CobaltEvent::builder(17).as_int_histogram(histogram.clone()).payload,
/// EventPayload::IntHistogram(histogram));
/// ```
pub fn as_int_histogram(self, int_histogram: Vec<HistogramBucket>) -> CobaltEvent {
self.build(EventPayload::IntHistogram(int_histogram))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder_as_event() {
let event = CobaltEvent::builder(1).with_event_code(2).as_event();
let expected = CobaltEvent {
metric_id: 1,
event_codes: vec![2],
component: None,
payload: EventPayload::Event(fidl_fuchsia_cobalt::Event),
};
assert_eq!(event, expected);
}
#[test]
fn test_builder_as_count_event() {
let event =
CobaltEvent::builder(2).with_event_code(3).with_component("A").as_count_event(4, 5);
let expected = CobaltEvent {
metric_id: 2,
event_codes: vec![3],
component: Some("A".into()),
payload: EventPayload::EventCount(CountEvent { count: 5, period_duration_micros: 4 }),
};
assert_eq!(event, expected);
}
#[test]
fn test_as_elapsed_time() {
let event =
CobaltEvent::builder(3).with_event_code(4).with_component("B").as_elapsed_time(5);
let expected = CobaltEvent {
metric_id: 3,
event_codes: vec![4],
component: Some("B".into()),
payload: EventPayload::ElapsedMicros(5),
};
assert_eq!(event, expected);
}
#[test]
fn test_as_frame_rate() {
let event =
CobaltEvent::builder(4).with_event_code(5).with_component("C").as_frame_rate(6.);
let expected = CobaltEvent {
metric_id: 4,
event_codes: vec![5],
component: Some("C".into()),
payload: EventPayload::Fps(6.),
};
assert_eq!(event, expected);
}
#[test]
fn test_as_memory_usage() {
let event =
CobaltEvent::builder(5).with_event_code(6).with_component("D").as_memory_usage(7);
let expected = CobaltEvent {
metric_id: 5,
event_codes: vec![6],
component: Some("D".into()),
payload: EventPayload::MemoryBytesUsed(7),
};
assert_eq!(event, expected);
}
#[test]
fn test_as_int_histogram() {
let event = CobaltEvent::builder(7)
.with_event_code(8)
.with_component("E")
.as_int_histogram(vec![HistogramBucket { index: 0, count: 1 }]);
let expected = CobaltEvent {
metric_id: 7,
event_codes: vec![8],
component: Some("E".into()),
payload: EventPayload::IntHistogram(vec![HistogramBucket { index: 0, count: 1 }]),
};
assert_eq!(event, expected);
}
#[test]
#[should_panic(expected = "Invalid index")]
fn test_bad_event_code_at_index() {
CobaltEvent::builder(8).with_event_code_at(5, 10).as_event();
}
}