@@ -25,7 +25,10 @@ use opentelemetry_proto::tonic::trace::v1::TracesData;
2525use serde_json:: { Map , Value } ;
2626
2727use super :: otel_utils:: convert_epoch_nano_to_timestamp;
28+ use super :: otel_utils:: fetch_attributes_from_json;
29+ use super :: otel_utils:: fetch_attributes_string;
2830use super :: otel_utils:: insert_attributes;
31+ use super :: otel_utils:: merge_attributes_in_json;
2932
3033pub const OTEL_TRACES_KNOWN_FIELD_LIST : [ & str ; 15 ] = [
3134 "span_trace_id" ,
@@ -46,15 +49,12 @@ pub const OTEL_TRACES_KNOWN_FIELD_LIST: [&str; 15] = [
4649] ;
4750/// this function flattens the `ScopeSpans` object
4851/// and returns a `Vec` of `Map` of the flattened json
49- fn flatten_scope_span (
50- scope_span : & ScopeSpans ,
51- other_attributes : & mut Map < String , Value > ,
52- ) -> Vec < Map < String , Value > > {
52+ fn flatten_scope_span ( scope_span : & ScopeSpans ) -> Vec < Map < String , Value > > {
5353 let mut vec_scope_span_json = Vec :: new ( ) ;
5454 let mut scope_span_json = Map :: new ( ) ;
55-
55+ let mut other_attributes = Map :: new ( ) ;
5656 for span in & scope_span. spans {
57- let span_record_json = flatten_span_record ( span, other_attributes ) ;
57+ let span_record_json = flatten_span_record ( span) ;
5858 vec_scope_span_json. extend ( span_record_json) ;
5959 }
6060
@@ -64,7 +64,11 @@ fn flatten_scope_span(
6464 "scope_version" . to_string ( ) ,
6565 Value :: String ( scope. version . clone ( ) ) ,
6666 ) ;
67- insert_attributes ( & mut scope_span_json, & scope. attributes , other_attributes) ;
67+ insert_attributes (
68+ & mut scope_span_json,
69+ & scope. attributes ,
70+ & mut other_attributes,
71+ ) ;
6872 scope_span_json. insert (
6973 "scope_dropped_attributes_count" . to_string ( ) ,
7074 Value :: Number ( scope. dropped_attributes_count . into ( ) ) ,
@@ -83,6 +87,8 @@ fn flatten_scope_span(
8387 Value :: String ( scope_span. schema_url . clone ( ) ) ,
8488 ) ;
8589 }
90+ // Add the `other_attributes` to the scope span json
91+ merge_attributes_in_json ( other_attributes. clone ( ) , & mut vec_scope_span_json) ;
8692
8793 vec_scope_span_json
8894}
@@ -109,7 +115,7 @@ pub fn flatten_otel_traces(message: &TracesData) -> Vec<Value> {
109115
110116 let mut vec_resource_spans_json = Vec :: new ( ) ;
111117 for scope_span in & record. scope_spans {
112- let scope_span_json = flatten_scope_span ( scope_span, & mut other_attributes ) ;
118+ let scope_span_json = flatten_scope_span ( scope_span) ;
113119 vec_resource_spans_json. extend ( scope_span_json) ;
114120 }
115121
@@ -123,49 +129,43 @@ pub fn flatten_otel_traces(message: &TracesData) -> Vec<Value> {
123129 resource_spans_json. insert ( key. clone ( ) , value. clone ( ) ) ;
124130 }
125131 }
126-
132+ // Add the `other_attributes` to the resource span json
133+ merge_attributes_in_json ( other_attributes. clone ( ) , & mut vec_resource_spans_json) ;
127134 vec_otel_json. extend ( vec_resource_spans_json) ;
128135 }
129- // Add common attributes as one attribute in stringified array to each span record
130- let other_attributes = match serde_json:: to_string ( & other_attributes) {
131- Ok ( s) => s,
132- Err ( e) => {
133- tracing:: warn!( "failed to serialise OTEL other_attributes: {e}" ) ;
134- String :: default ( )
135- }
136- } ;
137- for span_record_json in & mut vec_otel_json {
138- span_record_json. insert (
139- "other_attributes" . to_string ( ) ,
140- Value :: String ( other_attributes. clone ( ) ) ,
141- ) ;
142- }
136+
143137 vec_otel_json. into_iter ( ) . map ( Value :: Object ) . collect ( )
144138}
145139
146140/// otel traces has json array of events
147141/// this function flattens the `Event` object
148142/// and returns a `Vec` of `Map` of the flattened json
149- fn flatten_events (
150- events : & [ Event ] ,
151- other_attributes : & mut Map < String , Value > ,
152- ) -> Vec < Map < String , Value > > {
143+ fn flatten_events ( events : & [ Event ] ) -> Vec < Map < String , Value > > {
153144 events
154145 . iter ( )
155146 . map ( |event| {
156147 let mut event_json = Map :: new ( ) ;
148+ let mut other_attributes = Map :: new ( ) ;
157149 event_json. insert (
158150 "event_time_unix_nano" . to_string ( ) ,
159151 Value :: String (
160152 convert_epoch_nano_to_timestamp ( event. time_unix_nano as i64 ) . to_string ( ) ,
161153 ) ,
162154 ) ;
163155 event_json. insert ( "event_name" . to_string ( ) , Value :: String ( event. name . clone ( ) ) ) ;
164- insert_attributes ( & mut event_json, & event. attributes , other_attributes) ;
156+ insert_attributes ( & mut event_json, & event. attributes , & mut other_attributes) ;
165157 event_json. insert (
166158 "event_dropped_attributes_count" . to_string ( ) ,
167159 Value :: Number ( event. dropped_attributes_count . into ( ) ) ,
168160 ) ;
161+
162+ if !other_attributes. is_empty ( ) {
163+ let other_attributes = fetch_attributes_string ( & other_attributes) ;
164+ event_json. insert (
165+ "other_attributes" . to_string ( ) ,
166+ Value :: String ( other_attributes) ,
167+ ) ;
168+ }
169169 event_json
170170 } )
171171 . collect ( )
@@ -174,14 +174,12 @@ fn flatten_events(
174174/// otel traces has json array of links
175175/// this function flattens the `Link` object
176176/// and returns a `Vec` of `Map` of the flattened json
177- fn flatten_links (
178- links : & [ Link ] ,
179- other_attributes : & mut Map < String , Value > ,
180- ) -> Vec < Map < String , Value > > {
177+ fn flatten_links ( links : & [ Link ] ) -> Vec < Map < String , Value > > {
181178 links
182179 . iter ( )
183180 . map ( |link| {
184181 let mut link_json = Map :: new ( ) ;
182+ let mut other_attributes = Map :: new ( ) ;
185183 link_json. insert (
186184 "link_span_id" . to_string ( ) ,
187185 Value :: String ( hex:: encode ( & link. span_id ) ) ,
@@ -191,11 +189,19 @@ fn flatten_links(
191189 Value :: String ( hex:: encode ( & link. trace_id ) ) ,
192190 ) ;
193191
194- insert_attributes ( & mut link_json, & link. attributes , other_attributes) ;
192+ insert_attributes ( & mut link_json, & link. attributes , & mut other_attributes) ;
195193 link_json. insert (
196194 "link_dropped_attributes_count" . to_string ( ) ,
197195 Value :: Number ( link. dropped_attributes_count . into ( ) ) ,
198196 ) ;
197+
198+ if !other_attributes. is_empty ( ) {
199+ let other_attributes = fetch_attributes_string ( & other_attributes) ;
200+ link_json. insert (
201+ "other_attributes" . to_string ( ) ,
202+ Value :: String ( other_attributes) ,
203+ ) ;
204+ }
199205 link_json
200206 } )
201207 . collect ( )
@@ -278,12 +284,9 @@ fn flatten_kind(kind: i32) -> Map<String, Value> {
278284/// this function flattens the `Span` object
279285/// and returns a `Vec` of `Map` of the flattened json
280286/// this function is called recursively for each span record object in the otel traces event
281- fn flatten_span_record (
282- span_record : & Span ,
283- other_attributes : & mut Map < String , Value > ,
284- ) -> Vec < Map < String , Value > > {
287+ fn flatten_span_record ( span_record : & Span ) -> Vec < Map < String , Value > > {
285288 let mut span_records_json = Vec :: new ( ) ;
286-
289+ let mut other_attributes = Map :: new ( ) ;
287290 let mut span_record_json = Map :: new ( ) ;
288291 span_record_json. insert (
289292 "span_trace_id" . to_string ( ) ,
@@ -322,18 +325,41 @@ fn flatten_span_record(
322325 insert_attributes (
323326 & mut span_record_json,
324327 & span_record. attributes ,
325- other_attributes,
328+ & mut other_attributes,
326329 ) ;
327330 span_record_json. insert (
328331 "span_dropped_attributes_count" . to_string ( ) ,
329332 Value :: Number ( span_record. dropped_attributes_count . into ( ) ) ,
330333 ) ;
331- span_records_json. extend ( flatten_events ( & span_record. events , other_attributes) ) ;
334+ let events_json = flatten_events ( & span_record. events ) ;
335+ // fetch all other_attributes from the events_json
336+ let events_other_attributes = fetch_attributes_from_json ( & events_json) ;
337+ span_records_json. extend ( events_json) ;
332338 span_record_json. insert (
333339 "span_dropped_events_count" . to_string ( ) ,
334340 Value :: Number ( span_record. dropped_events_count . into ( ) ) ,
335341 ) ;
336- span_records_json. extend ( flatten_links ( & span_record. links , other_attributes) ) ;
342+ let links_json = flatten_links ( & span_record. links ) ;
343+ // fetch all other_attributes from the links_json
344+ let links_other_attributes = fetch_attributes_from_json ( & links_json) ;
345+ span_records_json. extend ( links_json) ;
346+ if !other_attributes. is_empty ( ) {
347+ let other_attributes = fetch_attributes_string ( & other_attributes) ;
348+ span_record_json. insert (
349+ "other_attributes" . to_string ( ) ,
350+ Value :: String ( format ! (
351+ "{other_attributes} {events_other_attributes} {links_other_attributes}"
352+ ) ) ,
353+ ) ;
354+ } else {
355+ span_record_json. insert (
356+ "other_attributes" . to_string ( ) ,
357+ Value :: String ( format ! (
358+ "{events_other_attributes} {links_other_attributes}"
359+ ) ) ,
360+ ) ;
361+ }
362+
337363 span_record_json. insert (
338364 "span_dropped_links_count" . to_string ( ) ,
339365 Value :: Number ( span_record. dropped_links_count . into ( ) ) ,
0 commit comments