Skip to content

Commit 0348e93

Browse files
committed
fix: register links on follows_from
1 parent 627aaf4 commit 0348e93

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
@@ -10,12 +10,12 @@ use opentelemetry::{
1010
};
1111
#[cfg(feature = "activate_context")]
1212
use std::cell::RefCell;
13-
use std::fmt;
1413
use std::marker;
1514
use std::thread;
1615
#[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))]
1716
use std::time::Instant;
1817
use std::{any::TypeId, borrow::Cow};
18+
use std::{fmt, vec};
1919
use tracing_core::span::{self, Attributes, Id, Record};
2020
use tracing_core::{field, Event, Subscriber};
2121
#[cfg(feature = "tracing-log")]
@@ -1140,7 +1140,7 @@ where
11401140
fn on_follows_from(&self, id: &Id, follows: &Id, ctx: Context<S>) {
11411141
let span = ctx.span(id).expect("Span not found, this is a bug");
11421142
let mut extensions = span.extensions_mut();
1143-
let _data = extensions
1143+
let data = extensions
11441144
.get_mut::<OtelData>()
11451145
.expect("Missing otel data span extensions");
11461146

@@ -1149,26 +1149,20 @@ where
11491149
// uses the same reasoning as `parent_context` above.
11501150
if let Some(follows_span) = ctx.span(follows) {
11511151
let mut follows_extensions = follows_span.extensions_mut();
1152-
let _follows_data = follows_extensions
1152+
let follows_data = follows_extensions
11531153
.get_mut::<OtelData>()
11541154
.expect("Missing otel data span extensions");
1155-
// TODO:ban There are no tests that check this code :(
1156-
// TODO:ban if the follows span has a span builder the follows span should be _started_ here
1157-
// let follows_link = self.with_started_cx(follows_data, &|cx| {
1158-
// otel::Link::with_context(cx.span().span_context().clone())
1159-
// });
1160-
// let follows_context = self
1161-
// .tracer
1162-
// .sampled_context(follows_data)
1163-
// .span()
1164-
// .span_context()
1165-
// .clone();
1166-
// let follows_link = otel::Link::with_context(follows_context);
1167-
// if let Some(ref mut links) = data.builder.links {
1168-
// links.push(follows_link);
1169-
// } else {
1170-
// data.builder.links = Some(vec![follows_link]);
1171-
// }
1155+
let follows_context =
1156+
self.with_started_cx(follows_data, &|cx| cx.span().span_context().clone());
1157+
if let Some(builder) = data.builder.as_mut() {
1158+
if let Some(ref mut links) = builder.links {
1159+
links.push(otel::Link::with_context(follows_context));
1160+
} else {
1161+
builder.links = Some(vec![otel::Link::with_context(follows_context)]);
1162+
}
1163+
} else {
1164+
data.parent_cx.span().add_link(follows_context, vec![]);
1165+
}
11721166
}
11731167
}
11741168

@@ -2088,7 +2082,115 @@ mod tests {
20882082
assert_eq!(child1.parent_span_id, root.span_context.span_id());
20892083
assert_eq!(child2.parent_span_id, child1.span_context.span_id());
20902084

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

0 commit comments

Comments
 (0)