Skip to content

Commit 7b72efd

Browse files
authored
feat(transport): Added configurable compression levels (#2382)
1 parent a07c4ae commit 7b72efd

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

sentry_sdk/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"profiles_sample_rate": Optional[float],
4141
"profiler_mode": Optional[ProfilerMode],
4242
"otel_powered_performance": Optional[bool],
43+
"transport_zlib_compression_level": Optional[int],
4344
},
4445
total=False,
4546
)

sentry_sdk/transport.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ def __init__(
163163
proxy_headers=options["proxy_headers"],
164164
)
165165

166+
compresslevel = options.get("_experiments", {}).get(
167+
"transport_zlib_compression_level"
168+
)
169+
self._compresslevel = 9 if compresslevel is None else int(compresslevel)
170+
166171
from sentry_sdk import Hub
167172

168173
self.hub_cls = Hub
@@ -338,8 +343,13 @@ def _send_event(
338343
return None
339344

340345
body = io.BytesIO()
341-
with gzip.GzipFile(fileobj=body, mode="w") as f:
342-
f.write(json_dumps(event))
346+
if self._compresslevel == 0:
347+
body.write(json_dumps(event))
348+
else:
349+
with gzip.GzipFile(
350+
fileobj=body, mode="w", compresslevel=self._compresslevel
351+
) as f:
352+
f.write(json_dumps(event))
343353

344354
assert self.parsed_dsn is not None
345355
logger.debug(
@@ -352,10 +362,14 @@ def _send_event(
352362
self.parsed_dsn.host,
353363
)
354364
)
355-
self._send_request(
356-
body.getvalue(),
357-
headers={"Content-Type": "application/json", "Content-Encoding": "gzip"},
358-
)
365+
366+
headers = {
367+
"Content-Type": "application/json",
368+
}
369+
if self._compresslevel > 0:
370+
headers["Content-Encoding"] = "gzip"
371+
372+
self._send_request(body.getvalue(), headers=headers)
359373
return None
360374

361375
def _send_envelope(
@@ -390,8 +404,13 @@ def _send_envelope(
390404
envelope.items.append(client_report_item)
391405

392406
body = io.BytesIO()
393-
with gzip.GzipFile(fileobj=body, mode="w") as f:
394-
envelope.serialize_into(f)
407+
if self._compresslevel == 0:
408+
envelope.serialize_into(body)
409+
else:
410+
with gzip.GzipFile(
411+
fileobj=body, mode="w", compresslevel=self._compresslevel
412+
) as f:
413+
envelope.serialize_into(f)
395414

396415
assert self.parsed_dsn is not None
397416
logger.debug(
@@ -401,12 +420,15 @@ def _send_envelope(
401420
self.parsed_dsn.host,
402421
)
403422

423+
headers = {
424+
"Content-Type": "application/x-sentry-envelope",
425+
}
426+
if self._compresslevel > 0:
427+
headers["Content-Encoding"] = "gzip"
428+
404429
self._send_request(
405430
body.getvalue(),
406-
headers={
407-
"Content-Type": "application/x-sentry-envelope",
408-
"Content-Encoding": "gzip",
409-
},
431+
headers=headers,
410432
endpoint_type="envelope",
411433
envelope=envelope,
412434
)

tests/test_transport.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from sentry_sdk.integrations.logging import LoggingIntegration
1919

2020

21-
CapturedData = namedtuple("CapturedData", ["path", "event", "envelope"])
21+
CapturedData = namedtuple("CapturedData", ["path", "event", "envelope", "compressed"])
2222

2323

2424
class CapturingServer(WSGIServer):
@@ -42,15 +42,25 @@ def __call__(self, environ, start_response):
4242
"""
4343
request = Request(environ)
4444
event = envelope = None
45+
if request.headers.get("content-encoding") == "gzip":
46+
rdr = gzip.GzipFile(fileobj=io.BytesIO(request.data))
47+
compressed = True
48+
else:
49+
rdr = io.BytesIO(request.data)
50+
compressed = False
51+
4552
if request.mimetype == "application/json":
46-
event = parse_json(gzip.GzipFile(fileobj=io.BytesIO(request.data)).read())
53+
event = parse_json(rdr.read())
4754
else:
48-
envelope = Envelope.deserialize_from(
49-
gzip.GzipFile(fileobj=io.BytesIO(request.data))
50-
)
55+
envelope = Envelope.deserialize_from(rdr)
5156

5257
self.captured.append(
53-
CapturedData(path=request.path, event=event, envelope=envelope)
58+
CapturedData(
59+
path=request.path,
60+
event=event,
61+
envelope=envelope,
62+
compressed=compressed,
63+
)
5464
)
5565

5666
response = Response(status=self.code)
@@ -81,6 +91,7 @@ def inner(**kwargs):
8191
@pytest.mark.parametrize("debug", (True, False))
8292
@pytest.mark.parametrize("client_flush_method", ["close", "flush"])
8393
@pytest.mark.parametrize("use_pickle", (True, False))
94+
@pytest.mark.parametrize("compressionlevel", (0, 9))
8495
def test_transport_works(
8596
capturing_server,
8697
request,
@@ -90,10 +101,16 @@ def test_transport_works(
90101
make_client,
91102
client_flush_method,
92103
use_pickle,
104+
compressionlevel,
93105
maybe_monkeypatched_threading,
94106
):
95107
caplog.set_level(logging.DEBUG)
96-
client = make_client(debug=debug)
108+
client = make_client(
109+
debug=debug,
110+
_experiments={
111+
"transport_zlib_compression_level": compressionlevel,
112+
},
113+
)
97114

98115
if use_pickle:
99116
client = pickle.loads(pickle.dumps(client))
@@ -109,6 +126,7 @@ def test_transport_works(
109126
out, err = capsys.readouterr()
110127
assert not err and not out
111128
assert capturing_server.captured
129+
assert capturing_server.captured[0].compressed == (compressionlevel > 0)
112130

113131
assert any("Sending event" in record.msg for record in caplog.records) == debug
114132

0 commit comments

Comments
 (0)