blob: 06bb40e54a8318ac9d1b0fa5f8459327d0ac5187 [file] [log] [blame]
// Copyright 2020 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.
//! Defining and handling of the monitor environment.
//!
//! # Summary
//!
//! The monitoring logic in the setting service is meant to be modular. Based on
//! product configuration, a variety of sources (resource monitors) and
//! sinks (data outlets) may participate in the monitoring environment. The
//! components in this mod are meant to aid capturing and passing this setup
//! to the appropriate handling component, and bringing up the environment as
//! directed. The separation of this responsibility from the main
//! resource-watching component promotes code reshare and modularity.
use crate::message::base::MessengerType;
use crate::monitor::base::{
monitor::{self as base_monitor},
Error,
};
use crate::service;
/// `Actor` handles bringing up and controlling environment-specific components
/// surrounding monitoring, such as the resource monitors.
#[derive(Clone)]
pub struct Actor {
messenger_factory: service::message::Factory,
monitors: Vec<base_monitor::Generate>,
}
impl Actor {
/// Starts up environment monitors and returns a TargetedMessenger that
/// broadcasts to all monitors.
pub async fn start_monitoring(&self) -> Result<service::message::TargetedMessenger, Error> {
// Create unbound, broadcasting messenger to send messages to the monitors.
let monitor_messenger = service::message::TargetedMessenger::new(
self.messenger_factory
.create(MessengerType::Unbound)
.await
.map_err(|_| {
Error::MessageSetupFailure("could not create monitor messenger".into())
})?
.0,
service::message::Audience::Broadcast,
);
// Bring up each monitor.
for monitor in &self.monitors {
let (_, monitor_receptor) =
self.messenger_factory.create(MessengerType::Unbound).await.map_err(|_| {
Error::MessageSetupFailure("could not create monitor receptor".into())
})?;
monitor(base_monitor::Context { receptor: monitor_receptor })
.await
.map_err(|_| Error::MonitorSetupFailure("could not create monitor".into()))?
}
Ok(monitor_messenger)
}
}
/// `Builder` helps construct a monitoring environment in a step-wise fashion,
/// reutrning an [`Actor`] to control the resulting environment.
pub struct Builder {
monitors: Vec<base_monitor::Generate>,
}
impl Builder {
/// Returns a builder with no values set.
pub fn new() -> Self {
Self { monitors: vec![] }
}
/// Appends [`monitor::Generate`] to the set of monitors to participate in
/// this environment.
pub fn add_monitors(mut self, mut monitors: Vec<base_monitor::Generate>) -> Self {
self.monitors.append(&mut monitors);
self
}
/// Constructs the configuration.
pub fn build(self) -> Actor {
let monitor_messenger_factory = service::message::create_hub();
Actor { messenger_factory: monitor_messenger_factory, monitors: self.monitors }
}
}