Skip to main content

input_pipeline/metrics/
mod.rs

1// Copyright 2023 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
5use crate::{Dispatcher, Incoming};
6use anyhow::{Context as _, Error};
7use cobalt_client::traits::AsEventCode;
8use fidl_fuchsia_metrics as metrics;
9use log::warn;
10use metrics_registry::*;
11
12/// Connects to the MetricEventLoggerFactory service to create a
13/// MetricEventLoggerProxy for the caller.
14fn create_metrics_logger(incoming: &Incoming) -> Result<metrics::MetricEventLoggerProxy, Error> {
15    let factory_proxy = incoming
16        .connect_protocol::<metrics::MetricEventLoggerFactoryProxy>()
17        .context("connecting to metrics")?;
18
19    let (cobalt_proxy, cobalt_server) =
20        fidl::endpoints::create_proxy::<metrics::MetricEventLoggerMarker>();
21
22    let project_spec = metrics::ProjectSpec {
23        customer_id: None, // defaults to fuchsia
24        project_id: Some(PROJECT_ID),
25        ..Default::default()
26    };
27
28    Dispatcher::spawn_local(async move {
29        match factory_proxy.create_metric_event_logger(&project_spec, cobalt_server).await {
30            Err(e) => warn!("FIDL failure setting up event logger: {e:?}"),
31            Ok(Err(e)) => warn!("CreateMetricEventLogger failure: {e:?}"),
32            Ok(Ok(())) => {}
33        }
34    })
35    .detach();
36
37    Ok(cobalt_proxy)
38}
39
40fn log_on_failure(result: Result<Result<(), metrics::Error>, fidl::Error>) {
41    match result {
42        Ok(Ok(())) => (),
43        e => warn!("failed to log metrics: {:?}", e),
44    };
45}
46
47/// A client connection to the Cobalt logging service.
48#[derive(Clone, Debug, Default)]
49pub struct MetricsLogger(Option<metrics::MetricEventLoggerProxy>);
50
51impl MetricsLogger {
52    pub fn new(incoming: &Incoming) -> Self {
53        let logger = create_metrics_logger(incoming)
54            .map_err(|e| warn!("Failed to create metrics logger: {e}"))
55            .ok();
56        Self(logger)
57    }
58
59    /// Logs an warning occurrence metric using the Cobalt logger. Does not block execution.
60    pub fn log_warn<E: AsEventCode, S: Into<String>>(&self, event_code: E, message: S) {
61        log::warn!("{}", message.into());
62        self.send_metric(event_code);
63    }
64
65    /// Logs an error occurrence metric using the Cobalt logger. Does not block execution.
66    pub fn log_error<E: AsEventCode, S: Into<String>>(&self, event_code: E, message: S) {
67        log::error!("{}", message.into());
68        self.send_metric(event_code);
69    }
70
71    // send metric, does not block the execution.
72    fn send_metric<E: AsEventCode>(&self, event_code: E) {
73        let Some(c) = self.0.clone() else { return };
74        let code = event_code.as_event_code();
75        Dispatcher::spawn_local(async move {
76            log_on_failure(c.log_occurrence(INPUT_PIPELINE_ERROR_METRIC_ID, 1, &[code]).await);
77        })
78        .detach();
79    }
80}