@@ -4,7 +4,9 @@ use relay_event_schema::protocol::SpanV2;
44use relay_quotas:: { DataCategory , RateLimits } ;
55
66use crate :: Envelope ;
7- use crate :: envelope:: { ContainerItems , EnvelopeHeaders , Item , ItemType } ;
7+ use crate :: envelope:: {
8+ ContainerItems , ContainerWriteError , EnvelopeHeaders , Item , ItemContainer , ItemType , Items ,
9+ } ;
810use crate :: managed:: {
911 Counted , Managed , ManagedEnvelope , ManagedResult , OutcomeError , Quantities , Rejected ,
1012} ;
@@ -72,14 +74,14 @@ impl processing::Processor for SpansProcessor {
7274 & self ,
7375 envelope : & mut ManagedEnvelope ,
7476 ) -> Option < Managed < Self :: UnitOfWork > > {
75- let _headers = envelope. envelope ( ) . headers ( ) . clone ( ) ;
77+ let headers = envelope. envelope ( ) . headers ( ) . clone ( ) ;
7678
7779 let spans = envelope
7880 . envelope_mut ( )
7981 . take_items_by ( |item| matches ! ( * item. ty( ) , ItemType :: Span ) )
8082 . into_vec ( ) ;
8183
82- let work = SerializedSpans { _headers , spans } ;
84+ let work = SerializedSpans { headers , spans } ;
8385 Some ( Managed :: from_envelope ( envelope, work) )
8486 }
8587
@@ -127,39 +129,74 @@ pub enum SpanOutput {
127129
128130impl Forward for SpanOutput {
129131 fn serialize_envelope ( self ) -> Result < Managed < Box < Envelope > > , Rejected < ( ) > > {
130- debug_assert ! ( false , "Not Implemented Yet" ) ;
131- Err ( match self {
132- Self :: NotProcessed ( spans) => {
133- spans. reject_err ( ( Outcome :: Invalid ( DiscardReason :: Internal ) , ( ) ) )
134- }
135- Self :: Processed ( spans) => {
136- spans. reject_err ( ( Outcome :: Invalid ( DiscardReason :: Internal ) , ( ) ) )
137- }
138- } )
132+ let spans = match self {
133+ Self :: NotProcessed ( spans) => spans,
134+ Self :: Processed ( spans) => spans. try_map ( |spans, _| {
135+ spans
136+ . serialize ( )
137+ . map_err ( drop)
138+ . with_outcome ( Outcome :: Invalid ( DiscardReason :: Internal ) )
139+ } ) ?,
140+ } ;
141+
142+ Ok ( spans. map ( |spans, _| spans. serialize_envelope ( ) ) )
139143 }
140144
141145 #[ cfg( feature = "processing" ) ]
142146 fn forward_store (
143147 self ,
144- _s : & relay_system:: Addr < crate :: services:: store:: Store > ,
148+ s : & relay_system:: Addr < crate :: services:: store:: Store > ,
145149 ) -> Result < ( ) , Rejected < ( ) > > {
146- debug_assert ! ( false , "Not Implemented Yet" ) ;
147- Err ( match self {
148- Self :: NotProcessed ( spans) => {
149- spans. reject_err ( ( Outcome :: Invalid ( DiscardReason :: Internal ) , ( ) ) )
150+ use crate :: envelope:: ContentType ;
151+ use crate :: services:: store:: StoreEnvelope ;
152+
153+ let spans = match self {
154+ SpanOutput :: NotProcessed ( spans) => {
155+ return Err ( spans. internal_error (
156+ "spans must be processed before they can be forwarded to the store" ,
157+ ) ) ;
150158 }
151- Self :: Processed ( spans) => {
152- spans. reject_err ( ( Outcome :: Invalid ( DiscardReason :: Internal ) , ( ) ) )
159+ SpanOutput :: Processed ( spans) => spans,
160+ } ;
161+
162+ // Converts all SpanV2 spans into their SpanV1 counterparts and packages them into an
163+ // envelope to forward them.
164+ //
165+ // This is temporary until we have proper mapping code from SpanV2 -> SpanKafka,
166+ // similar to what we do for logs.
167+ let envelope = spans. map ( |spans, records| {
168+ let mut items = Items :: with_capacity ( spans. spans . len ( ) ) ;
169+ for span in spans. spans {
170+ let span = span. value . map_value ( relay_spans:: span_v2_to_span_v1) ;
171+
172+ let mut item = Item :: new ( ItemType :: Span ) ;
173+ let payload = match span. to_json ( ) {
174+ Ok ( payload) => payload,
175+ Err ( error) => {
176+ records. internal_error ( error, span) ;
177+ continue ;
178+ }
179+ } ;
180+ item. set_payload ( ContentType :: Json , payload) ;
181+ items. push ( item) ;
153182 }
154- } )
183+
184+ Envelope :: from_parts ( spans. headers , items)
185+ } ) ;
186+
187+ s. send ( StoreEnvelope {
188+ envelope : ManagedEnvelope :: from ( envelope) . into_processed ( ) ,
189+ } ) ;
190+
191+ Ok ( ( ) )
155192 }
156193}
157194
158195/// Spans in their serialized state, as transported in an envelope.
159196#[ derive( Debug ) ]
160197pub struct SerializedSpans {
161198 /// Original envelope headers.
162- _headers : EnvelopeHeaders ,
199+ headers : EnvelopeHeaders ,
163200
164201 /// A list of spans waiting to be processed.
165202 ///
@@ -176,6 +213,10 @@ impl SerializedSpans {
176213 let c: u32 = self . spans . iter ( ) . filter_map ( |item| item. item_count ( ) ) . sum ( ) ;
177214 c as usize
178215 }
216+
217+ fn serialize_envelope ( self ) -> Box < Envelope > {
218+ Envelope :: from_parts ( self . headers , Items :: from_vec ( self . spans ) )
219+ }
179220}
180221
181222impl Counted for SerializedSpans {
@@ -196,12 +237,31 @@ impl CountRateLimited for Managed<SerializedSpans> {
196237#[ derive( Debug ) ]
197238pub struct ExpandedSpans {
198239 /// Original envelope headers.
199- _headers : EnvelopeHeaders ,
240+ headers : EnvelopeHeaders ,
200241
201242 /// Expanded and parsed spans.
202243 spans : ContainerItems < SpanV2 > ,
203244}
204245
246+ impl ExpandedSpans {
247+ fn serialize ( self ) -> Result < SerializedSpans , ContainerWriteError > {
248+ let mut spans = Vec :: new ( ) ;
249+
250+ if !self . spans . is_empty ( ) {
251+ let mut item = Item :: new ( ItemType :: Span ) ;
252+ ItemContainer :: from ( self . spans )
253+ . write_to ( & mut item)
254+ . inspect_err ( |err| relay_log:: error!( "failed to serialize spans: {err}" ) ) ?;
255+ spans. push ( item) ;
256+ }
257+
258+ Ok ( SerializedSpans {
259+ headers : self . headers ,
260+ spans,
261+ } )
262+ }
263+ }
264+
205265impl Counted for ExpandedSpans {
206266 fn quantities ( & self ) -> Quantities {
207267 let quantity = self . spans . len ( ) ;
0 commit comments