@@ -18,15 +18,14 @@ use self::init::TracingHarness;
1818use self :: internal:: { create_span, current_span, span_trace_id, SharedSpan } ;
1919use super :: scope:: Scope ;
2020use super :: TelemetryContext ;
21- use cf_rustracing_jaeger:: Span ;
2221use std:: borrow:: Cow ;
2322use std:: sync:: Arc ;
2423
2524#[ cfg( any( test, feature = "testing" ) ) ]
2625pub use self :: testing:: { TestSpan , TestTrace , TestTraceIterator , TestTraceOptions } ;
2726
2827pub use cf_rustracing:: tag:: TagValue ;
29- pub use cf_rustracing_jaeger:: span:: { SpanContextState as SerializableTraceState , TraceId } ;
28+ pub use cf_rustracing_jaeger:: span:: { Span , SpanContextState as SerializableTraceState , TraceId } ;
3029
3130/// Returns active traces as a JSON dump.
3231///
@@ -650,6 +649,75 @@ macro_rules! __set_span_finish_time {
650649 } ;
651650}
652651
652+ /// Sets a new finish callback for the current span. It executes when the span is dropped.
653+ ///
654+ /// Each span can only have one callback at a time. Children of a span inherit the
655+ /// callback that is set at the time each child is created. To remove a callback, use
656+ /// `set_span_finish_callback!(None)`.
657+ ///
658+ /// The callback has signature `Fn(&mut Span)` and can access all functions available on
659+ /// [`Span`].
660+ ///
661+ /// # Examples
662+ /// ```
663+ /// use foundations::telemetry::TelemetryContext;
664+ /// use foundations::telemetry::tracing::{self, Span, test_trace, TestTraceOptions};
665+ ///
666+ /// // Test context is used for demonstration purposes to show the resulting traces.
667+ /// let ctx = TelemetryContext::test();
668+ ///
669+ /// {
670+ /// let _scope = ctx.scope();
671+ /// let _root = tracing::span("root");
672+ ///
673+ /// tracing::set_span_finish_callback!(|span: &mut Span| {
674+ /// use cf_rustracing::tag::Tag;
675+ /// span.set_tag(|| Tag::new("user-id", 92395));
676+ /// });
677+ ///
678+ /// let child_with_cb = tracing::span("child_with_cb");
679+ /// drop(child_with_cb);
680+ ///
681+ /// // Remove the callback from a newly-created child
682+ /// let _child_without_cb = tracing::span("child_without_cb");
683+ /// tracing::set_span_finish_callback!(None);
684+ /// }
685+ ///
686+ /// let traces = ctx.traces(TestTraceOptions {
687+ /// include_tags: true,
688+ /// ..Default::default()
689+ /// });
690+ ///
691+ /// assert_eq!(
692+ /// traces,
693+ /// vec![test_trace! {
694+ /// "root"; {
695+ /// tags: [ ("user-id", 92395) ]
696+ /// } => {
697+ /// "child_with_cb"; {
698+ /// tags: [ ("user-id", 92395) ]
699+ /// },
700+ /// "child_without_cb"
701+ /// }
702+ /// }]
703+ /// );
704+ /// ```
705+ #[ macro_export]
706+ #[ doc( hidden) ]
707+ macro_rules! __set_span_finish_callback {
708+ ( None ) => {
709+ $crate:: telemetry:: tracing:: internal:: write_current_span( |span| {
710+ span. take_finish_callback( ) ;
711+ } )
712+ } ;
713+ ( $cb: expr ) => { {
714+ let cb = $cb;
715+ $crate:: telemetry:: tracing:: internal:: write_current_span( move |span| {
716+ span. set_finish_callback( cb) ;
717+ } )
718+ } } ;
719+ }
720+
653721/// A convenience macro to construct [`TestTrace`] for test assertions.
654722///
655723/// Note that for span timings the macro always generates default
@@ -835,6 +903,7 @@ macro_rules! __test_trace {
835903#[ doc( inline) ]
836904pub use {
837905 __add_span_log_fields as add_span_log_fields, __add_span_tags as add_span_tags,
906+ __set_span_finish_callback as set_span_finish_callback,
838907 __set_span_finish_time as set_span_finish_time, __set_span_start_time as set_span_start_time,
839908} ;
840909
0 commit comments