Skip to content

Commit d73ab01

Browse files
committed
fix: register links on follows_from
1 parent 4dd7744 commit d73ab01

File tree

1 file changed

+123
-21
lines changed

1 file changed

+123
-21
lines changed

src/layer.rs

Lines changed: 123 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ use opentelemetry::{
99
};
1010
#[cfg(feature = "activate_context")]
1111
use std::cell::RefCell;
12-
use std::fmt;
1312
use std::marker;
1413
use std::thread;
1514
#[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))]
1615
use std::time::Instant;
1716
use std::{any::TypeId, borrow::Cow};
17+
use std::{fmt, vec};
1818
use tracing_core::span::{self, Attributes, Id, Record};
1919
use tracing_core::{field, Event, Subscriber};
2020
#[cfg(feature = "tracing-log")]
@@ -1145,7 +1145,7 @@ where
11451145
fn on_follows_from(&self, id: &Id, follows: &Id, ctx: Context<S>) {
11461146
let span = ctx.span(id).expect("Span not found, this is a bug");
11471147
let mut extensions = span.extensions_mut();
1148-
let _data = extensions
1148+
let data = extensions
11491149
.get_mut::<OtelData>()
11501150
.expect("Missing otel data span extensions");
11511151

@@ -1154,26 +1154,20 @@ where
11541154
// uses the same reasoning as `parent_context` above.
11551155
if let Some(follows_span) = ctx.span(follows) {
11561156
let mut follows_extensions = follows_span.extensions_mut();
1157-
let _follows_data = follows_extensions
1157+
let follows_data = follows_extensions
11581158
.get_mut::<OtelData>()
11591159
.expect("Missing otel data span extensions");
1160-
// TODO:ban There are no tests that check this code :(
1161-
// TODO:ban if the follows span has a span builder the follows span should be _started_ here
1162-
// let follows_link = self.with_started_cx(follows_data, &|cx| {
1163-
// otel::Link::with_context(cx.span().span_context().clone())
1164-
// });
1165-
// let follows_context = self
1166-
// .tracer
1167-
// .sampled_context(follows_data)
1168-
// .span()
1169-
// .span_context()
1170-
// .clone();
1171-
// let follows_link = otel::Link::with_context(follows_context);
1172-
// if let Some(ref mut links) = data.builder.links {
1173-
// links.push(follows_link);
1174-
// } else {
1175-
// data.builder.links = Some(vec![follows_link]);
1176-
// }
1160+
let follows_context =
1161+
self.with_started_cx(follows_data, &|cx| cx.span().span_context().clone());
1162+
if let Some(builder) = data.builder.as_mut() {
1163+
if let Some(ref mut links) = builder.links {
1164+
links.push(otel::Link::with_context(follows_context));
1165+
} else {
1166+
builder.links = Some(vec![otel::Link::with_context(follows_context)]);
1167+
}
1168+
} else {
1169+
data.parent_cx.span().add_link(follows_context, vec![]);
1170+
}
11771171
}
11781172
}
11791173

@@ -2095,7 +2089,115 @@ mod tests {
20952089
assert_eq!(child1.parent_span_id, root.span_context.span_id());
20962090
assert_eq!(child2.parent_span_id, child1.span_context.span_id());
20972091

2098-
// This is surprising, the parent should be `child1`, but is 'root'.
2092+
// The parent should be `child1`
20992093
assert_eq!(child3.parent_span_id, child1.span_context.span_id());
21002094
}
2095+
2096+
#[test]
2097+
fn follows_from_adds_link() {
2098+
use crate::OpenTelemetrySpanExt;
2099+
let mut tracer = TestTracer::default();
2100+
let subscriber = tracing_subscriber::registry().with(layer().with_tracer(tracer.clone()));
2101+
2102+
let span1_id = tracing::subscriber::with_default(subscriber, || {
2103+
let span2 = tracing::debug_span!("span2");
2104+
let span1 = tracing::debug_span!("span1");
2105+
2106+
// Ensure that span2 is started
2107+
let _ = span2.context();
2108+
2109+
// Establish follows_from relationship
2110+
span2.follows_from(&span1);
2111+
2112+
// Enter span2 to ensure it's exported
2113+
let _guard = span2.enter();
2114+
2115+
// Get span ID for later verification
2116+
span1.context().span().span_context().span_id()
2117+
});
2118+
2119+
let spans = tracer.spans();
2120+
// Check that both spans are exported
2121+
assert_eq!(spans.len(), 2, "Expected two spans to be exported");
2122+
assert!(spans.iter().any(|span| span.name == "span1"));
2123+
let span2 = spans
2124+
.iter()
2125+
.find(|span| span.name == "span2")
2126+
.expect("Expected span2 to be exported");
2127+
2128+
// Collect span2 links
2129+
let links = span2
2130+
.links
2131+
.iter()
2132+
.map(|link| link.span_context.span_id())
2133+
.collect::<Vec<_>>();
2134+
2135+
// Verify that span2 has a link to span1
2136+
assert_eq!(
2137+
links.len(),
2138+
1,
2139+
"Expected span to have one link from follows_from relationship"
2140+
);
2141+
2142+
assert!(
2143+
links.contains(&span1_id),
2144+
"Link should point to the correct source span"
2145+
);
2146+
}
2147+
2148+
#[test]
2149+
fn follows_from_multiple_links() {
2150+
use crate::OpenTelemetrySpanExt;
2151+
let mut tracer = TestTracer::default();
2152+
let subscriber = tracing_subscriber::registry().with(layer().with_tracer(tracer.clone()));
2153+
2154+
let (span1_id, span2_id) = tracing::subscriber::with_default(subscriber, || {
2155+
let span3 = tracing::debug_span!("span3");
2156+
let span2 = tracing::debug_span!("span2");
2157+
let span1 = tracing::debug_span!("span1");
2158+
2159+
// Establish multiple follows_from relationships
2160+
span3.follows_from(&span1);
2161+
span3.follows_from(&span2);
2162+
2163+
// Enter span3 to ensure it's exported
2164+
let _guard = span3.enter();
2165+
2166+
// Get span IDs for later verification
2167+
(
2168+
span1.context().span().span_context().span_id(),
2169+
span2.context().span().span_context().span_id(),
2170+
)
2171+
});
2172+
2173+
let spans = tracer.spans();
2174+
// Check that all three spans are exported
2175+
assert_eq!(spans.len(), 3, "Expected three spans to be exported");
2176+
assert!(spans.iter().any(|span| span.name == "span1"));
2177+
assert!(spans.iter().any(|span| span.name == "span2"));
2178+
let span3 = spans
2179+
.iter()
2180+
.find(|span| span.name == "span3")
2181+
.expect("Expected span3 to be exported");
2182+
2183+
// Collect span3 links
2184+
let links = span3
2185+
.links
2186+
.iter()
2187+
.map(|link| link.span_context.span_id())
2188+
.collect::<Vec<_>>();
2189+
2190+
// Verify that span3 has multiple links and they point to the correct spans
2191+
assert_eq!(
2192+
links.len(),
2193+
2,
2194+
"Expected span to have two links from follows_from relationships"
2195+
);
2196+
2197+
// Verify that the links point to the correct spans in the correct order
2198+
assert!(
2199+
links[0] == span1_id && links[1] == span2_id,
2200+
"Links should point to the correct source spans"
2201+
);
2202+
}
21012203
}

0 commit comments

Comments
 (0)