blob: aec2a600ea200a17790ba8f32affe3b8b699b2d2 [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.
use {
anyhow::{format_err, Context, Error},
fidl_fuchsia_metrics::{MetricEventLoggerFactoryMarker, MetricEventLoggerProxy, ProjectSpec},
fuchsia_async as fasync,
fuchsia_component::client::connect_to_protocol,
fuchsia_zircon as zx,
session_framework_metrics_registry::cobalt_registry as metrics,
tracing::error,
};
/// Creates a LoggerProxy connected to Cobalt.
///
/// The connection is performed in a Future run on the global executor, but the `LoggerProxy`
/// can be used immediately.
///
/// # Returns
/// `LoggerProxy` for log messages to be sent to.
pub fn get_logger() -> Result<MetricEventLoggerProxy, Error> {
let (logger_proxy, server_end) =
fidl::endpoints::create_proxy().context("Failed to create endpoints")?;
let logger_factory = connect_to_protocol::<MetricEventLoggerFactoryMarker>()
.context("Failed to connect to the Cobalt MetricEventLoggerFactory")?;
fasync::Task::spawn(async move {
if let Err(err) = logger_factory
.create_metric_event_logger(
ProjectSpec { project_id: Some(metrics::PROJECT_ID), ..ProjectSpec::EMPTY },
server_end,
)
.await
{
error!(%err, "Failed to create Cobalt logger");
}
})
.detach();
Ok(logger_proxy)
}
/// Reports the time elapsed while launching a session.
///
/// # Parameters
/// - `logger_proxy`: The cobalt logger.
/// - `start_time`: The time when session_manager starts launching a session.
/// - `end_time`: The time when session_manager has bound to a session. This must be strictly after
/// `start_time`.
///
/// # Returns
/// `Ok` if the time elapsed was logged successfully.
pub async fn log_session_launch_time(
logger_proxy: MetricEventLoggerProxy,
start_time: zx::Time,
end_time: zx::Time,
) -> Result<(), Error> {
let elapsed_time = (end_time - start_time).into_micros();
if elapsed_time < 0 {
return Err(format_err!("End time must be after start time."));
}
logger_proxy
.log_integer(
metrics::SESSION_LAUNCH_TIME_MIGRATED_METRIC_ID,
elapsed_time,
&[metrics::SessionLaunchTimeMigratedMetricDimensionStatus::Success as u32],
)
.await
.context("Could not log session launch time.")?
.map_err(|e| format_err!("Logging session launch time returned an error: {:?}", e))?;
Ok(())
}
#[cfg(test)]
mod tests {
use {
super::*,
fidl::endpoints::create_proxy_and_stream,
fidl_fuchsia_metrics::{MetricEventLoggerMarker, MetricEventLoggerRequest},
futures::TryStreamExt,
};
/// Tests that the right payload is sent to Cobalt when logging the session launch time.
#[fasync::run_singlethreaded(test)]
async fn test_log_session_launch_time() {
let (logger_proxy, mut logger_server) =
create_proxy_and_stream::<MetricEventLoggerMarker>()
.expect("Failed to create Logger FIDL.");
let start_time = zx::Time::from_nanos(0);
let end_time = zx::Time::from_nanos(5000);
fasync::Task::spawn(async move {
let _ = log_session_launch_time(logger_proxy, start_time, end_time).await;
})
.detach();
if let Some(log_request) = logger_server.try_next().await.unwrap() {
if let MetricEventLoggerRequest::LogInteger {
metric_id,
value,
event_codes,
responder: _,
} = log_request
{
assert_eq!(metric_id, metrics::SESSION_LAUNCH_TIME_MIGRATED_METRIC_ID);
assert_eq!(
event_codes,
vec![metrics::SessionLaunchTimeMigratedMetricDimensionStatus::Success as u32]
);
assert_eq!(value, 5);
} else {
assert!(false);
}
} else {
assert!(false);
}
}
/// Tests that an error is raised if end_time < start_time.
#[fasync::run_singlethreaded(test)]
async fn test_log_session_launch_time_swap_start_end_time() {
let (logger_proxy, _logger_server) = create_proxy_and_stream::<MetricEventLoggerMarker>()
.expect("Failed to create Logger FIDL.");
let start_time = zx::Time::from_nanos(0);
let end_time = zx::Time::from_nanos(5000);
assert!(log_session_launch_time(logger_proxy, end_time, start_time).await.is_err());
}
}