• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Encapsulate the main runtime loop of a metrics process.
6 
7 use anyhow::Result;
8 use base::info;
9 use base::warn;
10 use base::EventToken;
11 use base::Tube;
12 
13 use crate::metrics_requests::MetricsRequest;
14 use crate::RequestHandler;
15 
16 /// Handles incoming requests to log metrics
17 pub(crate) trait MetricsRequestHandler {
new() -> Self18     fn new() -> Self;
handle_request(&self, request: MetricsRequest)19     fn handle_request(&self, request: MetricsRequest);
shutdown(&self)20     fn shutdown(&self);
21 }
22 
23 /// Runs the metrics controller.
24 pub struct MetricsController {
25     pub(crate) agents: Vec<Tube>,
26     handler: RequestHandler,
27     pub(crate) closed_tubes: usize,
28 }
29 
30 #[derive(EventToken)]
31 pub(crate) enum MetricsControllerToken {
32     /// Triggered when the agent's pipe is readable (e.g. read_notifier).
33     Agent(usize),
34     /// Triggered when the agent's pipe closes (e.g. close_notifier).
35     #[cfg(windows)]
36     AgentExited(usize),
37 }
38 
39 impl MetricsController {
new(agents: Vec<Tube>) -> Self40     pub fn new(agents: Vec<Tube>) -> Self {
41         Self {
42             agents,
43             handler: RequestHandler::new(),
44             closed_tubes: 0,
45         }
46     }
47 
48     /// Run the metrics controller until all clients exit & close their Tubes.
run(&mut self) -> Result<()>49     pub fn run(&mut self) -> Result<()> {
50         self.run_internal()?;
51         self.handler.shutdown();
52         Ok(())
53     }
54 
55     /// Handles a tube that has indicated it has data ready to read.
on_tube_readable(&self, client: &Tube)56     pub(crate) fn on_tube_readable(&self, client: &Tube) {
57         match client.recv::<MetricsRequest>() {
58             Ok(req) => self.handler.handle_request(req),
59             Err(e) => {
60                 warn!("unexpected error receiving agent metrics request: {}", e)
61             }
62         }
63     }
64 
65     /// Handles a closed connection, and returns a bool indicating
66     /// whether the run loop itself should close.
on_connection_closed(&mut self) -> bool67     pub(crate) fn on_connection_closed(&mut self) -> bool {
68         self.closed_tubes += 1;
69         info!(
70             "metrics tube closed: {} out of {} closed",
71             self.closed_tubes,
72             self.agents.len(),
73         );
74         if self.closed_tubes == self.agents.len() {
75             info!("metrics run loop exiting: all tubes closed");
76             return true;
77         }
78 
79         false
80     }
81 }
82