Skip to content

Commit 26391d6

Browse files
fix: Add hard limit to log batcher (#5069)
Introduce a hard limit on the number of elements in the log batcher. The size constraint prevents the log batcher from using too much memory.
1 parent faa327c commit 26391d6

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

sentry_sdk/_log_batcher.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,18 @@
1313

1414
class LogBatcher:
1515
MAX_LOGS_BEFORE_FLUSH = 100
16+
MAX_LOGS_BEFORE_DROP = 1_000
1617
FLUSH_WAIT_TIME = 5.0
1718

1819
def __init__(
1920
self,
2021
capture_func, # type: Callable[[Envelope], None]
22+
record_lost_func, # type: Callable[..., None]
2123
):
2224
# type: (...) -> None
2325
self._log_buffer = [] # type: List[Log]
2426
self._capture_func = capture_func
27+
self._record_lost_func = record_lost_func
2528
self._running = True
2629
self._lock = threading.Lock()
2730

@@ -79,6 +82,14 @@ def add(
7982
return None
8083

8184
with self._lock:
85+
if len(self._log_buffer) >= self.MAX_LOGS_BEFORE_DROP:
86+
self._record_lost_func(
87+
reason="queue_overflow",
88+
data_category="log_item",
89+
quantity=1,
90+
)
91+
return None
92+
8293
self._log_buffer.append(log)
8394
if len(self._log_buffer) >= self.MAX_LOGS_BEFORE_FLUSH:
8495
self._flush_event.set()

sentry_sdk/client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,10 @@ def _record_lost_event(
386386
if has_logs_enabled(self.options):
387387
from sentry_sdk._log_batcher import LogBatcher
388388

389-
self.log_batcher = LogBatcher(capture_func=_capture_envelope)
389+
self.log_batcher = LogBatcher(
390+
capture_func=_capture_envelope,
391+
record_lost_func=_record_lost_event,
392+
)
390393

391394
self.metrics_batcher = None
392395
if has_metrics_enabled(self.options):

tests/test_logs.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,3 +446,28 @@ def test_logs_with_literal_braces(
446446
assert logs[0]["attributes"]["sentry.message.template"] == message
447447
else:
448448
assert "sentry.message.template" not in logs[0]["attributes"]
449+
450+
451+
@minimum_python_37
452+
def test_batcher_drops_logs(sentry_init, monkeypatch):
453+
sentry_init(enable_logs=True)
454+
client = sentry_sdk.get_client()
455+
456+
def no_op_flush():
457+
pass
458+
459+
monkeypatch.setattr(client.log_batcher, "_flush", no_op_flush)
460+
461+
lost_event_calls = []
462+
463+
def record_lost_event(reason, data_category=None, item=None, *, quantity=1):
464+
lost_event_calls.append((reason, data_category, item, quantity))
465+
466+
monkeypatch.setattr(client.log_batcher, "_record_lost_func", record_lost_event)
467+
468+
for i in range(1_005): # 5 logs over the hard limit
469+
sentry_sdk.logger.info("This is a 'info' log...")
470+
471+
assert len(lost_event_calls) == 5
472+
for lost_event_call in lost_event_calls:
473+
assert lost_event_call == ("queue_overflow", "log_item", None, 1)

0 commit comments

Comments
 (0)