Skip to content

Commit 133ab73

Browse files
committed
fix: add span links to SpanRef when builder has been consumed
1 parent 94137c5 commit 133ab73

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

src/span_ext.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,10 @@ impl OpenTelemetrySpanExt for tracing::Span {
239239
// NOTE - if the span has been created - if we have _already_
240240
// consumed our SpanBuilder_ - we can no longer mutate our parent!
241241
// This is an intentional design decision.
242-
if let Some(builder) = &mut data.builder {
243-
// If we still have a builder, update it to use the new parent context
244-
// when it's eventually built
242+
if data.builder.is_some() {
243+
// If we still have a builder, update the data so it uses the
244+
// new parent context when it's eventually built
245245
data.parent_cx = new_cx;
246-
builder.sampling_result = None;
247246
}
248247
});
249248
});
@@ -257,7 +256,6 @@ impl OpenTelemetrySpanExt for tracing::Span {
257256
if cx.is_valid() {
258257
let mut cx = Some(cx);
259258
let mut att = Some(attributes);
260-
// TODO:ban add add version for SpanRef
261259
self.with_subscriber(move |(id, subscriber)| {
262260
let Some(get_context) = subscriber.downcast_ref::<WithContext>() else {
263261
return;
@@ -273,6 +271,9 @@ impl OpenTelemetrySpanExt for tracing::Span {
273271
.links
274272
.get_or_insert_with(|| Vec::with_capacity(1))
275273
.push(follows_link);
274+
} else {
275+
let span = data.parent_cx.span();
276+
span.add_link(follows_link.span_context, follows_link.attributes);
276277
}
277278
});
278279
});

tests/span_ext.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,69 @@ fn test_add_event_with_timestamp() {
165165
event_data.timestamp
166166
);
167167
}
168+
169+
#[test]
170+
fn test_add_link_variants() {
171+
let (_tracer, provider, exporter, subscriber) = test_tracer();
172+
173+
let link_builder_cx = opentelemetry::trace::SpanContext::new(
174+
opentelemetry::trace::TraceId::from_u128(0x1234567890abcdef1234567890abcdef),
175+
opentelemetry::trace::SpanId::from_u64(0x1234567890abcdef),
176+
opentelemetry::trace::TraceFlags::default(),
177+
true, // Is remote
178+
opentelemetry::trace::TraceState::default(),
179+
);
180+
let link_current_cx = opentelemetry::trace::SpanContext::new(
181+
opentelemetry::trace::TraceId::from_u128(0xabcdef1234567890abcdef1234567890),
182+
opentelemetry::trace::SpanId::from_u64(0xabcdef1234567890),
183+
opentelemetry::trace::TraceFlags::default(),
184+
true, // Is remote
185+
opentelemetry::trace::TraceState::default(),
186+
);
187+
let link_attrs = vec![
188+
opentelemetry::KeyValue::new("link_key_1", "link_value_1"),
189+
opentelemetry::KeyValue::new("link_key_2", 123),
190+
];
191+
192+
tracing::subscriber::with_default(subscriber, || {
193+
let root = tracing::debug_span!("root");
194+
// Add the link using the extension method that now targets the builder
195+
root.add_link(link_builder_cx.clone());
196+
// Enter span to make it current for the link addition
197+
let _enter = root.enter();
198+
// Add the link using the extension method that now targets the span in the context
199+
root.add_link_with_attributes(link_current_cx.clone(), link_attrs.clone());
200+
});
201+
202+
drop(provider); // flush all spans
203+
let spans = exporter.0.lock().unwrap();
204+
205+
assert_eq!(spans.len(), 1, "Should have exported exactly one span.");
206+
let root_span_data = spans.first().unwrap();
207+
208+
assert_eq!(root_span_data.links.len(), 2, "Span should have two links.");
209+
let mut links = root_span_data.links.iter().collect::<Vec<_>>();
210+
links.sort_by(|a, b| {
211+
a.span_context
212+
.trace_id()
213+
.to_string()
214+
.cmp(&b.span_context.trace_id().to_string())
215+
});
216+
let link1 = &links[0];
217+
let link2 = &links[1];
218+
219+
assert_eq!(
220+
link1.span_context, link_builder_cx,
221+
"Link 1 context mismatch."
222+
);
223+
assert_eq!(
224+
link1.attributes,
225+
vec![],
226+
"Link 1 attributes should be empty."
227+
);
228+
assert_eq!(
229+
link2.span_context, link_current_cx,
230+
"Link 2 context mismatch."
231+
);
232+
assert_eq!(link2.attributes, link_attrs, "Link 2 attributes mismatch.");
233+
}

0 commit comments

Comments
 (0)