Skip to content

Commit b7e32c5

Browse files
authored
feat: Make client pickleable (getsentry#439)
* feat: Make client pickleable * ref: Wrap pickle state in dict * fix: Encoding
1 parent 8ecc159 commit b7e32c5

File tree

3 files changed

+64
-38
lines changed

3 files changed

+64
-38
lines changed

sentry_sdk/client.py

+20-6
Original file line numberDiff line numberDiff line change
@@ -74,23 +74,37 @@ class _Client(object):
7474
"""
7575

7676
def __init__(self, *args, **kwargs):
77-
# type: (*Optional[str], **Any) -> None
77+
# type: (*Any, **Any) -> None
78+
self.options = get_options(*args, **kwargs) # type: Dict[str, Any]
79+
self._init_impl()
80+
81+
def __getstate__(self):
82+
# type: () -> Any
83+
return {"options": self.options}
84+
85+
def __setstate__(self, state):
86+
# type: (Any) -> None
87+
self.options = state["options"]
88+
self._init_impl()
89+
90+
def _init_impl(self):
91+
# type: () -> None
7892
old_debug = _client_init_debug.get(False)
7993
try:
80-
self.options = options = get_options(*args, **kwargs) # type: ignore
81-
_client_init_debug.set(options["debug"])
82-
self.transport = make_transport(options)
94+
_client_init_debug.set(self.options["debug"])
95+
self.transport = make_transport(self.options)
8396

8497
request_bodies = ("always", "never", "small", "medium")
85-
if options["request_bodies"] not in request_bodies:
98+
if self.options["request_bodies"] not in request_bodies:
8699
raise ValueError(
87100
"Invalid value for request_bodies. Must be one of {}".format(
88101
request_bodies
89102
)
90103
)
91104

92105
self.integrations = setup_integrations(
93-
options["integrations"], with_defaults=options["default_integrations"]
106+
self.options["integrations"],
107+
with_defaults=self.options["default_integrations"],
94108
)
95109
finally:
96110
_client_init_debug.set(old_debug)

tests/test_client.py

+1-32
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
# coding: utf-8
22
import json
3-
import logging
43
import pytest
54
import subprocess
65
import sys
76
import time
87

9-
from datetime import datetime
108
from textwrap import dedent
11-
from sentry_sdk import (
12-
Hub,
13-
Client,
14-
configure_scope,
15-
capture_message,
16-
add_breadcrumb,
17-
capture_exception,
18-
)
9+
from sentry_sdk import Hub, Client, configure_scope, capture_message, capture_exception
1910
from sentry_sdk.hub import HubMeta
2011
from sentry_sdk.transport import Transport
2112
from sentry_sdk._compat import reraise, text_type, PY2
@@ -359,28 +350,6 @@ def callback(scope):
359350
assert not calls
360351

361352

362-
@pytest.mark.parametrize("debug", (True, False))
363-
def test_transport_works(httpserver, request, capsys, caplog, debug):
364-
httpserver.serve_content("ok", 200)
365-
caplog.set_level(logging.DEBUG)
366-
367-
client = Client(
368-
"http://foobar@{}/123".format(httpserver.url[len("http://") :]), debug=debug
369-
)
370-
Hub.current.bind_client(client)
371-
request.addfinalizer(lambda: Hub.current.bind_client(None))
372-
373-
add_breadcrumb(level="info", message="i like bread", timestamp=datetime.now())
374-
capture_message("löl")
375-
client.close()
376-
377-
out, err = capsys.readouterr()
378-
assert not err and not out
379-
assert httpserver.requests
380-
381-
assert any("Sending event" in record.msg for record in caplog.records) == debug
382-
383-
384353
@pytest.mark.tests_internal_exceptions
385354
def test_client_debug_option_enabled(sentry_init, caplog):
386355
sentry_init(debug=True)

tests/test_transport.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# coding: utf-8
2+
import logging
3+
import pickle
4+
5+
from datetime import datetime
6+
7+
import pytest
8+
9+
from sentry_sdk import Hub, Client, add_breadcrumb, capture_message
10+
11+
12+
@pytest.fixture(params=[True, False])
13+
def make_client(request):
14+
def inner(*args, **kwargs):
15+
client = Client(*args, **kwargs)
16+
if request.param:
17+
client = pickle.loads(pickle.dumps(client))
18+
19+
return client
20+
21+
return inner
22+
23+
24+
@pytest.mark.parametrize("debug", (True, False))
25+
def test_transport_works(httpserver, request, capsys, caplog, debug, make_client):
26+
httpserver.serve_content("ok", 200)
27+
caplog.set_level(logging.DEBUG)
28+
29+
client = make_client(
30+
"http://foobar@{}/123".format(httpserver.url[len("http://") :]), debug=debug
31+
)
32+
Hub.current.bind_client(client)
33+
request.addfinalizer(lambda: Hub.current.bind_client(None))
34+
35+
add_breadcrumb(level="info", message="i like bread", timestamp=datetime.now())
36+
capture_message("löl")
37+
client.close()
38+
39+
out, err = capsys.readouterr()
40+
assert not err and not out
41+
assert httpserver.requests
42+
43+
assert any("Sending event" in record.msg for record in caplog.records) == debug

0 commit comments

Comments
 (0)