ref(batcher): Only flush the bucket that triggered the flush event #6168
2 issues
find-bugs: Found 2 issues (2 low)
Low
_flush_queue grows with duplicate trace_ids while bucket is awaiting flush - `sentry_sdk/_span_batcher.py:103-109`
In add(), every span added to a bucket that already exceeds MAX_BEFORE_FLUSH (or MAX_BYTES_BEFORE_FLUSH) puts another copy of the same trace_id onto _flush_queue. Until the bucket is actually drained by the flusher, up to (MAX_BEFORE_DROP - MAX_BEFORE_FLUSH) = 1000 redundant entries can accumulate per trace, multiplied across concurrent traces. The flusher then performs many no-op _flush() calls (each acquiring the lock) for buckets that have already been flushed. The 'XXX remove trace_id from queue' comment in _flush() acknowledges the missing dedup. Impact: wasted CPU/lock contention and unbounded queue growth proportional to span volume; not a correctness bug.
kill() does not join the flusher thread, risking lost spans on shutdown - `sentry_sdk/_span_batcher.py:113-119`
kill() sets _running=False, puts None on _flush_queue (which causes _flush_loop to call _flush(trace_id=None), a full flush), and immediately sets self._flusher=None without join()ing. If the interpreter shuts down before the daemon flusher thread finishes its final full flush and the resulting envelope is captured/transported, in-flight spans can be lost. The parent Batcher.kill() has the same shape, but here the final flush is more expensive (multiple envelopes per trace) so the window is larger.
Duration: 1m 37s · Tokens: 202.6k in / 5.5k out · Cost: $1.22 (+merge: $0.00)