diff --git a/CHANGELOG.md b/CHANGELOG.md index cb8163a0..b5ff0197 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Add `LocalSpans::to_span_records()`. + ## v0.6.2 - Improve documentation. diff --git a/minitrace-macro/src/lib.rs b/minitrace-macro/src/lib.rs index 59715e37..adf3d65b 100644 --- a/minitrace-macro/src/lib.rs +++ b/minitrace-macro/src/lib.rs @@ -174,7 +174,7 @@ pub fn trace( // let's rewrite some statements! match internal_fun.kind { // async-trait <= 0.1.43 - AsyncTraitKind::Function(_) => { + AsyncTraitKind::Function => { unimplemented!( "Please upgrade the crate `async-trait` to a version higher than 0.1.44" ) @@ -185,7 +185,7 @@ pub fn trace( // useful for crates exhibiting the same behaviors as async-trait let instrumented_block = gen_block(&async_expr.block, true, false, args); let async_attrs = &async_expr.attrs; - quote! { + quote::quote! { Box::pin(#(#async_attrs) * #instrumented_block) } } @@ -292,7 +292,7 @@ fn gen_name(span: proc_macro2::Span, name: Name) -> proc_macro2::TokenStream { enum AsyncTraitKind<'a> { // old construction. Contains the function - Function(&'a ItemFn), + Function, // new construction. Contains a reference to the async block Async(&'a ExprAsync), } @@ -396,13 +396,13 @@ fn get_async_trait_info(block: &Block, block_is_async: bool) -> Option Vec { + let anchor: Anchor = Anchor::new(); + let mut dangling_events = HashMap::new(); + let mut records = Vec::new(); + amend_local_span( + self, + parent.trace_id, + parent.span_id, + &mut records, + &mut dangling_events, + &anchor, + ); + mount_events(&mut records, &mut dangling_events); + records + } +} + fn amend_local_span( local_spans: &LocalSpansInner, trace_id: TraceId, diff --git a/minitrace/src/collector/mod.rs b/minitrace/src/collector/mod.rs index b907d010..ae577add 100644 --- a/minitrace/src/collector/mod.rs +++ b/minitrace/src/collector/mod.rs @@ -43,7 +43,7 @@ pub enum SpanSet { /// A record of a span that includes all the information about the span, /// such as its identifiers, timing information, name, and associated properties. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct SpanRecord { pub trace_id: TraceId, pub span_id: SpanId, @@ -56,7 +56,7 @@ pub struct SpanRecord { } /// A record of an event that occurred during the execution of a span. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct EventRecord { pub name: Cow<'static, str>, pub timestamp_unix_ns: u64, diff --git a/minitrace/src/local/local_collector.rs b/minitrace/src/local/local_collector.rs index 2c9a3d31..a16e7075 100644 --- a/minitrace/src/local/local_collector.rs +++ b/minitrace/src/local/local_collector.rs @@ -9,6 +9,8 @@ use minstant::Instant; use crate::local::local_span_stack::LocalSpanStack; use crate::local::local_span_stack::SpanLineHandle; use crate::local::local_span_stack::LOCAL_SPAN_STACK; +use crate::prelude::SpanContext; +use crate::prelude::SpanRecord; use crate::util::CollectToken; use crate::util::RawSpans; @@ -183,13 +185,64 @@ impl Drop for LocalCollector { } } +impl LocalSpans { + /// Converts the `LocalSpans` to `SpanRecord`s. + /// + /// The converted spans will appear as if they were collected within the given parent context. + /// The parent of the top local span is set to the given parent. + /// + /// This function is particularly useful when you want to manually collect the span records + /// without involving the global collector. This function does not require that the global + /// collector is set up by [`set_reporter()`]. + /// + /// # Example + /// + /// ```rust + /// use minitrace::local::LocalCollector; + /// use minitrace::local::LocalSpans; + /// use minitrace::prelude::*; + /// + /// // Collect local spans manually without a parent + /// let collector = LocalCollector::start(); + /// let span = LocalSpan::enter_with_local_parent("a child span"); + /// drop(span); + /// + /// // Collect local spans into a LocalSpans instance + /// let local_spans: LocalSpans = collector.collect(); + /// + /// // Convert LocalSpans to SpanRecords with a given parent context + /// let parent_context = SpanContext::random(); + /// let span_records = local_spans.to_span_records(parent_context); + /// + /// // Now you can manually handle the span records + /// for record in span_records { + /// println!("{:?}", record); + /// } + /// ``` + /// + /// [`set_reporter()`]: crate::set_reporter + pub fn to_span_records(&self, parent: SpanContext) -> Vec { + #[cfg(not(feature = "enable"))] + { + vec![] + } + + #[cfg(feature = "enable")] + { + self.inner.to_span_records(parent) + } + } +} + #[cfg(test)] mod tests { use super::*; use crate::collector::CollectTokenItem; use crate::collector::SpanId; + use crate::prelude::LocalSpan; use crate::prelude::TraceId; use crate::util::tree::tree_str_from_raw_spans; + use crate::util::tree::tree_str_from_span_records; #[test] fn local_collector_basic() { @@ -259,4 +312,26 @@ span1 [] " ); } + + #[test] + fn local_spans_to_span_record() { + let collector = LocalCollector::start(); + let span1 = LocalSpan::enter_with_local_parent("span1").with_property(|| ("k1", "v1")); + let span2 = LocalSpan::enter_with_local_parent("span2").with_property(|| ("k2", "v2")); + drop(span2); + drop(span1); + + let local_spans: LocalSpans = collector.collect(); + + let parent_context = SpanContext::random(); + let span_records = local_spans.to_span_records(parent_context); + + assert_eq!( + tree_str_from_span_records(span_records), + r#" +span1 [("k1", "v1")] + span2 [("k2", "v2")] +"# + ); + } } diff --git a/test-statically-disable/src/main.rs b/test-statically-disable/src/main.rs index e8179117..c08c1aeb 100644 --- a/test-statically-disable/src/main.rs +++ b/test-statically-disable/src/main.rs @@ -43,6 +43,7 @@ fn main() { let local_collector = LocalCollector::start(); let _ = LocalSpan::enter_with_local_parent("span3"); let local_spans = local_collector.collect(); + assert_eq!(local_spans.to_span_records(SpanContext::random()), vec![]); let span3 = Span::enter_with_parent("span3", &root); let span4 = Span::enter_with_local_parent("span4");