Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sentry_sdk/_log_batcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def add(
self._record_lost_func(
reason="queue_overflow",
data_category="log_item",
item=LogBatcher._log_to_transport_format(log),
quantity=1,
)
return None
Expand Down
1 change: 1 addition & 0 deletions sentry_sdk/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ class SDKInfo(TypedDict):
"monitor",
"span",
"log_item",
"log_byte",
"trace_metric",
]
SessionStatus = Literal["ok", "exited", "crashed", "abnormal"]
Expand Down
5 changes: 5 additions & 0 deletions sentry_sdk/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ def record_lost_event(
)
self.record_lost_event(reason, "span", quantity=span_count)

elif data_category == "log_item" and item:
# Also record size of lost logs in bytes
bytes_size = len(item.get_bytes())
self.record_lost_event(reason, "log_byte", quantity=bytes_size)

elif data_category == "attachment":
# quantity of 0 is actually 1 as we do not want to count
# empty attachments as actually empty.
Expand Down
52 changes: 50 additions & 2 deletions tests/test_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import time
from typing import List, Any, Mapping, Union
import pytest
from unittest import mock

import sentry_sdk
import sentry_sdk.logger
Expand Down Expand Up @@ -450,7 +451,7 @@ def test_logs_with_literal_braces(

@minimum_python_37
def test_batcher_drops_logs(sentry_init, monkeypatch):
sentry_init(enable_logs=True)
sentry_init(enable_logs=True, server_name="test-server", release="1.0.0")
client = sentry_sdk.get_client()

def no_op_flush():
Expand All @@ -469,5 +470,52 @@ def record_lost_event(reason, data_category=None, item=None, *, quantity=1):
sentry_sdk.logger.info("This is a 'info' log...")

assert len(lost_event_calls) == 5

expected_dropped_item = {
"body": "This is a 'info' log...",
"level": "info",
"timestamp": mock.ANY,
"trace_id": mock.ANY,
"attributes": {
"sentry.environment": {
"type": "string",
"value": "production",
},
"sentry.release": {
"type": "string",
"value": "1.0.0",
},
"sentry.sdk.name": {
"type": "string",
"value": mock.ANY,
},
"sentry.sdk.version": {
"type": "string",
"value": VERSION,
},
"sentry.severity_number": {
"type": "integer",
"value": 9,
},
"sentry.severity_text": {
"type": "string",
"value": "info",
},
"sentry.trace.parent_span_id": {
"type": "string",
"value": mock.ANY,
},
"server.address": {
"type": "string",
"value": "test-server",
},
},
}

for lost_event_call in lost_event_calls:
assert lost_event_call == ("queue_overflow", "log_item", None, 1)
assert lost_event_call == (
"queue_overflow",
"log_item",
expected_dropped_item,
1,
)
128 changes: 122 additions & 6 deletions tests/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
Hub,
)
from sentry_sdk._compat import PY37, PY38
from sentry_sdk.envelope import Envelope, Item, parse_json
from sentry_sdk.envelope import Envelope, Item, parse_json, PayloadRef
from sentry_sdk.transport import (
KEEP_ALIVE_SOCKET_OPTIONS,
_parse_rate_limits,
Expand Down Expand Up @@ -591,7 +591,110 @@ def test_complex_limits_without_data_category(


@pytest.mark.parametrize("response_code", [200, 429])
def test_log_item_limits(capturing_server, response_code, make_client):
@pytest.mark.parametrize(
"item",
[
Item(payload=b"{}", type="log"),
Item(
type="log",
content_type="application/vnd.sentry.items.log+json",
headers={
"item_count": 2,
},
payload=PayloadRef(
json={
"items": [
{
"body": "This is a 'info' log...",
"level": "info",
"timestamp": datetime(
2025, 1, 1, tzinfo=timezone.utc
).timestamp(),
"trace_id": "00000000-0000-0000-0000-000000000000",
"attributes": {
"sentry.environment": {
"value": "production",
"type": "string",
},
"sentry.release": {
"value": "1.0.0",
"type": "string",
},
"sentry.sdk.name": {
"value": "sentry.python",
"type": "string",
},
"sentry.sdk.version": {
"value": "2.45.0",
"type": "string",
},
"sentry.severity_number": {
"value": 9,
"type": "integer",
},
"sentry.severity_text": {
"value": "info",
"type": "string",
},
"server.address": {
"value": "test-server",
"type": "string",
},
},
},
{
"body": "The recorded value was '2.0'",
"level": "warn",
"timestamp": datetime(
2025, 1, 1, tzinfo=timezone.utc
).timestamp(),
"trace_id": "00000000-0000-0000-0000-000000000000",
"attributes": {
"sentry.message.parameter.float_var": {
"value": 2.0,
"type": "double",
},
"sentry.message.template": {
"value": "The recorded value was '{float_var}'",
"type": "string",
},
"sentry.sdk.name": {
"value": "sentry.python",
"type": "string",
},
"sentry.sdk.version": {
"value": "2.45.0",
"type": "string",
},
"server.address": {
"value": "test-server",
"type": "string",
},
"sentry.environment": {
"value": "production",
"type": "string",
},
"sentry.release": {
"value": "1.0.0",
"type": "string",
},
"sentry.severity_number": {
"value": 13,
"type": "integer",
},
"sentry.severity_text": {
"value": "warn",
"type": "string",
},
},
},
]
}
),
),
],
)
def test_log_item_limits(capturing_server, response_code, item, make_client):
client = make_client()
capturing_server.respond_with(
code=response_code,
Expand All @@ -601,7 +704,7 @@ def test_log_item_limits(capturing_server, response_code, make_client):
)

envelope = Envelope()
envelope.add_item(Item(payload=b"{}", type="log"))
envelope.add_item(item)
client.transport.capture_envelope(envelope)
client.flush()

Expand All @@ -622,9 +725,22 @@ def test_log_item_limits(capturing_server, response_code, make_client):
envelope = capturing_server.captured[1].envelope
assert envelope.items[0].type == "client_report"
report = parse_json(envelope.items[0].get_bytes())
assert report["discarded_events"] == [
{"category": "log_item", "reason": "ratelimit_backoff", "quantity": 1},
]

assert {
"category": "log_item",
"reason": "ratelimit_backoff",
"quantity": 1,
} in report["discarded_events"]

expected_lost_bytes = 1243
if item.payload.bytes == b"{}":
expected_lost_bytes = 2

assert {
"category": "log_byte",
"reason": "ratelimit_backoff",
"quantity": expected_lost_bytes,
} in report["discarded_events"]


def test_hub_cls_backwards_compat():
Expand Down