sentry-sdk 2.2.0__tar.gz → 2.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. {sentry_sdk-2.2.0/sentry_sdk.egg-info → sentry_sdk-2.3.0}/PKG-INFO +2 -1
  2. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/consts.py +22 -2
  3. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/celery/__init__.py +54 -5
  4. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/clickhouse_driver.py +8 -7
  5. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/cohere.py +8 -2
  6. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/django/__init__.py +13 -1
  7. sentry_sdk-2.3.0/sentry_sdk/integrations/django/caching.py +176 -0
  8. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/__init__.py +37 -0
  9. sentry_sdk-2.2.0/sentry_sdk/integrations/redis/asyncio.py → sentry_sdk-2.3.0/sentry_sdk/integrations/redis/_async_common.py +49 -14
  10. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/_sync_common.py +108 -0
  11. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/consts.py +17 -0
  12. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/modules/caches.py +114 -0
  13. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/modules/queries.py +68 -0
  14. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/rb.py +32 -0
  15. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/redis.py +69 -0
  16. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/redis_cluster.py +98 -0
  17. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +50 -0
  18. sentry_sdk-2.3.0/sentry_sdk/integrations/redis/utils.py +116 -0
  19. sentry_sdk-2.3.0/sentry_sdk/py.typed +0 -0
  20. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0/sentry_sdk.egg-info}/PKG-INFO +2 -1
  21. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk.egg-info/SOURCES.txt +11 -1
  22. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk.egg-info/requires.txt +1 -0
  23. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/setup.py +2 -2
  24. sentry_sdk-2.2.0/sentry_sdk/integrations/django/caching.py +0 -115
  25. sentry_sdk-2.2.0/sentry_sdk/integrations/redis/__init__.py +0 -377
  26. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/LICENSE +0 -0
  27. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/MANIFEST.in +0 -0
  28. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/README.md +0 -0
  29. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/pyproject.toml +0 -0
  30. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/__init__.py +0 -0
  31. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/_compat.py +0 -0
  32. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/_lru_cache.py +0 -0
  33. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/_queue.py +0 -0
  34. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/_types.py +0 -0
  35. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/_werkzeug.py +0 -0
  36. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/ai/__init__.py +0 -0
  37. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/ai/monitoring.py +0 -0
  38. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/ai/utils.py +0 -0
  39. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/api.py +0 -0
  40. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/attachments.py +0 -0
  41. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/client.py +0 -0
  42. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/crons/__init__.py +0 -0
  43. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/crons/api.py +0 -0
  44. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/crons/consts.py +0 -0
  45. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/crons/decorator.py +0 -0
  46. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/db/__init__.py +0 -0
  47. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/db/explain_plan/__init__.py +0 -0
  48. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/db/explain_plan/django.py +0 -0
  49. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/db/explain_plan/sqlalchemy.py +0 -0
  50. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/debug.py +0 -0
  51. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/envelope.py +0 -0
  52. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/hub.py +0 -0
  53. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/__init__.py +0 -0
  54. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/_asgi_common.py +0 -0
  55. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/_wsgi_common.py +0 -0
  56. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/aiohttp.py +0 -0
  57. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/anthropic.py +0 -0
  58. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/argv.py +0 -0
  59. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/ariadne.py +0 -0
  60. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/arq.py +0 -0
  61. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/asgi.py +0 -0
  62. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/asyncio.py +0 -0
  63. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/asyncpg.py +0 -0
  64. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/atexit.py +0 -0
  65. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/aws_lambda.py +0 -0
  66. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/beam.py +0 -0
  67. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/boto3.py +0 -0
  68. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/bottle.py +0 -0
  69. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/celery/beat.py +0 -0
  70. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/celery/utils.py +0 -0
  71. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/chalice.py +0 -0
  72. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/cloud_resource_context.py +0 -0
  73. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/dedupe.py +0 -0
  74. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/django/asgi.py +0 -0
  75. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/django/middleware.py +0 -0
  76. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/django/signals_handlers.py +0 -0
  77. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/django/templates.py +0 -0
  78. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/django/transactions.py +0 -0
  79. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/django/views.py +0 -0
  80. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/excepthook.py +0 -0
  81. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/executing.py +0 -0
  82. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/falcon.py +0 -0
  83. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/fastapi.py +0 -0
  84. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/flask.py +0 -0
  85. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/gcp.py +0 -0
  86. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/gnu_backtrace.py +0 -0
  87. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/gql.py +0 -0
  88. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/graphene.py +0 -0
  89. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/grpc/__init__.py +0 -0
  90. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/grpc/aio/__init__.py +0 -0
  91. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/grpc/aio/client.py +0 -0
  92. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/grpc/aio/server.py +0 -0
  93. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/grpc/client.py +0 -0
  94. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/grpc/server.py +0 -0
  95. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/httpx.py +0 -0
  96. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/huey.py +0 -0
  97. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/huggingface_hub.py +0 -0
  98. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/langchain.py +0 -0
  99. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/logging.py +0 -0
  100. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/loguru.py +0 -0
  101. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/modules.py +0 -0
  102. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/openai.py +0 -0
  103. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/opentelemetry/__init__.py +0 -0
  104. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/opentelemetry/consts.py +0 -0
  105. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/opentelemetry/integration.py +0 -0
  106. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/opentelemetry/propagator.py +0 -0
  107. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/opentelemetry/span_processor.py +0 -0
  108. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/pure_eval.py +0 -0
  109. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/pymongo.py +0 -0
  110. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/pyramid.py +0 -0
  111. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/quart.py +0 -0
  112. /sentry_sdk-2.2.0/sentry_sdk/py.typed → /sentry_sdk-2.3.0/sentry_sdk/integrations/redis/modules/__init__.py +0 -0
  113. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/rq.py +0 -0
  114. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/sanic.py +0 -0
  115. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/serverless.py +0 -0
  116. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/socket.py +0 -0
  117. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/spark/__init__.py +0 -0
  118. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/spark/spark_driver.py +0 -0
  119. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/spark/spark_worker.py +0 -0
  120. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/sqlalchemy.py +0 -0
  121. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/starlette.py +0 -0
  122. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/starlite.py +0 -0
  123. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/stdlib.py +0 -0
  124. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/strawberry.py +0 -0
  125. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/threading.py +0 -0
  126. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/tornado.py +0 -0
  127. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/trytond.py +0 -0
  128. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/integrations/wsgi.py +0 -0
  129. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/metrics.py +0 -0
  130. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/monitor.py +0 -0
  131. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/profiler.py +0 -0
  132. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/scope.py +0 -0
  133. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/scrubber.py +0 -0
  134. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/serializer.py +0 -0
  135. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/session.py +0 -0
  136. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/sessions.py +0 -0
  137. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/spotlight.py +0 -0
  138. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/tracing.py +0 -0
  139. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/tracing_utils.py +0 -0
  140. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/transport.py +0 -0
  141. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/types.py +0 -0
  142. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/utils.py +0 -0
  143. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk/worker.py +0 -0
  144. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk.egg-info/dependency_links.txt +0 -0
  145. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk.egg-info/not-zip-safe +0 -0
  146. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/sentry_sdk.egg-info/top_level.txt +0 -0
  147. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/setup.cfg +0 -0
  148. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_api.py +0 -0
  149. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_basics.py +0 -0
  150. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_client.py +0 -0
  151. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_conftest.py +0 -0
  152. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_crons.py +0 -0
  153. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_envelope.py +0 -0
  154. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_exceptiongroup.py +0 -0
  155. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_lru_cache.py +0 -0
  156. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_metrics.py +0 -0
  157. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_monitor.py +0 -0
  158. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_new_scopes_compat.py +0 -0
  159. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_new_scopes_compat_event.py +0 -0
  160. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_profiler.py +0 -0
  161. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_propagationcontext.py +0 -0
  162. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_scope.py +0 -0
  163. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_scrubber.py +0 -0
  164. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_serializer.py +0 -0
  165. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_sessions.py +0 -0
  166. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_spotlight.py +0 -0
  167. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_transport.py +0 -0
  168. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_types.py +0 -0
  169. {sentry_sdk-2.2.0 → sentry_sdk-2.3.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sentry-sdk
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Python client for Sentry (https://sentry.io)
5
5
  Home-page: https://github.com/getsentry/sentry-python
6
6
  Author: Sentry Team and Contributors
@@ -60,6 +60,7 @@ Requires-Dist: blinker>=1.1; extra == "flask"
60
60
  Requires-Dist: markupsafe; extra == "flask"
61
61
  Provides-Extra: grpcio
62
62
  Requires-Dist: grpcio>=1.21.1; extra == "grpcio"
63
+ Requires-Dist: protobuf>=3.8.0; extra == "grpcio"
63
64
  Provides-Extra: httpx
64
65
  Requires-Dist: httpx>=0.16.0; extra == "httpx"
65
66
  Provides-Extra: huey
@@ -240,6 +240,24 @@ class SPANDATA:
240
240
  Example: 58
241
241
  """
242
242
 
243
+ CACHE_KEY = "cache.key"
244
+ """
245
+ The key of the requested data.
246
+ Example: template.cache.some_item.867da7e2af8e6b2f3aa7213a4080edb3
247
+ """
248
+
249
+ NETWORK_PEER_ADDRESS = "network.peer.address"
250
+ """
251
+ Peer address of the network connection - IP address or Unix domain socket name.
252
+ Example: 10.1.2.80, /tmp/my.sock, localhost
253
+ """
254
+
255
+ NETWORK_PEER_PORT = "network.peer.port"
256
+ """
257
+ Peer port number of the network connection.
258
+ Example: 6379
259
+ """
260
+
243
261
  HTTP_QUERY = "http.query"
244
262
  """
245
263
  The Query string present in the URL.
@@ -349,7 +367,8 @@ class SPANDATA:
349
367
 
350
368
  class OP:
351
369
  ANTHROPIC_MESSAGES_CREATE = "ai.messages.create.anthropic"
352
- CACHE_GET_ITEM = "cache.get_item"
370
+ CACHE_GET = "cache.get"
371
+ CACHE_PUT = "cache.put"
353
372
  COHERE_CHAT_COMPLETIONS_CREATE = "ai.chat_completions.create.cohere"
354
373
  COHERE_EMBEDDINGS_CREATE = "ai.embeddings.create.cohere"
355
374
  DB = "db"
@@ -388,6 +407,7 @@ class OP:
388
407
  LANGCHAIN_AGENT = "ai.agent.langchain"
389
408
  LANGCHAIN_CHAT_COMPLETIONS_CREATE = "ai.chat_completions.create.langchain"
390
409
  QUEUE_PROCESS = "queue.process"
410
+ QUEUE_PUBLISH = "queue.publish"
391
411
  QUEUE_SUBMIT_ARQ = "queue.submit.arq"
392
412
  QUEUE_TASK_ARQ = "queue.task.arq"
393
413
  QUEUE_SUBMIT_CELERY = "queue.submit.celery"
@@ -488,4 +508,4 @@ DEFAULT_OPTIONS = _get_default_options()
488
508
  del _get_default_options
489
509
 
490
510
 
491
- VERSION = "2.2.0"
511
+ VERSION = "2.3.0"
@@ -1,4 +1,5 @@
1
1
  import sys
2
+ from collections.abc import Mapping
2
3
  from functools import wraps
3
4
 
4
5
  import sentry_sdk
@@ -47,6 +48,7 @@ try:
47
48
  Retry,
48
49
  SoftTimeLimitExceeded,
49
50
  )
51
+ from kombu import Producer # type: ignore
50
52
  except ImportError:
51
53
  raise DidNotEnable("Celery not installed")
52
54
 
@@ -82,6 +84,7 @@ class CeleryIntegration(Integration):
82
84
  _patch_build_tracer()
83
85
  _patch_task_apply_async()
84
86
  _patch_worker_exit()
87
+ _patch_producer_publish()
85
88
 
86
89
  # This logger logs every status of every task that ran on the worker.
87
90
  # Meaning that every task's breadcrumbs are full of stuff like "Task
@@ -330,11 +333,12 @@ def _set_messaging_destination_name(task, span):
330
333
  """Set "messaging.destination.name" tag for span"""
331
334
  with capture_internal_exceptions():
332
335
  delivery_info = task.request.delivery_info
333
- routing_key = delivery_info.get("routing_key")
334
- if delivery_info.get("exchange") == "" and routing_key is not None:
335
- # Empty exchange indicates the default exchange, meaning the tasks
336
- # are sent to the queue with the same name as the routing key.
337
- span.set_data(SPANDATA.MESSAGING_DESTINATION_NAME, routing_key)
336
+ if delivery_info:
337
+ routing_key = delivery_info.get("routing_key")
338
+ if delivery_info.get("exchange") == "" and routing_key is not None:
339
+ # Empty exchange indicates the default exchange, meaning the tasks
340
+ # are sent to the queue with the same name as the routing key.
341
+ span.set_data(SPANDATA.MESSAGING_DESTINATION_NAME, routing_key)
338
342
 
339
343
 
340
344
  def _wrap_task_call(task, f):
@@ -433,3 +437,48 @@ def _patch_worker_exit():
433
437
  sentry_sdk.flush()
434
438
 
435
439
  Worker.workloop = sentry_workloop
440
+
441
+
442
+ def _patch_producer_publish():
443
+ # type: () -> None
444
+ original_publish = Producer.publish
445
+
446
+ @ensure_integration_enabled(CeleryIntegration, original_publish)
447
+ def sentry_publish(self, *args, **kwargs):
448
+ # type: (Producer, *Any, **Any) -> Any
449
+ kwargs_headers = kwargs.get("headers", {})
450
+ if not isinstance(kwargs_headers, Mapping):
451
+ # Ensure kwargs_headers is a Mapping, so we can safely call get().
452
+ # We don't expect this to happen, but it's better to be safe. Even
453
+ # if it does happen, only our instrumentation breaks. This line
454
+ # does not overwrite kwargs["headers"], so the original publish
455
+ # method will still work.
456
+ kwargs_headers = {}
457
+
458
+ task_name = kwargs_headers.get("task")
459
+ task_id = kwargs_headers.get("id")
460
+ retries = kwargs_headers.get("retries")
461
+
462
+ routing_key = kwargs.get("routing_key")
463
+ exchange = kwargs.get("exchange")
464
+
465
+ with sentry_sdk.start_span(op=OP.QUEUE_PUBLISH, description=task_name) as span:
466
+ if task_id is not None:
467
+ span.set_data(SPANDATA.MESSAGING_MESSAGE_ID, task_id)
468
+
469
+ if exchange == "" and routing_key is not None:
470
+ # Empty exchange indicates the default exchange, meaning messages are
471
+ # routed to the queue with the same name as the routing key.
472
+ span.set_data(SPANDATA.MESSAGING_DESTINATION_NAME, routing_key)
473
+
474
+ if retries is not None:
475
+ span.set_data(SPANDATA.MESSAGING_MESSAGE_RETRY_COUNT, retries)
476
+
477
+ with capture_internal_exceptions():
478
+ span.set_data(
479
+ SPANDATA.MESSAGING_SYSTEM, self.connection.transport.driver_type
480
+ )
481
+
482
+ return original_publish(self, *args, **kwargs)
483
+
484
+ Producer.publish = sentry_publish
@@ -107,7 +107,7 @@ def _wrap_end(f: Callable[P, T]) -> Callable[P, T]:
107
107
  def _inner_end(*args: P.args, **kwargs: P.kwargs) -> T:
108
108
  res = f(*args, **kwargs)
109
109
  instance = args[0]
110
- span = instance.connection._sentry_span # type: ignore[attr-defined]
110
+ span = getattr(instance.connection, "_sentry_span", None) # type: ignore[attr-defined]
111
111
 
112
112
  if span is not None:
113
113
  if res is not None and should_send_default_pii():
@@ -129,14 +129,15 @@ def _wrap_send_data(f: Callable[P, T]) -> Callable[P, T]:
129
129
  def _inner_send_data(*args: P.args, **kwargs: P.kwargs) -> T:
130
130
  instance = args[0] # type: clickhouse_driver.client.Client
131
131
  data = args[2]
132
- span = instance.connection._sentry_span
132
+ span = getattr(instance.connection, "_sentry_span", None)
133
133
 
134
- _set_db_data(span, instance.connection)
134
+ if span is not None:
135
+ _set_db_data(span, instance.connection)
135
136
 
136
- if should_send_default_pii():
137
- db_params = span._data.get("db.params", [])
138
- db_params.extend(data)
139
- span.set_data("db.params", db_params)
137
+ if should_send_default_pii():
138
+ db_params = span._data.get("db.params", [])
139
+ db_params.extend(data)
140
+ span.set_data("db.params", db_params)
140
141
 
141
142
  return f(*args, **kwargs)
142
143
 
@@ -22,7 +22,11 @@ from sentry_sdk.utils import (
22
22
  try:
23
23
  from cohere.client import Client
24
24
  from cohere.base_client import BaseCohere
25
- from cohere import ChatStreamEndEvent, NonStreamedChatResponse
25
+ from cohere import (
26
+ ChatStreamEndEvent,
27
+ NonStreamedChatResponse,
28
+ StreamedChatResponse_StreamEnd,
29
+ )
26
30
 
27
31
  if TYPE_CHECKING:
28
32
  from cohere import StreamedChatResponse
@@ -181,7 +185,9 @@ def _wrap_chat(f, streaming):
181
185
 
182
186
  with capture_internal_exceptions():
183
187
  for x in old_iterator:
184
- if isinstance(x, ChatStreamEndEvent):
188
+ if isinstance(x, ChatStreamEndEvent) or isinstance(
189
+ x, StreamedChatResponse_StreamEnd
190
+ ):
185
191
  collect_chat_response_fields(
186
192
  span,
187
193
  x.response,
@@ -104,6 +104,16 @@ TRANSACTION_STYLE_VALUES = ("function_name", "url")
104
104
 
105
105
 
106
106
  class DjangoIntegration(Integration):
107
+ """
108
+ Auto instrument a Django application.
109
+
110
+ :param transaction_style: How to derive transaction names. Either `"function_name"` or `"url"`. Defaults to `"url"`.
111
+ :param middleware_spans: Whether to create spans for middleware. Defaults to `True`.
112
+ :param signals_spans: Whether to create spans for signals. Defaults to `True`.
113
+ :param signals_denylist: A list of signals to ignore when creating spans.
114
+ :param cache_spans: Whether to create spans for cache operations. Defaults to `False`.
115
+ """
116
+
107
117
  identifier = "django"
108
118
 
109
119
  transaction_style = ""
@@ -128,10 +138,12 @@ class DjangoIntegration(Integration):
128
138
  )
129
139
  self.transaction_style = transaction_style
130
140
  self.middleware_spans = middleware_spans
141
+
131
142
  self.signals_spans = signals_spans
132
- self.cache_spans = cache_spans
133
143
  self.signals_denylist = signals_denylist or []
134
144
 
145
+ self.cache_spans = cache_spans
146
+
135
147
  @staticmethod
136
148
  def setup_once():
137
149
  # type: () -> None
@@ -0,0 +1,176 @@
1
+ import functools
2
+ from typing import TYPE_CHECKING
3
+ from sentry_sdk.integrations.redis.utils import _get_safe_key
4
+ from urllib3.util import parse_url as urlparse
5
+
6
+ from django import VERSION as DJANGO_VERSION
7
+ from django.core.cache import CacheHandler
8
+
9
+ import sentry_sdk
10
+ from sentry_sdk.consts import OP, SPANDATA
11
+ from sentry_sdk.utils import (
12
+ capture_internal_exceptions,
13
+ ensure_integration_enabled,
14
+ )
15
+
16
+
17
+ if TYPE_CHECKING:
18
+ from typing import Any
19
+ from typing import Callable
20
+ from typing import Optional
21
+
22
+
23
+ METHODS_TO_INSTRUMENT = [
24
+ "set",
25
+ "set_many",
26
+ "get",
27
+ "get_many",
28
+ ]
29
+
30
+
31
+ def _get_span_description(method_name, args, kwargs):
32
+ # type: (str, tuple[Any], dict[str, Any]) -> str
33
+ return _get_safe_key(method_name, args, kwargs)
34
+
35
+
36
+ def _patch_cache_method(cache, method_name, address, port):
37
+ # type: (CacheHandler, str, Optional[str], Optional[int]) -> None
38
+ from sentry_sdk.integrations.django import DjangoIntegration
39
+
40
+ original_method = getattr(cache, method_name)
41
+
42
+ @ensure_integration_enabled(DjangoIntegration, original_method)
43
+ def _instrument_call(
44
+ cache, method_name, original_method, args, kwargs, address, port
45
+ ):
46
+ # type: (CacheHandler, str, Callable[..., Any], tuple[Any, ...], dict[str, Any], Optional[str], Optional[int]) -> Any
47
+ is_set_operation = method_name.startswith("set")
48
+ is_get_operation = not is_set_operation
49
+
50
+ op = OP.CACHE_PUT if is_set_operation else OP.CACHE_GET
51
+ description = _get_span_description(method_name, args, kwargs)
52
+
53
+ with sentry_sdk.start_span(op=op, description=description) as span:
54
+ value = original_method(*args, **kwargs)
55
+
56
+ with capture_internal_exceptions():
57
+ if address is not None:
58
+ span.set_data(SPANDATA.NETWORK_PEER_ADDRESS, address)
59
+
60
+ if port is not None:
61
+ span.set_data(SPANDATA.NETWORK_PEER_PORT, port)
62
+
63
+ key = _get_safe_key(method_name, args, kwargs)
64
+ if key != "":
65
+ span.set_data(SPANDATA.CACHE_KEY, key)
66
+
67
+ item_size = None
68
+ if is_get_operation:
69
+ if value:
70
+ item_size = len(str(value))
71
+ span.set_data(SPANDATA.CACHE_HIT, True)
72
+ else:
73
+ span.set_data(SPANDATA.CACHE_HIT, False)
74
+ else:
75
+ try:
76
+ # 'set' command
77
+ item_size = len(str(args[1]))
78
+ except IndexError:
79
+ # 'set_many' command
80
+ item_size = len(str(args[0]))
81
+
82
+ if item_size is not None:
83
+ span.set_data(SPANDATA.CACHE_ITEM_SIZE, item_size)
84
+
85
+ return value
86
+
87
+ @functools.wraps(original_method)
88
+ def sentry_method(*args, **kwargs):
89
+ # type: (*Any, **Any) -> Any
90
+ return _instrument_call(
91
+ cache, method_name, original_method, args, kwargs, address, port
92
+ )
93
+
94
+ setattr(cache, method_name, sentry_method)
95
+
96
+
97
+ def _patch_cache(cache, address=None, port=None):
98
+ # type: (CacheHandler, Optional[str], Optional[int]) -> None
99
+ if not hasattr(cache, "_sentry_patched"):
100
+ for method_name in METHODS_TO_INSTRUMENT:
101
+ _patch_cache_method(cache, method_name, address, port)
102
+ cache._sentry_patched = True
103
+
104
+
105
+ def _get_address_port(settings):
106
+ # type: (dict[str, Any]) -> tuple[Optional[str], Optional[int]]
107
+ location = settings.get("LOCATION")
108
+
109
+ # TODO: location can also be an array of locations
110
+ # see: https://docs.djangoproject.com/en/5.0/topics/cache/#redis
111
+ # GitHub issue: https://github.com/getsentry/sentry-python/issues/3062
112
+ if not isinstance(location, str):
113
+ return None, None
114
+
115
+ if "://" in location:
116
+ parsed_url = urlparse(location)
117
+ # remove the username and password from URL to not leak sensitive data.
118
+ address = "{}://{}{}".format(
119
+ parsed_url.scheme or "",
120
+ parsed_url.hostname or "",
121
+ parsed_url.path or "",
122
+ )
123
+ port = parsed_url.port
124
+ else:
125
+ address = location
126
+ port = None
127
+
128
+ return address, int(port) if port is not None else None
129
+
130
+
131
+ def patch_caching():
132
+ # type: () -> None
133
+ from sentry_sdk.integrations.django import DjangoIntegration
134
+
135
+ if not hasattr(CacheHandler, "_sentry_patched"):
136
+ if DJANGO_VERSION < (3, 2):
137
+ original_get_item = CacheHandler.__getitem__
138
+
139
+ @functools.wraps(original_get_item)
140
+ def sentry_get_item(self, alias):
141
+ # type: (CacheHandler, str) -> Any
142
+ cache = original_get_item(self, alias)
143
+
144
+ integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
145
+ if integration is not None and integration.cache_spans:
146
+ from django.conf import settings
147
+
148
+ address, port = _get_address_port(
149
+ settings.CACHES[alias or "default"]
150
+ )
151
+
152
+ _patch_cache(cache, address, port)
153
+
154
+ return cache
155
+
156
+ CacheHandler.__getitem__ = sentry_get_item
157
+ CacheHandler._sentry_patched = True
158
+
159
+ else:
160
+ original_create_connection = CacheHandler.create_connection
161
+
162
+ @functools.wraps(original_create_connection)
163
+ def sentry_create_connection(self, alias):
164
+ # type: (CacheHandler, str) -> Any
165
+ cache = original_create_connection(self, alias)
166
+
167
+ integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
168
+ if integration is not None and integration.cache_spans:
169
+ address, port = _get_address_port(self.settings[alias or "default"])
170
+
171
+ _patch_cache(cache, address, port)
172
+
173
+ return cache
174
+
175
+ CacheHandler.create_connection = sentry_create_connection
176
+ CacheHandler._sentry_patched = True
@@ -0,0 +1,37 @@
1
+ from sentry_sdk._types import TYPE_CHECKING
2
+ from sentry_sdk.integrations import Integration, DidNotEnable
3
+ from sentry_sdk.integrations.redis.consts import _DEFAULT_MAX_DATA_SIZE
4
+ from sentry_sdk.integrations.redis.rb import _patch_rb
5
+ from sentry_sdk.integrations.redis.redis import _patch_redis
6
+ from sentry_sdk.integrations.redis.redis_cluster import _patch_redis_cluster
7
+ from sentry_sdk.integrations.redis.redis_py_cluster_legacy import _patch_rediscluster
8
+ from sentry_sdk.utils import logger
9
+
10
+ if TYPE_CHECKING:
11
+ from typing import Optional
12
+
13
+
14
+ class RedisIntegration(Integration):
15
+ identifier = "redis"
16
+
17
+ def __init__(self, max_data_size=_DEFAULT_MAX_DATA_SIZE, cache_prefixes=None):
18
+ # type: (int, Optional[list[str]]) -> None
19
+ self.max_data_size = max_data_size
20
+ self.cache_prefixes = cache_prefixes if cache_prefixes is not None else []
21
+
22
+ @staticmethod
23
+ def setup_once():
24
+ # type: () -> None
25
+ try:
26
+ from redis import StrictRedis, client
27
+ except ImportError:
28
+ raise DidNotEnable("Redis client not installed")
29
+
30
+ _patch_redis(StrictRedis, client)
31
+ _patch_redis_cluster()
32
+ _patch_rb()
33
+
34
+ try:
35
+ _patch_rediscluster()
36
+ except Exception:
37
+ logger.exception("Error occurred while patching `rediscluster` library")
@@ -1,16 +1,18 @@
1
- import sentry_sdk
1
+ from sentry_sdk._types import TYPE_CHECKING
2
2
  from sentry_sdk.consts import OP
3
- from sentry_sdk.integrations.redis import (
4
- RedisIntegration,
5
- _get_span_description,
3
+ from sentry_sdk.integrations.redis.modules.caches import (
4
+ _compile_cache_span_properties,
5
+ _set_cache_data,
6
+ )
7
+ from sentry_sdk.integrations.redis.modules.queries import _compile_db_span_properties
8
+ from sentry_sdk.integrations.redis.utils import (
6
9
  _set_client_data,
7
10
  _set_pipeline_data,
8
11
  )
9
- from sentry_sdk._types import TYPE_CHECKING
10
12
  from sentry_sdk.tracing import Span
11
- from sentry_sdk.utils import (
12
- capture_internal_exceptions,
13
- )
13
+ from sentry_sdk.utils import capture_internal_exceptions
14
+ import sentry_sdk
15
+
14
16
 
15
17
  if TYPE_CHECKING:
16
18
  from collections.abc import Callable
@@ -25,6 +27,8 @@ def patch_redis_async_pipeline(
25
27
  # type: (Union[type[Pipeline[Any]], type[ClusterPipeline[Any]]], bool, Any, Callable[[Span, Any], None]) -> None
26
28
  old_execute = pipeline_cls.execute
27
29
 
30
+ from sentry_sdk.integrations.redis import RedisIntegration
31
+
28
32
  async def _sentry_execute(self, *args, **kwargs):
29
33
  # type: (Any, *Any, **Any) -> Any
30
34
  if sentry_sdk.get_client().get_integration(RedisIntegration) is None:
@@ -52,17 +56,48 @@ def patch_redis_async_client(cls, is_cluster, set_db_data_fn):
52
56
  # type: (Union[type[StrictRedis[Any]], type[RedisCluster[Any]]], bool, Callable[[Span, Any], None]) -> None
53
57
  old_execute_command = cls.execute_command
54
58
 
59
+ from sentry_sdk.integrations.redis import RedisIntegration
60
+
55
61
  async def _sentry_execute_command(self, name, *args, **kwargs):
56
62
  # type: (Any, str, *Any, **Any) -> Any
57
- if sentry_sdk.get_client().get_integration(RedisIntegration) is None:
63
+ integration = sentry_sdk.get_client().get_integration(RedisIntegration)
64
+ if integration is None:
58
65
  return await old_execute_command(self, name, *args, **kwargs)
59
66
 
60
- description = _get_span_description(name, *args)
67
+ cache_properties = _compile_cache_span_properties(
68
+ name,
69
+ args,
70
+ kwargs,
71
+ integration,
72
+ )
61
73
 
62
- with sentry_sdk.start_span(op=OP.DB_REDIS, description=description) as span:
63
- set_db_data_fn(span, self)
64
- _set_client_data(span, is_cluster, name, *args)
74
+ cache_span = None
75
+ if cache_properties["is_cache_key"] and cache_properties["op"] is not None:
76
+ cache_span = sentry_sdk.start_span(
77
+ op=cache_properties["op"],
78
+ description=cache_properties["description"],
79
+ )
80
+ cache_span.__enter__()
65
81
 
66
- return await old_execute_command(self, name, *args, **kwargs)
82
+ db_properties = _compile_db_span_properties(integration, name, args)
83
+
84
+ db_span = sentry_sdk.start_span(
85
+ op=db_properties["op"],
86
+ description=db_properties["description"],
87
+ )
88
+ db_span.__enter__()
89
+
90
+ set_db_data_fn(db_span, self)
91
+ _set_client_data(db_span, is_cluster, name, *args)
92
+
93
+ value = await old_execute_command(self, name, *args, **kwargs)
94
+
95
+ db_span.__exit__(None, None, None)
96
+
97
+ if cache_span:
98
+ _set_cache_data(cache_span, self, cache_properties, value)
99
+ cache_span.__exit__(None, None, None)
100
+
101
+ return value
67
102
 
68
103
  cls.execute_command = _sentry_execute_command # type: ignore
@@ -0,0 +1,108 @@
1
+ from sentry_sdk._types import TYPE_CHECKING
2
+ from sentry_sdk.consts import OP
3
+ from sentry_sdk.integrations.redis.modules.caches import (
4
+ _compile_cache_span_properties,
5
+ _set_cache_data,
6
+ )
7
+ from sentry_sdk.integrations.redis.modules.queries import _compile_db_span_properties
8
+ from sentry_sdk.integrations.redis.utils import (
9
+ _set_client_data,
10
+ _set_pipeline_data,
11
+ )
12
+ from sentry_sdk.tracing import Span
13
+ from sentry_sdk.utils import capture_internal_exceptions
14
+ import sentry_sdk
15
+
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Callable
19
+ from typing import Any
20
+
21
+
22
+ def patch_redis_pipeline(
23
+ pipeline_cls,
24
+ is_cluster,
25
+ get_command_args_fn,
26
+ set_db_data_fn,
27
+ ):
28
+ # type: (Any, bool, Any, Callable[[Span, Any], None]) -> None
29
+ old_execute = pipeline_cls.execute
30
+
31
+ from sentry_sdk.integrations.redis import RedisIntegration
32
+
33
+ def sentry_patched_execute(self, *args, **kwargs):
34
+ # type: (Any, *Any, **Any) -> Any
35
+ if sentry_sdk.get_client().get_integration(RedisIntegration) is None:
36
+ return old_execute(self, *args, **kwargs)
37
+
38
+ with sentry_sdk.start_span(
39
+ op=OP.DB_REDIS, description="redis.pipeline.execute"
40
+ ) as span:
41
+ with capture_internal_exceptions():
42
+ set_db_data_fn(span, self)
43
+ _set_pipeline_data(
44
+ span,
45
+ is_cluster,
46
+ get_command_args_fn,
47
+ False if is_cluster else self.transaction,
48
+ self.command_stack,
49
+ )
50
+
51
+ return old_execute(self, *args, **kwargs)
52
+
53
+ pipeline_cls.execute = sentry_patched_execute
54
+
55
+
56
+ def patch_redis_client(cls, is_cluster, set_db_data_fn):
57
+ # type: (Any, bool, Callable[[Span, Any], None]) -> None
58
+ """
59
+ This function can be used to instrument custom redis client classes or
60
+ subclasses.
61
+ """
62
+ old_execute_command = cls.execute_command
63
+
64
+ from sentry_sdk.integrations.redis import RedisIntegration
65
+
66
+ def sentry_patched_execute_command(self, name, *args, **kwargs):
67
+ # type: (Any, str, *Any, **Any) -> Any
68
+ integration = sentry_sdk.get_client().get_integration(RedisIntegration)
69
+ if integration is None:
70
+ return old_execute_command(self, name, *args, **kwargs)
71
+
72
+ cache_properties = _compile_cache_span_properties(
73
+ name,
74
+ args,
75
+ kwargs,
76
+ integration,
77
+ )
78
+
79
+ cache_span = None
80
+ if cache_properties["is_cache_key"] and cache_properties["op"] is not None:
81
+ cache_span = sentry_sdk.start_span(
82
+ op=cache_properties["op"],
83
+ description=cache_properties["description"],
84
+ )
85
+ cache_span.__enter__()
86
+
87
+ db_properties = _compile_db_span_properties(integration, name, args)
88
+
89
+ db_span = sentry_sdk.start_span(
90
+ op=db_properties["op"],
91
+ description=db_properties["description"],
92
+ )
93
+ db_span.__enter__()
94
+
95
+ set_db_data_fn(db_span, self)
96
+ _set_client_data(db_span, is_cluster, name, *args)
97
+
98
+ value = old_execute_command(self, name, *args, **kwargs)
99
+
100
+ db_span.__exit__(None, None, None)
101
+
102
+ if cache_span:
103
+ _set_cache_data(cache_span, self, cache_properties, value)
104
+ cache_span.__exit__(None, None, None)
105
+
106
+ return value
107
+
108
+ cls.execute_command = sentry_patched_execute_command
@@ -0,0 +1,17 @@
1
+ _SINGLE_KEY_COMMANDS = frozenset(
2
+ ["decr", "decrby", "get", "incr", "incrby", "pttl", "set", "setex", "setnx", "ttl"],
3
+ )
4
+ _MULTI_KEY_COMMANDS = frozenset(
5
+ [
6
+ "del",
7
+ "touch",
8
+ "unlink",
9
+ "mget",
10
+ ],
11
+ )
12
+ _COMMANDS_INCLUDING_SENSITIVE_DATA = [
13
+ "auth",
14
+ ]
15
+ _MAX_NUM_ARGS = 10 # Trim argument lists to this many values
16
+ _MAX_NUM_COMMANDS = 10 # Trim command lists to this many values
17
+ _DEFAULT_MAX_DATA_SIZE = 1024