Skip to content

Commit 0ba03b7

Browse files
authored
feat: Add span links to Span V2 (#4737)
The link schema for Span V2 has been finalized. This implements it according to the Notion doc, which means that it's the same as the schema for V1 span links, except for the `attributes` collection containing typed values. Closes RELAY-71. #skip-changelog
1 parent 95f8912 commit 0ba03b7

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

relay-event-schema/src/protocol/span_v2.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, Value};
1+
use relay_protocol::{Annotated, Array, Empty, FromValue, IntoValue, Object, Value};
22

33
use std::fmt;
44

@@ -57,6 +57,10 @@ pub struct SpanV2 {
5757
#[metastructure(required = true)]
5858
pub end_timestamp: Annotated<Timestamp>,
5959

60+
/// Links from this span to other spans.
61+
#[metastructure(pii = "maybe")]
62+
pub links: Annotated<Array<SpanV2Link>>,
63+
6064
/// Arbitrary attributes on a span.
6165
#[metastructure(pii = "true", trim = false)]
6266
pub attributes: Annotated<Object<Attribute>>,
@@ -255,6 +259,31 @@ impl IntoValue for SpanV2Kind {
255259
}
256260
}
257261

262+
/// A link from a span to another span.
263+
#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
264+
#[metastructure(trim = false)]
265+
pub struct SpanV2Link {
266+
/// The trace id of the linked span.
267+
#[metastructure(required = true, trim = false)]
268+
pub trace_id: Annotated<TraceId>,
269+
270+
/// The span id of the linked span.
271+
#[metastructure(required = true, trim = false)]
272+
pub span_id: Annotated<SpanId>,
273+
274+
/// Whether the linked span was positively/negatively sampled.
275+
#[metastructure(trim = false)]
276+
pub sampled: Annotated<bool>,
277+
278+
/// Span link attributes, similar to span attributes/data.
279+
#[metastructure(pii = "maybe", trim = false)]
280+
pub attributes: Annotated<Object<Attribute>>,
281+
282+
/// Additional arbitrary fields for forwards compatibility.
283+
#[metastructure(additional_properties, pii = "maybe", trim = false)]
284+
pub other: Object<Value>,
285+
}
286+
258287
#[cfg(test)]
259288
mod tests {
260289
use chrono::{TimeZone, Utc};
@@ -287,6 +316,19 @@ mod tests {
287316
"kind": "server",
288317
"start_timestamp": 1742921669.25,
289318
"end_timestamp": 1742921669.75,
319+
"links": [
320+
{
321+
"trace_id": "627a2885119dcc8184fae7eef09438cb",
322+
"span_id": "6c71fc6b09b8b716",
323+
"sampled": true,
324+
"attributes": {
325+
"sentry.link.type": {
326+
"type": "string",
327+
"value": "previous_trace"
328+
}
329+
}
330+
}
331+
],
290332
"attributes": {
291333
"custom.error_rate": {
292334
"type": "double",
@@ -348,6 +390,16 @@ mod tests {
348390
"server.address" => "DHWKN7KX6N.local", String,
349391
"http.response.status_code" => 200i64, Integer,
350392
);
393+
394+
let links = vec![Annotated::new(SpanV2Link {
395+
trace_id: Annotated::new("627a2885119dcc8184fae7eef09438cb".parse().unwrap()),
396+
span_id: Annotated::new(SpanId("6c71fc6b09b8b716".into())),
397+
sampled: Annotated::new(true),
398+
attributes: Annotated::new(attrs!(
399+
"sentry.link.type" => "previous_trace", String
400+
)),
401+
..Default::default()
402+
})];
351403
let span = Annotated::new(SpanV2 {
352404
start_timestamp: Annotated::new(
353405
Utc.timestamp_opt(1742921669, 250000000).unwrap().into(),
@@ -360,6 +412,7 @@ mod tests {
360412
status: Annotated::new(SpanV2Status::Ok),
361413
kind: Annotated::new(SpanV2Kind::Server),
362414
is_remote: Annotated::new(true),
415+
links: Annotated::new(links),
363416
attributes: Annotated::new(attributes),
364417
..Default::default()
365418
});

0 commit comments

Comments
 (0)