Skip to content

Commit 02e2506

Browse files
committed
rebase
1 parent 7fb64fe commit 02e2506

File tree

20 files changed

+483
-112
lines changed

20 files changed

+483
-112
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- Fix parsing of data categories/quotas when using an aliased data category name. ([#5435](https://github.com/getsentry/relay/pull/5435))
88

9+
**Features**:
10+
11+
- Add functionality to process and store span attachments. ([#5423](https://github.com/getsentry/relay/pull/5423), [#5363](https://github.com/getsentry/relay/pull/5363))
12+
913
## 25.11.1
1014

1115
**Breaking Changes**:

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ sentry-release-parser = { version = "1.4.0", default-features = false, features
184184
"semver-1",
185185
] }
186186
sentry-types = "0.41.0"
187-
sentry_protos = "0.4.2"
187+
sentry_protos = "0.4.8"
188188
serde = { version = "=1.0.228", features = ["derive", "rc"] }
189189
serde-transcode = "1.1.1"
190190
serde-vars = "0.2.0"

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

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

33
use crate::processor::ProcessValue;
4-
use crate::protocol::{Attributes, Timestamp};
4+
use crate::protocol::{Attributes, Timestamp, TraceId};
55

66
use uuid::Uuid;
77

88
/// Metadata for a span attachment.
99
#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
1010
pub struct AttachmentV2Meta {
11+
/// The ID of the trace that the attachment belongs to.
12+
#[metastructure(required = true, nonempty = true, trim = false)]
13+
pub trace_id: Annotated<TraceId>,
14+
1115
/// Unique identifier for this attachment.
1216
#[metastructure(required = true, nonempty = true, trim = false)]
1317
pub attachment_id: Annotated<Uuid>,

relay-server/src/envelope/item.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,15 @@ pub enum ParentId {
10671067
SpanId(Option<SpanId>),
10681068
}
10691069

1070+
impl ParentId {
1071+
/// Converts the ID to a span ID (if applicable).
1072+
pub fn as_span_id(&self) -> Option<SpanId> {
1073+
match self {
1074+
ParentId::SpanId(span_id) => *span_id,
1075+
}
1076+
}
1077+
}
1078+
10701079
#[cfg(test)]
10711080
mod tests {
10721081
use crate::integrations::OtelFormat;

relay-server/src/managed/counted.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::BTreeMap;
22

3+
use itertools::Either;
34
use relay_event_schema::protocol::{
45
OurLog, SessionAggregateItem, SessionAggregates, SessionUpdate, Span, SpanV2, TraceMetric,
56
};
@@ -40,6 +41,19 @@ impl<T: Counted> Counted for Option<T> {
4041
}
4142
}
4243

44+
impl<L, R> Counted for Either<L, R>
45+
where
46+
L: Counted,
47+
R: Counted,
48+
{
49+
fn quantities(&self) -> Quantities {
50+
match self {
51+
Either::Left(value) => value.quantities(),
52+
Either::Right(value) => value.quantities(),
53+
}
54+
}
55+
}
56+
4357
impl Counted for Item {
4458
fn quantities(&self) -> Quantities {
4559
self.quantities()

relay-server/src/managed/managed.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::sync::Arc;
99
use std::sync::atomic::{AtomicBool, Ordering};
1010

1111
use chrono::{DateTime, Utc};
12+
use itertools::Either;
1213
use relay_event_schema::protocol::EventId;
1314
use relay_quotas::{DataCategory, Scoping};
1415
use relay_system::Addr;
@@ -593,6 +594,17 @@ impl<T: Counted> Managed<Option<T>> {
593594
}
594595
}
595596

597+
impl<L: Counted, R: Counted> Managed<Either<L, R>> {
598+
/// Turns a managed option into an optional [`Managed`].
599+
pub fn transpose(self) -> Either<Managed<L>, Managed<R>> {
600+
let (either, meta) = self.destructure();
601+
match either {
602+
Either::Left(value) => Either::Left(Managed::from_parts(value, meta)),
603+
Either::Right(value) => Either::Right(Managed::from_parts(value, meta)),
604+
}
605+
}
606+
}
607+
596608
impl From<Managed<Box<Envelope>>> for ManagedEnvelope {
597609
fn from(value: Managed<Box<Envelope>>) -> Self {
598610
let (value, meta) = value.destructure();

relay-server/src/processing/forward.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ impl<'a> StoreHandle<'a> {
3636
}
3737

3838
/// Sends a message to the [`Upload`] service.
39-
#[expect(unused)]
4039
pub fn upload<M>(&self, message: M)
4140
where
4241
Upload: FromMessage<M>,

relay-server/src/processing/logs/store.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::collections::HashMap;
22

33
use chrono::{DateTime, Utc};
4-
use prost_types::Timestamp;
54
use relay_event_schema::protocol::{Attributes, OurLog, OurLogLevel, SpanId};
65
use relay_protocol::{Annotated, IntoValue, Value};
76
use relay_quotas::Scoping;
@@ -10,7 +9,7 @@ use uuid::Uuid;
109

1110
use crate::envelope::WithHeader;
1211
use crate::processing::logs::{Error, Result};
13-
use crate::processing::utils::store::{AttributeMeta, extract_meta_attributes};
12+
use crate::processing::utils::store::{AttributeMeta, extract_meta_attributes, proto_timestamp};
1413
use crate::processing::{Counted, Retention};
1514
use crate::services::outcome::DiscardReason;
1615
use crate::services::store::StoreTraceItem;
@@ -66,10 +65,10 @@ pub fn convert(log: WithHeader<OurLog>, ctx: &Context) -> Result<StoreTraceItem>
6665
item_type: TraceItemType::Log.into(),
6766
organization_id: ctx.scoping.organization_id.value(),
6867
project_id: ctx.scoping.project_id.value(),
69-
received: Some(ts(ctx.received_at)),
68+
received: Some(proto_timestamp(ctx.received_at)),
7069
retention_days: ctx.retention.standard.into(),
7170
downsampled_retention_days: ctx.retention.downsampled.into(),
72-
timestamp: Some(ts(timestamp.0)),
71+
timestamp: Some(proto_timestamp(timestamp.0)),
7372
trace_id: required!(log.trace_id).to_string(),
7473
item_id: Uuid::new_v7(timestamp.into()).as_bytes().to_vec(),
7574
attributes: attributes(meta, attrs, fields),
@@ -83,13 +82,6 @@ pub fn convert(log: WithHeader<OurLog>, ctx: &Context) -> Result<StoreTraceItem>
8382
})
8483
}
8584

86-
fn ts(dt: DateTime<Utc>) -> Timestamp {
87-
Timestamp {
88-
seconds: dt.timestamp(),
89-
nanos: i32::try_from(dt.timestamp_subsec_nanos()).unwrap_or(0),
90-
}
91-
}
92-
9385
/// Fields on the log message which are stored as fields.
9486
struct FieldAttributes {
9587
/// The log level.

relay-server/src/processing/spans/mod.rs

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use bytes::Bytes;
44
use either::Either;
55
use relay_event_normalization::GeoIpLookup;
66
use relay_event_schema::processor::ProcessingAction;
7-
use relay_event_schema::protocol::{AttachmentV2Meta, SpanId, SpanV2};
7+
use relay_event_schema::protocol::{AttachmentV2Meta, SpanV2};
88
use relay_pii::PiiConfigError;
99
use relay_protocol::Annotated;
1010
use relay_quotas::{DataCategory, RateLimits};
@@ -242,21 +242,24 @@ impl Forward for SpanOutput {
242242
retention: ctx.retention(|r| r.span.as_ref()),
243243
};
244244

245-
// Explicitly drop standalone attachments before splitting
246-
// They are not stored for now.
247-
// This must be fixed before enabling the feature flag.
248-
let spans = spans.map(|mut inner, record_keeper| {
249-
if !inner.stand_alone_attachments.is_empty() {
250-
let standalone = std::mem::take(&mut inner.stand_alone_attachments);
251-
record_keeper.reject_err(Outcome::Invalid(DiscardReason::Internal), standalone);
245+
let spans_and_attachments = spans.split(|spans| spans.into_parts());
246+
for either in spans_and_attachments {
247+
match either.transpose() {
248+
Either::Left(span) => {
249+
if let Ok(span) = span.try_map(|span, _| store::convert(span, &ctx)) {
250+
s.store(span);
251+
}
252+
}
253+
Either::Right(attachment) => {
254+
if let Ok(attachment) = store::attachment::convert(
255+
attachment,
256+
ctx.retention,
257+
ctx.server_sample_rate,
258+
) {
259+
s.upload(attachment);
260+
}
261+
}
252262
}
253-
inner
254-
});
255-
256-
for span in spans.split(|spans| spans.into_indexed_spans()) {
257-
if let Ok(span) = span.try_map(|span, _| store::convert(span, &ctx)) {
258-
s.store(span)
259-
};
260263
}
261264

262265
Ok(())
@@ -359,8 +362,7 @@ impl<C> ExpandedSpans<C> {
359362

360363
for ExpandedSpan { span, attachments } in self.spans {
361364
for attachment in attachments {
362-
let span_id = span.value().and_then(|s| s.span_id.value().copied());
363-
items.push(attachment_to_item(attachment, span_id)?);
365+
items.push(attachment_to_item(attachment)?);
364366
}
365367

366368
spans_without_attachments.push(span);
@@ -373,7 +375,7 @@ impl<C> ExpandedSpans<C> {
373375
}
374376

375377
for attachment in self.stand_alone_attachments {
376-
items.push(attachment_to_item(attachment, None)?);
378+
items.push(attachment_to_item(attachment)?);
377379
}
378380

379381
Ok(Envelope::from_parts(self.headers, Items::from_vec(items)))
@@ -403,11 +405,12 @@ impl<C> ExpandedSpans<C> {
403405
}
404406
}
405407

406-
fn attachment_to_item(
407-
attachment: ExpandedAttachment,
408-
span_id: Option<SpanId>,
409-
) -> Result<Item, ContainerWriteError> {
410-
let ExpandedAttachment { meta, body } = attachment;
408+
fn attachment_to_item(attachment: ExpandedAttachment) -> Result<Item, ContainerWriteError> {
409+
let ExpandedAttachment {
410+
parent_id,
411+
meta,
412+
body,
413+
} = attachment;
411414

412415
let meta_json = meta.to_json()?;
413416
let meta_bytes = meta_json.into_bytes();
@@ -420,7 +423,7 @@ fn attachment_to_item(
420423
let mut item = Item::new(ItemType::Attachment);
421424
item.set_payload(ContentType::AttachmentV2, payload.freeze());
422425
item.set_meta_length(meta_length as u32);
423-
item.set_parent_id(ParentId::SpanId(span_id));
426+
item.set_parent_id(parent_id);
424427

425428
Ok(item)
426429
}
@@ -450,8 +453,22 @@ impl ExpandedSpans<TotalAndIndexed> {
450453

451454
impl ExpandedSpans<Indexed> {
452455
#[cfg(feature = "processing")]
453-
fn into_indexed_spans(self) -> impl Iterator<Item = IndexedSpan> {
454-
self.spans.into_iter().map(IndexedSpan)
456+
fn into_parts(self) -> impl Iterator<Item = Either<IndexedSpanOnly, ExpandedAttachment>> {
457+
let Self {
458+
headers: _,
459+
server_sample_rate: _,
460+
spans,
461+
stand_alone_attachments,
462+
category: _,
463+
} = self;
464+
spans
465+
.into_iter()
466+
.flat_map(|span| {
467+
let ExpandedSpan { span, attachments } = span;
468+
std::iter::once(Either::Left(IndexedSpanOnly(span)))
469+
.chain(attachments.into_iter().map(Either::Right))
470+
})
471+
.chain(stand_alone_attachments.into_iter().map(Either::Right))
455472
}
456473
}
457474

@@ -610,23 +627,23 @@ impl Managed<ExpandedSpans<TotalAndIndexed>> {
610627
}
611628
}
612629

613-
/// A Span which only represents the indexed category.
614630
#[cfg(feature = "processing")]
615631
#[derive(Debug)]
616-
struct IndexedSpan(ExpandedSpan);
632+
struct IndexedSpanOnly(WithHeader<SpanV2>);
617633

618634
#[cfg(feature = "processing")]
619-
impl Counted for IndexedSpan {
635+
impl Counted for IndexedSpanOnly {
620636
fn quantities(&self) -> Quantities {
621-
let mut quantities = smallvec::smallvec![(DataCategory::SpanIndexed, 1)];
622-
quantities.extend(self.0.attachments.quantities());
623-
quantities
637+
smallvec::smallvec![(DataCategory::SpanIndexed, 1)]
624638
}
625639
}
626640

627641
/// A validated and parsed span attachment.
628642
#[derive(Debug)]
629643
pub struct ExpandedAttachment {
644+
/// The ID of the log / span / metric that owns the span.
645+
pub parent_id: ParentId,
646+
630647
/// The parsed metadata from the attachment.
631648
pub meta: Annotated<AttachmentV2Meta>,
632649

0 commit comments

Comments
 (0)