@@ -95,23 +95,42 @@ def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dic
9595 # If we are in essential mode return the span with minimized attributes.
9696 if partial_granularity_type == "essential" :
9797 return [i_attrs , {}, a_minimized_attrs ]
98- # If the span is an exit span but span compression (compact) is enabled, we need to check
99- # for uniqueness before returning it.
98+ # If the span is an exit span but span compression (compact) is enabled,
99+ # we need to check for uniqueness before returning it.
100100 # Combine all the entity relationship attr values into a string to be
101101 # used as the hash to check for uniqueness.
102102 span_attrs = "" .join ([str (a_minimized_attrs [key ]) for key in exit_span_attrs_present ])
103103 new_exit_span = span_attrs not in ct_exit_spans
104- # If this is a new exit span, add it to the known ct_exit_spans and return it.
104+ # If this is a new exit span, add it to the known ct_exit_spans and
105+ # return it.
105106 if new_exit_span :
106- # ids is the list of span guids that share this unqiue exit span.
107+ # nr. ids is the list of span guids that share this unqiue exit span.
107108 a_minimized_attrs ["nr.ids" ] = []
108109 a_minimized_attrs ["nr.durations" ] = self .duration
109- ct_exit_spans [span_attrs ] = [a_minimized_attrs ]
110+ ct_exit_spans [span_attrs ] = [i_attrs , a_minimized_attrs ]
110111 return [i_attrs , {}, a_minimized_attrs ]
111112 # If this is an exit span we've already seen, add it's guid to the list
112- # of ids on the seen span and return None.
113- ct_exit_spans [span_attrs ][0 ]["nr.ids" ].append (self .guid )
114- ct_exit_spans [span_attrs ][0 ]["nr.durations" ] += self .duration
113+ # of ids on the seen span, compute the new duration & start time, and
114+ # return None.
115+ ct_exit_spans [span_attrs ][1 ]["nr.ids" ].append (self .guid )
116+ # Compute the new start and end time for all compressed spans and use
117+ # that to set the duration for all compressed spans.
118+ current_start_time = ct_exit_spans [span_attrs ][0 ]["timestamp" ]
119+ current_end_time = ct_exit_spans [span_attrs ][0 ]["timestamp" ]/ 1000 + ct_exit_spans [span_attrs ][1 ]["nr.durations" ]
120+ new_start_time = i_attrs ["timestamp" ]
121+ new_end_time = i_attrs ["timestamp" ]/ 1000 + i_attrs ["duration" ]
122+ set_start_time = min (new_start_time , current_start_time )
123+ # If the new span starts after the old span's end time or the new span
124+ # ends before the current span starts; add the durations.
125+ if current_end_time < new_start_time / 1000 or new_end_time < current_start_time / 1000 :
126+ set_duration = ct_exit_spans [span_attrs ][1 ]["nr.durations" ] + i_attrs ["duration" ]
127+ # Otherwise, if the new and old span's overlap in time, use the newest
128+ # end time and subtract the start time from it to calculate the new
129+ # duration.
130+ else :
131+ set_duration = max (current_end_time , new_end_time ) - set_start_time / 1000
132+ ct_exit_spans [span_attrs ][0 ]["timestamp" ] = set_start_time
133+ ct_exit_spans [span_attrs ][1 ]["nr.durations" ] = set_duration
115134 return None
116135
117136 def span_events (self , settings , base_attrs = None , parent_guid = None , attr_class = dict , partial_granularity_sampled = False , ct_exit_spans = None ):
0 commit comments