11
11
is_valid_sample_rate ,
12
12
logger ,
13
13
nanosecond_time ,
14
+ AnnotatedValue
14
15
)
15
16
16
17
from typing import TYPE_CHECKING
@@ -193,7 +194,7 @@ def get_span_status_from_http_code(http_status_code):
193
194
class _SpanRecorder :
194
195
"""Limits the number of spans recorded in a transaction."""
195
196
196
- __slots__ = ("maxlen" , "spans" )
197
+ __slots__ = ("maxlen" , "spans" , "dropped_spans" )
197
198
198
199
def __init__ (self , maxlen ):
199
200
# type: (int) -> None
@@ -203,15 +204,53 @@ def __init__(self, maxlen):
203
204
# should be changed to match a consistent interpretation of what maxlen
204
205
# limits: either transaction+spans or only child spans.
205
206
self .maxlen = maxlen - 1
206
- self .spans = [] # type: List[Span]
207
+ self .spans = [] # type: Union[List[Span], AnnotatedValue]
208
+ self .dropped_spans = 0 # type: int
207
209
208
210
def add (self , span ):
209
211
# type: (Span) -> None
210
212
if len (self .spans ) > self .maxlen :
211
213
span ._span_recorder = None
214
+ self .dropped_spans += 1
212
215
else :
213
216
self .spans .append (span )
214
217
218
+
219
+
220
+
221
+
222
+
223
+
224
+ # __slots__ = ("maxlen", "_spans")
225
+
226
+ # def __init__(self, maxlen):
227
+ # # type: (int) -> None
228
+ # # FIXME: this is `maxlen - 1` only to preserve historical behavior
229
+ # # enforced by tests.
230
+ # # Either this should be changed to `maxlen` or the JS SDK implementation
231
+ # # should be changed to match a consistent interpretation of what maxlen
232
+ # # limits: either transaction+spans or only child spans.
233
+ # self.maxlen = maxlen - 1
234
+ # self._spans = [] # type: Union[List[Span], AnnotatedValue]
235
+
236
+ # def add(self, span):
237
+ # # type: (Span) -> None
238
+ # if isinstance(self._spans, AnnotatedValue):
239
+ # self._spans.metadata["len"] += 1
240
+ # else:
241
+ # if len(self._spans) > self.maxlen:
242
+ # span._span_recorder = None
243
+ # self._spans = AnnotatedValue(self._spans, {"len": self.maxlen}) # TODO!
244
+ # else:
245
+ # self._spans.append(span)
246
+
247
+ # @property
248
+ # def spans(self):
249
+ # # type: () -> List[Span]
250
+ # if isinstance(self._spans, AnnotatedValue):
251
+ # return self._spans.value
252
+ # return self._spans
253
+
215
254
216
255
class Span :
217
256
"""A span holds timing information of a block of code.
@@ -972,6 +1011,10 @@ def finish(
972
1011
if span .timestamp is not None
973
1012
]
974
1013
1014
+ len_diff = len (self ._span_recorder .spans ) - len (finished_spans )
1015
+ if len_diff or self ._span_recorder .dropped_spans :
1016
+ finished_spans = AnnotatedValue (finished_spans , {"len" : len_diff + self ._span_recorder .dropped_spans })
1017
+
975
1018
# we do this to break the circular reference of transaction -> span
976
1019
# recorder -> span -> containing transaction (which is where we started)
977
1020
# before either the spans or the transaction goes out of scope and has
0 commit comments