Skip to content

Commit

Permalink
feat(redis): Patch rediscluster if present (#752)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
beezz committed Jul 1, 2020
1 parent 7d482b5 commit b718925
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 3 deletions.
26 changes: 25 additions & 1 deletion sentry_sdk/integrations/redis.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import absolute_import

from sentry_sdk import Hub
from sentry_sdk.utils import capture_internal_exceptions
from sentry_sdk.utils import capture_internal_exceptions, logger
from sentry_sdk.integrations import Integration

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


def _patch_rediscluster():
# type: () -> None
try:
import rediscluster # type: ignore
except ImportError:
return

patch_redis_client(rediscluster.RedisCluster)

# up to v1.3.6, __version__ attribute is a tuple
# from v2.0.0, __version__ is a string and VERSION a tuple
version = getattr(rediscluster, "VERSION", rediscluster.__version__)

# StrictRedisCluster was introduced in v0.2.0 and removed in v2.0.0
# https://github.com/Grokzen/redis-py-cluster/blob/master/docs/release-notes.rst
if (0, 2, 0) < version < (2, 0, 0):
patch_redis_client(rediscluster.StrictRedisCluster)


class RedisIntegration(Integration):
identifier = "redis"

Expand All @@ -34,6 +53,11 @@ def setup_once():
patch_redis_client(rb.clients.MappingClient)
patch_redis_client(rb.clients.RoutingClient)

try:
_patch_rediscluster()
except Exception:
logger.exception("Error occured while patching `rediscluster` library")


def patch_redis_client(cls):
# type: (Any) -> None
Expand Down
3 changes: 3 additions & 0 deletions tests/integrations/rediscluster/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pytest

pytest.importorskip("rediscluster")
37 changes: 37 additions & 0 deletions tests/integrations/rediscluster/test_rediscluster.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pytest
from sentry_sdk import capture_message
from sentry_sdk.integrations.redis import RedisIntegration

import rediscluster

rediscluster_classes = [rediscluster.RedisCluster]

if hasattr(rediscluster, "StrictRedisCluster"):
rediscluster_classes.append(rediscluster.StrictRedisCluster)


@pytest.fixture(scope="module", autouse=True)
def monkeypatch_rediscluster_classes():
for cls in rediscluster_classes:
cls.execute_command = lambda *_, **__: None


@pytest.mark.parametrize("rediscluster_cls", rediscluster_classes)
def test_rediscluster_basic(rediscluster_cls, sentry_init, capture_events):
sentry_init(integrations=[RedisIntegration()])
events = capture_events()

rc = rediscluster_cls(connection_pool=True)
rc.get("foobar")
capture_message("hi")

(event,) = events
(crumb,) = event["breadcrumbs"]

assert crumb == {
"category": "redis",
"message": "GET 'foobar'",
"data": {"redis.key": "foobar", "redis.command": "GET"},
"timestamp": crumb["timestamp"],
"type": "redis",
}
7 changes: 5 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ envlist =
{py2.7,py3.8}-requests

{py2.7,py3.7,py3.8}-redis
{py2.7,py3.7,py3.8}-rediscluster-{1,2}

py{3.7,3.8}-asgi

Expand Down Expand Up @@ -166,8 +167,9 @@ deps =
trytond-4.6: trytond>=4.6,<4.7

redis: fakeredis
# https://github.com/jamesls/fakeredis/issues/245
redis: redis<3.2.2

rediscluster-1: redis-py-cluster>=1.0.0,<2.0.0
rediscluster-2: redis-py-cluster>=2.0.0,<3.0.0

asgi: starlette
asgi: requests
Expand Down Expand Up @@ -199,6 +201,7 @@ setenv =
tornado: TESTPATH=tests/integrations/tornado
trytond: TESTPATH=tests/integrations/trytond
redis: TESTPATH=tests/integrations/redis
rediscluster: TESTPATH=tests/integrations/rediscluster
asgi: TESTPATH=tests/integrations/asgi
sqlalchemy: TESTPATH=tests/integrations/sqlalchemy
spark: TESTPATH=tests/integrations/spark
Expand Down

0 comments on commit b718925

Please sign in to comment.