Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/sentry_sdk/integrations/redis.py: 27%
61 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1from __future__ import absolute_import
3from sentry_sdk import Hub
4from sentry_sdk.utils import capture_internal_exceptions, logger
5from sentry_sdk.integrations import Integration, DidNotEnable
7from sentry_sdk._types import MYPY
9if MYPY: 9 ↛ 10line 9 didn't jump to line 10, because the condition on line 9 was never true
10 from typing import Any
12_SINGLE_KEY_COMMANDS = frozenset(
13 ["decr", "decrby", "get", "incr", "incrby", "pttl", "set", "setex", "setnx", "ttl"]
14)
15_MULTI_KEY_COMMANDS = frozenset(["del", "touch", "unlink"])
18def _patch_rediscluster():
19 # type: () -> None
20 try:
21 import rediscluster # type: ignore
22 except ImportError:
23 return
25 patch_redis_client(rediscluster.RedisCluster)
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__)
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)
37class RedisIntegration(Integration):
38 identifier = "redis"
40 @staticmethod
41 def setup_once():
42 # type: () -> None
43 try:
44 import redis
45 except ImportError:
46 raise DidNotEnable("Redis client not installed")
48 patch_redis_client(redis.StrictRedis)
50 try:
51 import rb.clients # type: ignore
52 except ImportError:
53 pass
54 else:
55 patch_redis_client(rb.clients.FanoutClient)
56 patch_redis_client(rb.clients.MappingClient)
57 patch_redis_client(rb.clients.RoutingClient)
59 try:
60 _patch_rediscluster()
61 except Exception:
62 logger.exception("Error occurred while patching `rediscluster` library")
65def patch_redis_client(cls):
66 # type: (Any) -> None
67 """
68 This function can be used to instrument custom redis client classes or
69 subclasses.
70 """
72 old_execute_command = cls.execute_command
74 def sentry_patched_execute_command(self, name, *args, **kwargs):
75 # type: (Any, str, *Any, **Any) -> Any
76 hub = Hub.current
78 if hub.get_integration(RedisIntegration) is None:
79 return old_execute_command(self, name, *args, **kwargs)
81 description = name
83 with capture_internal_exceptions():
84 description_parts = [name]
85 for i, arg in enumerate(args):
86 if i > 10:
87 break
89 description_parts.append(repr(arg))
91 description = " ".join(description_parts)
93 with hub.start_span(op="redis", description=description) as span:
94 if name:
95 span.set_tag("redis.command", name)
97 if name and args:
98 name_low = name.lower()
99 if (name_low in _SINGLE_KEY_COMMANDS) or (
100 name_low in _MULTI_KEY_COMMANDS and len(args) == 1
101 ):
102 span.set_tag("redis.key", args[0])
104 return old_execute_command(self, name, *args, **kwargs)
106 cls.execute_command = sentry_patched_execute_command