Skip to main content

edgefirst_client/
instrument.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025 Au-Zone Technologies. All Rights Reserved.
3
4//! Conditional instrumentation support for profiling.
5//!
6//! This module provides tracing integration when the `profiling` feature is
7//! enabled. When disabled, instrumentation compiles to zero-cost no-ops.
8//!
9//! # Features
10//!
11//! - `profiling` - Base feature enabling tracing spans (no backend)
12//! - `trace-file` - Trace file output in Chrome JSON (.json) or Perfetto
13//!   (.pftrace) format
14//!
15//! # Usage
16//!
17//! For method-level instrumentation, use the `#[cfg_attr]` pattern:
18//!
19//! ```rust,ignore
20//! #[cfg_attr(feature = "profiling", tracing::instrument(skip(self)))]
21//! pub async fn my_method(&self) -> Result<T, Error> {
22//!     // ...
23//! }
24//! ```
25//!
26//! For manual span creation within functions:
27//!
28//! ```rust,ignore
29//! #[cfg(feature = "profiling")]
30//! let _span = tracing::info_span!("operation_name", field = value).entered();
31//!
32//! // ... code to profile
33//!
34//! #[cfg(feature = "profiling")]
35//! drop(_span);  // Optional: explicitly end span early
36//! ```
37//!
38//! # Trace Output
39//!
40//! When built with the `trace-file` feature, traces can be written to files:
41//! - `.json` extension → Chrome JSON format (viewable in Perfetto UI)
42//! - `.pftrace` extension → Native Perfetto format (viewable in Perfetto UI)
43//!
44//! Use `--trace-file path.json` or `--trace-file path.pftrace` to select
45//! format.
46
47#[cfg(feature = "profiling")]
48pub use tracing::{
49    Instrument, Level, Span, debug, debug_span, error, error_span, info, info_span, instrument,
50    trace, trace_span, warn, warn_span,
51};
52
53/// Conditional span creation macro - compiles to no-op when profiling is
54/// disabled.
55///
56/// # Example
57///
58/// ```rust,ignore
59/// use edgefirst_client::span;
60///
61/// fn process_data() {
62///     let _span = span!("process_data", items = 100);
63///     // ... processing
64/// }
65/// ```
66#[cfg(feature = "profiling")]
67#[macro_export]
68macro_rules! span {
69    ($name:expr) => {
70        tracing::info_span!($name)
71    };
72    ($name:expr, $($field:tt)*) => {
73        tracing::info_span!($name, $($field)*)
74    };
75}
76
77#[cfg(not(feature = "profiling"))]
78#[macro_export]
79macro_rules! span {
80    ($name:expr) => {
81        ()
82    };
83    ($name:expr, $($field:tt)*) => {
84        ()
85    };
86}
87
88/// Conditional event recording macro - compiles to no-op when profiling is
89/// disabled.
90///
91/// Use this for recording events within spans without creating new spans.
92///
93/// # Example
94///
95/// ```rust,ignore
96/// use edgefirst_client::trace_event;
97///
98/// fn download_file(url: &str) {
99///     trace_event!("starting download", url = %url);
100///     // ... download
101///     trace_event!("download complete", bytes = 1024);
102/// }
103/// ```
104#[cfg(feature = "profiling")]
105#[macro_export]
106macro_rules! trace_event {
107    ($($arg:tt)*) => {
108        tracing::info!($($arg)*)
109    };
110}
111
112#[cfg(not(feature = "profiling"))]
113#[macro_export]
114macro_rules! trace_event {
115    ($($arg:tt)*) => {};
116}