trace_task/
lib.rs

1// Copyright 2025 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 fidl_fuchsia_tracing_controller::{self as trace, RecordingError, StartError};
6
7mod trace_task;
8mod triggers;
9
10pub use trace_task::TraceTask;
11pub use triggers::{Trigger, TriggerAction, TriggersWatcher};
12
13#[derive(Debug, thiserror::Error)]
14pub enum TracingError {
15    /// Error encountered when opening the proxy to the target.
16    #[error("cannot open proxy")]
17    TargetProxyOpen,
18    /// This is a general error when starting a trace.
19    #[error("cannot start recording: {0}")]
20    RecordingStart(String),
21    /// An error encountered if a trace recording has already been started
22    /// for a given Fuchsia target.
23    #[error("recording already started")]
24    RecordingAlreadyStarted,
25    /// An error encountered when attempting to stop a trace. This causes an
26    /// immediate termination of the client channel, so the user should not
27    /// attempt to run `StopRecording` again.
28    #[error("unable to stop recording: {0:?}")]
29    RecordingStop(String),
30    /// Error for when a trace file is already being written to by the tracing
31    /// service.
32    #[error("trace file {0} already exists.")]
33    DuplicateTraceFile(String),
34    /// When attempting to stop a trace, there were no active traces found for
35    /// the given lookup name.
36    #[error("trace file {0} does not exist.")]
37    NoSuchTraceFile(String),
38
39    #[error("fidl error: {0:?}")]
40    FidlError(#[from] fidl::Error),
41
42    #[error("general error: {0}")]
43    GeneralError(String),
44}
45
46impl From<StartError> for TracingError {
47    fn from(value: StartError) -> Self {
48        match value {
49            StartError::NotInitialized => Self::RecordingStart("not initialized".into()),
50            StartError::AlreadyStarted => Self::RecordingAlreadyStarted,
51            StartError::Stopping => Self::RecordingStart("tracing is stopping".into()),
52            StartError::Terminating => Self::RecordingStart("tracing is terminating".into()),
53            e => Self::GeneralError(format!("Unknown StartError: {e:?}")),
54        }
55    }
56}
57
58impl Into<RecordingError> for TracingError {
59    fn into(self) -> RecordingError {
60        match self {
61            TracingError::TargetProxyOpen => RecordingError::TargetProxyOpen,
62            TracingError::RecordingStart(_) => RecordingError::RecordingStart,
63            TracingError::RecordingAlreadyStarted => RecordingError::RecordingAlreadyStarted,
64            TracingError::RecordingStop(_) => RecordingError::RecordingStop,
65            TracingError::DuplicateTraceFile(_) => RecordingError::DuplicateTraceFile,
66            TracingError::NoSuchTraceFile(_) => RecordingError::NoSuchTraceFile,
67            TracingError::FidlError(_) | TracingError::GeneralError(_) => {
68                RecordingError::RecordingStart
69            }
70        }
71    }
72}
73
74impl PartialEq for TracingError {
75    fn eq(&self, other: &Self) -> bool {
76        match (self, other) {
77            (Self::RecordingStart(l0), Self::RecordingStart(r0)) => l0 == r0,
78            (Self::RecordingStop(l0), Self::RecordingStop(r0)) => l0 == r0,
79            (Self::DuplicateTraceFile(l0), Self::DuplicateTraceFile(r0)) => l0 == r0,
80            (Self::NoSuchTraceFile(l0), Self::NoSuchTraceFile(r0)) => l0 == r0,
81            (Self::FidlError(l0), Self::FidlError(r0)) => l0.to_string() == r0.to_string(),
82            (Self::GeneralError(l0), Self::GeneralError(r0)) => l0 == r0,
83            _ => core::mem::discriminant(self) == core::mem::discriminant(other),
84        }
85    }
86}
87
88pub(crate) async fn trace_shutdown(
89    proxy: &trace::SessionProxy,
90) -> Result<trace::StopResult, TracingError> {
91    let res = proxy
92        .stop_tracing(&trace::StopOptions { write_results: Some(true), ..Default::default() })
93        .await
94        .map_err(|e| {
95            log::warn!("stopping tracing: {:?}", e);
96            TracingError::RecordingStop(e.to_string())
97        })?
98        .map_err(|e| {
99            let msg = format!("Received stop error: {:?}", e);
100            log::warn!("{msg}");
101            TracingError::RecordingStop(msg)
102        });
103    res
104}