@@ -6,7 +6,7 @@ use std::ops::AddAssign;
66use uuid:: Uuid ;
77
88use bytes:: Bytes ;
9- use relay_event_schema:: protocol:: EventType ;
9+ use relay_event_schema:: protocol:: { EventType , SpanId } ;
1010use relay_protocol:: Value ;
1111use relay_quotas:: DataCategory ;
1212use serde:: { Deserialize , Serialize } ;
@@ -45,6 +45,8 @@ impl Item {
4545 fully_normalized : false ,
4646 profile_type : None ,
4747 platform : None ,
48+ parent_id : None ,
49+ meta_length : None ,
4850 } ,
4951 payload : Bytes :: new ( ) ,
5052 }
@@ -129,7 +131,7 @@ impl Item {
129131 ItemType :: Nel => smallvec ! [ ] ,
130132 ItemType :: UnrealReport => smallvec ! [ ( DataCategory :: Error , item_count) ] ,
131133 ItemType :: Attachment => smallvec ! [
132- ( DataCategory :: Attachment , self . len ( ) . max ( 1 ) ) ,
134+ ( DataCategory :: Attachment , self . attachment_body_size ( ) ) ,
133135 ( DataCategory :: AttachmentItem , item_count) ,
134136 ] ,
135137 ItemType :: Session | ItemType :: Sessions => {
@@ -434,6 +436,53 @@ impl Item {
434436 self . headers . sampled = sampled;
435437 }
436438
439+ /// Returns the length of the item.
440+ pub fn meta_length ( & self ) -> Option < u32 > {
441+ self . headers . meta_length
442+ }
443+
444+ /// Sets the length of the optional meta segment.
445+ ///
446+ /// Only applicable if the item is an attachment.
447+ pub fn set_meta_length ( & mut self , meta_length : u32 ) {
448+ self . headers . meta_length = Some ( meta_length) ;
449+ }
450+
451+ /// Returns the parent entity that this item is associated with, if any.
452+ ///
453+ /// Only applicable if the item is an attachment.
454+ pub fn parent_id ( & self ) -> Option < & ParentId > {
455+ self . headers . parent_id . as_ref ( )
456+ }
457+
458+ /// Sets the parent entity that this item is associated with.
459+ pub fn set_parent_id ( & mut self , parent_id : ParentId ) {
460+ self . headers . parent_id = Some ( parent_id) ;
461+ }
462+
463+ /// Returns `true` if this item is an attachment with AttachmentV2 content type.
464+ pub fn is_attachment_v2 ( & self ) -> bool {
465+ self . ty ( ) == & ItemType :: Attachment
466+ && self . content_type ( ) == Some ( & ContentType :: AttachmentV2 )
467+ }
468+
469+ /// Returns the attachment payload size.
470+ ///
471+ /// For AttachmentV2, returns only the size of the actual payload, excluding the attachment meta.
472+ /// For Attachment, returns the size of entire payload.
473+ ///
474+ /// **Note:** This relies on the `meta_length` header which might not be correct as such this
475+ /// is best effort.
476+ pub fn attachment_body_size ( & self ) -> usize {
477+ if self . is_attachment_v2 ( ) {
478+ self . len ( )
479+ . saturating_sub ( self . meta_length ( ) . unwrap_or ( 0 ) as usize )
480+ } else {
481+ self . len ( )
482+ }
483+ . max ( 1 )
484+ }
485+
437486 /// Returns the specified header value, if present.
438487 pub fn get_header < K > ( & self , name : & K ) -> Option < & Value >
439488 where
@@ -947,6 +996,18 @@ pub struct ItemHeaders {
947996 #[ serde( default , skip) ]
948997 profile_type : Option < ProfileType > ,
949998
999+ /// Content length of an optional meta segment that might be contained in the item.
1000+ ///
1001+ /// For the time being such an meta segment is only present for span attachments.
1002+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
1003+ meta_length : Option < u32 > ,
1004+
1005+ /// Parent entity that this item is associated with, if any.
1006+ ///
1007+ /// For the time being only applicable if the item is a span-attachment.
1008+ #[ serde( flatten, skip_serializing_if = "Option::is_none" ) ]
1009+ parent_id : Option < ParentId > ,
1010+
9501011 /// Other attributes for forward compatibility.
9511012 #[ serde( flatten) ]
9521013 other : BTreeMap < String , Value > ,
@@ -994,6 +1055,18 @@ fn is_true(value: &bool) -> bool {
9941055 * value
9951056}
9961057
1058+ /// Parent identifier for an attachment-v2.
1059+ ///
1060+ /// Attachments can be associated with different types of parent entities (only spans for now).
1061+ ///
1062+ /// SpanId(None) indicates that the item is a span-attachment that is associated with no specific
1063+ /// span.
1064+ #[ derive( Clone , Debug , Deserialize , Serialize ) ]
1065+ #[ serde( rename_all = "snake_case" ) ]
1066+ pub enum ParentId {
1067+ SpanId ( Option < SpanId > ) ,
1068+ }
1069+
9971070#[ cfg( test) ]
9981071mod tests {
9991072 use crate :: integrations:: OtelFormat ;
0 commit comments