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