Skip to content

Commit

Permalink
layer: Document all public items
Browse files Browse the repository at this point in the history
  • Loading branch information
dflemstr committed Oct 30, 2024
1 parent 0a75aed commit a95be4a
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 5 deletions.
11 changes: 11 additions & 0 deletions crates/layer/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@ pub enum Error {
/// A generic C++ exception occurred in the C++ code.
#[error("C++ code threw an exception: {0}")]
Cxx(#[from] cxx::Exception),
/// A generic OS-level IO error occurred.
#[error("IO error: {0}")]
IO(#[from] io::Error),
/// An internal `Mutex` is poisoned due to some other thread panicking while
/// holding the mutex.
#[error("Encountered a poisoned mutex")]
PoisonedMutex,
/// An operation can't complete because someone already called
/// `layer.stop()` on the layer.
#[error("The layer has been stopped")]
LayerStopped,
/// An operation timed out according to one of the timeouts set in the layer
/// builder.
#[error("Failed to complete operation before timeout was reached")]
TimedOut,
/// A flush failed due to some unknown reason.
///
/// This is not necessarily separate from the `TimedOut` case; we simply
/// don't know the reason why the flush failed.
#[error("Failed to flush data due to some unknown reason (might also be due to timeout)")]
FlushFailed,
}
Expand Down
59 changes: 59 additions & 0 deletions crates/layer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![deny(clippy::all)]
#![deny(missing_docs)]
//! # `tracing-perfetto-sdk-layer`
//! A suite of tracing layers that reports traces via the C++ Perfetto SDK
//!
Expand Down Expand Up @@ -35,6 +36,35 @@
//! });
//! ```
//!
//! ## Trace config
//!
//! The layer constructor expects a `TraceConfig` protobuf message to configure
//! tracing settings. This can either be supplied as a `prost`-generated struct
//! or as raw (protobuf-encoded) bytes. The raw bytes option might be useful if
//! you want to embed a config with your binary that doesn't have to change, and
//! you want to save on space/overhead/... In the end the config will
//! always be encoded to bytes anyway to be sent to the C++ SDK.
//!
//! Since the protobuf schema also implements `serde` traits, you can load/store
//! the config file in any format you like, as long as there is a `serde` codec
//! for it. To activate the `tracing` data source, you need to add at least the
//! `rust_tracing` data source in the relevant config section (here, the config
//! is in YAML format):
//!
//! ```yaml
//! buffers:
//! - size_kb: 1024
//! data_sources:
//! - config:
//! name: "rust_tracing"
//! ```
//!
//! This is a good starting point for a minimal config file. If you want to
//! activate additional data sources, you can add them here; just remember that
//! most of them rely on the `traced daemon running on the host, and requires
//! you to use system mode (Explained further below in the section "Controlling
//! output destinations").
//!
//! ## Using counters
//!
//! When logging trace events, such as when calling `tracing::info!()` and
Expand All @@ -55,6 +85,9 @@
//! tracing::info!(counter.mem_usage.bytes=42, counter.cpu_usage.percent=23.2, "hi!");
//! ```
//!
//! The unit will be reported properly in the Perfetto UI at the track-level
//! next to the sidebar of each line chart.
//!
//! **NOTE**: at the time of writing, counters are only implemented by the
//! [`NativeLayer`].
//!
Expand Down Expand Up @@ -99,6 +132,32 @@
//! system's `traced` daemon, or (in the case of [`NativeLayer`]) poll for
//! system-wide traces from the `traced` daemon and include them in the trace
//! file.
//!
//! ## Sharing
//!
//! Layers are cloneable and will internally keep a reference count to keep the
//! layer internals alive. This means you can make a clone of the layer to
//! control it from many places at once. For example, it can be useful to have a
//! clone of the layer to be able to call `.flush()` or `.stop()` from somewhere
//! else.
//!
//! ## Timeouts
//!
//! The layers allow you to configure various timeouts that will be used
//! throughout the lifecycle of a layer. These are:
//!
//! * `drop_flush_timeout`: When the layer is dropped: how long to wait for a
//! final flush to complete before destroying the layer. If you want to
//! avoid this cost during `drop()`, call `.stop()` manually before the
//! layer is dropped.
//! * `background_flush_timeout`: In the case of [`NativeLayer`], a background
//! thread is used to fetch data from the SDK into the Rust world. This
//! controls how long we wait for each flush to complete; however, if it
//! doesn't complete in time, another attempt will soon be made.
//! * `background_poll_timeout`: How long to wait for new data to arrive
//! during each attempt of the background thread.
//! * `background_poll_interval`: How long to wait between attempts to poll
//! for new data in the background thread.
// Internal modules:
mod debug_annotations;
Expand Down
33 changes: 33 additions & 0 deletions crates/layer/src/native_layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub struct NativeLayer<W> {
inner: sync::Arc<Inner<W>>,
}

/// A builder for [`NativeLayer`]; use [`NativeLayer::from_config`] or
/// [`NativeLayer::from_config_bytes`] to create a new instance.
pub struct Builder<'c, W> {
config_bytes: borrow::Cow<'c, [u8]>,
writer: W,
Expand Down Expand Up @@ -65,11 +67,26 @@ impl<W> NativeLayer<W>
where
W: for<'w> fmt::MakeWriter<'w> + Send + Sync + 'static,
{
/// Create a new layer builder from the supplied proto config.
///
/// The proto config is usually read from an external source using the
/// prototext syntax, or else using one of the `serde` codecs. The config
/// will internally be encoded to bytes straight away, so prefer
/// [`NativeLayer::from_config_bytes`] if you already have the byte
/// representation.
///
/// The built layer will write traces to the supplied writer.
pub fn from_config(config: schema::TraceConfig, writer: W) -> Builder<'static, W> {
use prost::Message as _;
Builder::new(config.encode_to_vec().into(), writer)
}

/// Create a new layer builder from the supplied proto config bytes.
///
/// The proto config bytes needs to be an already encoded message of type
/// [`schema::TraceConfig`].
///
/// The built layer will write traces to the supplied writer.
pub fn from_config_bytes(config_bytes: &[u8], writer: W) -> Builder<W> {
Builder::new(config_bytes.into(), writer)
}
Expand Down Expand Up @@ -181,10 +198,13 @@ where
}
}

/// Flush internal buffers, making the best effort for all pending writes to
/// be visible on this layer's `writer`.
pub fn flush(&self, timeout: time::Duration) -> error::Result<()> {
self.inner.flush(timeout)
}

/// Stop the layer and stop collecting traces.
pub fn stop(&self) -> error::Result<()> {
self.inner.stop()
}
Expand Down Expand Up @@ -633,26 +653,36 @@ where
}
}

/// If `Some`, force the specified trace flavor. If `None`, use heuristics
/// for every created span to determine the flavor.
pub fn with_force_flavor(mut self, force_flavor: Option<flavor::Flavor>) -> Self {
self.force_flavor = force_flavor;
self
}

/// Enable in-process collection, where traces will be collected by buffers
/// in the Perfetto SDK and spilled to file in-process.
pub fn with_enable_in_process(mut self, enable_in_process: bool) -> Self {
self.enable_in_process = enable_in_process;
self
}

/// Enable system collection, where traces will be sent/collected from the
/// `traced` daemon, and additional system-wide data sources (such as
/// `ftrace`, `procfs`, `sysfs`, etc.) can be collected too.
pub fn with_enable_system(mut self, enable_system: bool) -> Self {
self.enable_system = enable_system;
self
}

/// The timeout of the final flush that will happen when dropping this
/// layer.
pub fn with_drop_flush_timeout(mut self, drop_flush_timeout: time::Duration) -> Self {
self.drop_flush_timeout = drop_flush_timeout;
self
}

/// The timeout of each flush in the background trace polling thread.
pub fn with_background_flush_timeout(
mut self,
background_flush_timeout: time::Duration,
Expand All @@ -661,11 +691,13 @@ where
self
}

/// The timeout of each poll in the background trace polling thread.
pub fn with_background_poll_timeout(mut self, background_poll_timeout: time::Duration) -> Self {
self.background_poll_timeout = background_poll_timeout;
self
}

/// The delay between each poll in the background trace polling thread.
pub fn with_background_poll_interval(
mut self,
background_poll_interval: time::Duration,
Expand All @@ -674,6 +706,7 @@ where
self
}

/// Turn this builder into a built layer.
pub fn build(self) -> error::Result<NativeLayer<W>> {
NativeLayer::build(self)
}
Expand Down
44 changes: 39 additions & 5 deletions crates/layer/src/sdk_layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub struct SdkLayer {
inner: sync::Arc<Inner>,
}

/// A builder for [`SdkLayer`]; use [`SdkLayer::from_config`] or
/// [`SdkLayer::from_config_bytes`] to create a new instance.
pub struct Builder<'c> {
config_bytes: borrow::Cow<'c, [u8]>,
output_file: Option<fs::File>,
Expand Down Expand Up @@ -46,6 +48,18 @@ struct Inner {
}

impl SdkLayer {
/// Create a new layer builder from the supplied proto config.
///
/// The proto config is usually read from an external source using the
/// prototext syntax, or else using one of the `serde` codecs. The config
/// will internally be encoded to bytes straight away, so prefer
/// [`NativeLayer::from_config_bytes`] if you already have the byte
/// representation.
///
/// The built layer will write traces to the supplied output file. If no
/// file is specified, it is probably only useful to run in system mode, so
/// that the traces are sent to the `traced` daemon instead (else they would
/// just get lost).
pub fn from_config(
config: schema::TraceConfig,
output_file: Option<fs::File>,
Expand All @@ -54,6 +68,15 @@ impl SdkLayer {
Builder::new(config.encode_to_vec().into(), output_file)
}

/// Create a new layer builder from the supplied proto config bytes.
///
/// The proto config bytes needs to be an already encoded message of type
/// [`schema::TraceConfig`].
///
/// The built layer will write traces to the supplied output file. If no
/// file is specified, it is probably only useful to run in system mode, so
/// that the traces are sent to the `traced` daemon instead (else they would
/// just get lost).
pub fn from_config_bytes(config_bytes: &[u8], output_file: Option<fs::File>) -> Builder {
Builder::new(config_bytes.into(), output_file)
}
Expand Down Expand Up @@ -183,10 +206,13 @@ impl SdkLayer {
)
}

/// Flush internal buffers, making the best effort for all pending writes to
/// be visible on this layer's `output_file`.
pub fn flush(&self, timeout: time::Duration) -> error::Result<()> {
self.inner.flush(timeout)
}

/// Stop the layer and stop collecting traces.
pub fn stop(&self) -> error::Result<()> {
self.inner.stop()
}
Expand Down Expand Up @@ -354,21 +380,29 @@ impl<'c> Builder<'c> {
}
}

pub fn with_drop_flush_timeout(mut self, drop_flush_timeout: time::Duration) -> Self {
self.drop_flush_timeout = drop_flush_timeout;
self
}

/// Enable in-process collection, where traces will be collected by buffers
/// in the Perfetto SDK and spilled to file in-process.
pub fn with_enable_in_process(mut self, enable_in_process: bool) -> Self {
self.enable_in_process = enable_in_process;
self
}

/// Enable system collection, where traces will be sent/collected from the
/// `traced` daemon, and additional system-wide data sources (such as
/// `ftrace`, `procfs`, `sysfs`, etc.) can be collected too.
pub fn with_enable_system(mut self, enable_system: bool) -> Self {
self.enable_system = enable_system;
self
}

/// The timeout of the final flush that will happen when dropping this
/// layer.
pub fn with_drop_flush_timeout(mut self, drop_flush_timeout: time::Duration) -> Self {
self.drop_flush_timeout = drop_flush_timeout;
self
}

/// Turn this builder into a built layer.
pub fn build(self) -> error::Result<SdkLayer> {
SdkLayer::build(self)
}
Expand Down

0 comments on commit a95be4a

Please sign in to comment.