Skip to content

Commit b718925

Browse files
authored
feat(redis): Patch rediscluster if present (#752)
* feat(redis): Patch rediscluster if present In addition to the redis and rb clients try to patch also the rediscluster library which does not use the already patched clients. * Add basic rediscluster tests
1 parent 7d482b5 commit b718925

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

sentry_sdk/integrations/redis.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import absolute_import
22

33
from sentry_sdk import Hub
4-
from sentry_sdk.utils import capture_internal_exceptions
4+
from sentry_sdk.utils import capture_internal_exceptions, logger
55
from sentry_sdk.integrations import Integration
66

77
from sentry_sdk._types import MYPY
@@ -15,6 +15,25 @@
1515
_MULTI_KEY_COMMANDS = frozenset(["del", "touch", "unlink"])
1616

1717

18+
def _patch_rediscluster():
19+
# type: () -> None
20+
try:
21+
import rediscluster # type: ignore
22+
except ImportError:
23+
return
24+
25+
patch_redis_client(rediscluster.RedisCluster)
26+
27+
# up to v1.3.6, __version__ attribute is a tuple
28+
# from v2.0.0, __version__ is a string and VERSION a tuple
29+
version = getattr(rediscluster, "VERSION", rediscluster.__version__)
30+
31+
# StrictRedisCluster was introduced in v0.2.0 and removed in v2.0.0
32+
# https://github.com/Grokzen/redis-py-cluster/blob/master/docs/release-notes.rst
33+
if (0, 2, 0) < version < (2, 0, 0):
34+
patch_redis_client(rediscluster.StrictRedisCluster)
35+
36+
1837
class RedisIntegration(Integration):
1938
identifier = "redis"
2039

@@ -34,6 +53,11 @@ def setup_once():
3453
patch_redis_client(rb.clients.MappingClient)
3554
patch_redis_client(rb.clients.RoutingClient)
3655

56+
try:
57+
_patch_rediscluster()
58+
except Exception:
59+
logger.exception("Error occured while patching `rediscluster` library")
60+
3761

3862
def patch_redis_client(cls):
3963
# type: (Any) -> None
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import pytest
2+
3+
pytest.importorskip("rediscluster")
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import pytest
2+
from sentry_sdk import capture_message
3+
from sentry_sdk.integrations.redis import RedisIntegration
4+
5+
import rediscluster
6+
7+
rediscluster_classes = [rediscluster.RedisCluster]
8+
9+
if hasattr(rediscluster, "StrictRedisCluster"):
10+
rediscluster_classes.append(rediscluster.StrictRedisCluster)
11+
12+
13+
@pytest.fixture(scope="module", autouse=True)
14+
def monkeypatch_rediscluster_classes():
15+
for cls in rediscluster_classes:
16+
cls.execute_command = lambda *_, **__: None
17+
18+
19+
@pytest.mark.parametrize("rediscluster_cls", rediscluster_classes)
20+
def test_rediscluster_basic(rediscluster_cls, sentry_init, capture_events):
21+
sentry_init(integrations=[RedisIntegration()])
22+
events = capture_events()
23+
24+
rc = rediscluster_cls(connection_pool=True)
25+
rc.get("foobar")
26+
capture_message("hi")
27+
28+
(event,) = events
29+
(crumb,) = event["breadcrumbs"]
30+
31+
assert crumb == {
32+
"category": "redis",
33+
"message": "GET 'foobar'",
34+
"data": {"redis.key": "foobar", "redis.command": "GET"},
35+
"timestamp": crumb["timestamp"],
36+
"type": "redis",
37+
}

tox.ini

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ envlist =
6262
{py2.7,py3.8}-requests
6363

6464
{py2.7,py3.7,py3.8}-redis
65+
{py2.7,py3.7,py3.8}-rediscluster-{1,2}
6566

6667
py{3.7,3.8}-asgi
6768

@@ -166,8 +167,9 @@ deps =
166167
trytond-4.6: trytond>=4.6,<4.7
167168

168169
redis: fakeredis
169-
# https://github.com/jamesls/fakeredis/issues/245
170-
redis: redis<3.2.2
170+
171+
rediscluster-1: redis-py-cluster>=1.0.0,<2.0.0
172+
rediscluster-2: redis-py-cluster>=2.0.0,<3.0.0
171173

172174
asgi: starlette
173175
asgi: requests
@@ -199,6 +201,7 @@ setenv =
199201
tornado: TESTPATH=tests/integrations/tornado
200202
trytond: TESTPATH=tests/integrations/trytond
201203
redis: TESTPATH=tests/integrations/redis
204+
rediscluster: TESTPATH=tests/integrations/rediscluster
202205
asgi: TESTPATH=tests/integrations/asgi
203206
sqlalchemy: TESTPATH=tests/integrations/sqlalchemy
204207
spark: TESTPATH=tests/integrations/spark

0 commit comments

Comments
 (0)