sentry-sdk 3.0.0a5__tar.gz → 3.0.0a6__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.

Potentially problematic release.


This version of sentry-sdk might be problematic. Click here for more details.

Files changed (206) hide show
  1. {sentry_sdk-3.0.0a5/sentry_sdk.egg-info → sentry_sdk-3.0.0a6}/PKG-INFO +3 -1
  2. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/pyproject.toml +4 -0
  3. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/ai/utils.py +7 -8
  4. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/api.py +13 -2
  5. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/client.py +93 -17
  6. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/consts.py +14 -6
  7. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/crons/api.py +5 -0
  8. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/anthropic.py +133 -73
  9. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/asgi.py +10 -9
  10. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/asyncio.py +85 -20
  11. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/clickhouse_driver.py +55 -28
  12. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/fastapi.py +1 -7
  13. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/gnu_backtrace.py +6 -3
  14. sentry_sdk-3.0.0a6/sentry_sdk/integrations/langchain.py +806 -0
  15. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/litestar.py +1 -1
  16. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/patches/agent_run.py +0 -2
  17. sentry_sdk-3.0.0a6/sentry_sdk/integrations/openai_agents/patches/runner.py +45 -0
  18. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/quart.py +1 -1
  19. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/starlette.py +1 -5
  20. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/starlite.py +2 -2
  21. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/scope.py +11 -11
  22. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/tracing.py +94 -17
  23. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/tracing_utils.py +330 -33
  24. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/transport.py +357 -62
  25. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/utils.py +23 -5
  26. sentry_sdk-3.0.0a6/sentry_sdk/worker.py +323 -0
  27. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6/sentry_sdk.egg-info}/PKG-INFO +3 -1
  28. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk.egg-info/requires.txt +3 -0
  29. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/setup.py +2 -1
  30. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_client.py +335 -1
  31. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_transport.py +298 -0
  32. sentry_sdk-3.0.0a5/sentry_sdk/integrations/langchain.py +0 -562
  33. sentry_sdk-3.0.0a5/sentry_sdk/integrations/openai_agents/patches/runner.py +0 -42
  34. sentry_sdk-3.0.0a5/sentry_sdk/worker.py +0 -129
  35. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/LICENSE +0 -0
  36. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/MANIFEST.in +0 -0
  37. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/README.md +0 -0
  38. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/__init__.py +0 -0
  39. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/_compat.py +0 -0
  40. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/_init_implementation.py +0 -0
  41. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/_log_batcher.py +0 -0
  42. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/_lru_cache.py +0 -0
  43. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/_queue.py +0 -0
  44. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/_types.py +0 -0
  45. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/_werkzeug.py +0 -0
  46. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/ai/__init__.py +0 -0
  47. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/ai/monitoring.py +0 -0
  48. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/attachments.py +0 -0
  49. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/crons/__init__.py +0 -0
  50. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/crons/consts.py +0 -0
  51. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/crons/decorator.py +0 -0
  52. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/debug.py +0 -0
  53. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/envelope.py +0 -0
  54. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/feature_flags.py +0 -0
  55. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/__init__.py +0 -0
  56. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/_asgi_common.py +0 -0
  57. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/_wsgi_common.py +0 -0
  58. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/aiohttp.py +0 -0
  59. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/argv.py +0 -0
  60. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/ariadne.py +0 -0
  61. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/arq.py +0 -0
  62. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/asyncpg.py +0 -0
  63. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/atexit.py +0 -0
  64. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/aws_lambda.py +0 -0
  65. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/beam.py +0 -0
  66. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/boto3.py +0 -0
  67. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/bottle.py +0 -0
  68. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/celery/__init__.py +0 -0
  69. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/celery/beat.py +0 -0
  70. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/celery/utils.py +0 -0
  71. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/chalice.py +0 -0
  72. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/cloud_resource_context.py +0 -0
  73. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/cohere.py +0 -0
  74. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/dedupe.py +0 -0
  75. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/__init__.py +0 -0
  76. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/asgi.py +0 -0
  77. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/caching.py +0 -0
  78. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/middleware.py +0 -0
  79. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/signals_handlers.py +0 -0
  80. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/templates.py +0 -0
  81. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/transactions.py +0 -0
  82. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/django/views.py +0 -0
  83. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/dramatiq.py +0 -0
  84. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/excepthook.py +0 -0
  85. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/executing.py +0 -0
  86. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/falcon.py +0 -0
  87. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/flask.py +0 -0
  88. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/gcp.py +0 -0
  89. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/gql.py +0 -0
  90. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/graphene.py +0 -0
  91. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/grpc/__init__.py +0 -0
  92. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/grpc/aio/__init__.py +0 -0
  93. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/grpc/aio/client.py +0 -0
  94. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/grpc/aio/server.py +0 -0
  95. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/grpc/client.py +0 -0
  96. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/grpc/consts.py +0 -0
  97. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/grpc/server.py +0 -0
  98. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/httpx.py +0 -0
  99. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/huey.py +0 -0
  100. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/huggingface_hub.py +0 -0
  101. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/launchdarkly.py +0 -0
  102. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/logging.py +0 -0
  103. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/loguru.py +0 -0
  104. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/modules.py +0 -0
  105. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai.py +0 -0
  106. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/__init__.py +0 -0
  107. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/consts.py +0 -0
  108. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/patches/__init__.py +0 -0
  109. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/patches/models.py +0 -0
  110. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/patches/tools.py +0 -0
  111. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/spans/__init__.py +0 -0
  112. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +0 -0
  113. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/spans/ai_client.py +0 -0
  114. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/spans/execute_tool.py +0 -0
  115. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/spans/handoff.py +0 -0
  116. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +0 -0
  117. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openai_agents/utils.py +0 -0
  118. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/openfeature.py +0 -0
  119. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/pure_eval.py +0 -0
  120. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/pymongo.py +0 -0
  121. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/pyramid.py +0 -0
  122. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/ray.py +0 -0
  123. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/__init__.py +0 -0
  124. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/_async_common.py +0 -0
  125. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/_sync_common.py +0 -0
  126. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/consts.py +0 -0
  127. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/modules/__init__.py +0 -0
  128. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/modules/caches.py +0 -0
  129. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/modules/queries.py +0 -0
  130. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/rb.py +0 -0
  131. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/redis.py +0 -0
  132. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/redis_cluster.py +0 -0
  133. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +0 -0
  134. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/redis/utils.py +0 -0
  135. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/rq.py +0 -0
  136. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/rust_tracing.py +0 -0
  137. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/sanic.py +0 -0
  138. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/serverless.py +0 -0
  139. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/socket.py +0 -0
  140. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/spark/__init__.py +0 -0
  141. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/spark/spark_driver.py +0 -0
  142. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/spark/spark_worker.py +0 -0
  143. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/sqlalchemy.py +0 -0
  144. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/statsig.py +0 -0
  145. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/stdlib.py +0 -0
  146. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/strawberry.py +0 -0
  147. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/sys_exit.py +0 -0
  148. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/threading.py +0 -0
  149. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/tornado.py +0 -0
  150. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/trytond.py +0 -0
  151. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/typer.py +0 -0
  152. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/unleash.py +0 -0
  153. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/integrations/wsgi.py +0 -0
  154. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/logger.py +0 -0
  155. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/monitor.py +0 -0
  156. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/__init__.py +0 -0
  157. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/consts.py +0 -0
  158. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/contextvars_context.py +0 -0
  159. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/propagator.py +0 -0
  160. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/sampler.py +0 -0
  161. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/scope.py +0 -0
  162. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/span_processor.py +0 -0
  163. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/tracing.py +0 -0
  164. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/opentelemetry/utils.py +0 -0
  165. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/profiler/__init__.py +0 -0
  166. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/profiler/continuous_profiler.py +0 -0
  167. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/profiler/transaction_profiler.py +0 -0
  168. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/profiler/utils.py +0 -0
  169. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/py.typed +0 -0
  170. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/scrubber.py +0 -0
  171. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/serializer.py +0 -0
  172. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/session.py +0 -0
  173. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/sessions.py +0 -0
  174. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/spotlight.py +0 -0
  175. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk/types.py +0 -0
  176. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk.egg-info/SOURCES.txt +0 -0
  177. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk.egg-info/dependency_links.txt +0 -0
  178. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk.egg-info/entry_points.txt +0 -0
  179. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk.egg-info/not-zip-safe +0 -0
  180. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/sentry_sdk.egg-info/top_level.txt +0 -0
  181. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/setup.cfg +0 -0
  182. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_ai_monitoring.py +0 -0
  183. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_api.py +0 -0
  184. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_basics.py +0 -0
  185. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_breadcrumbs.py +0 -0
  186. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_conftest.py +0 -0
  187. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_crons.py +0 -0
  188. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_dsc.py +0 -0
  189. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_envelope.py +0 -0
  190. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_exceptiongroup.py +0 -0
  191. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_feature_flags.py +0 -0
  192. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_full_stack_frames.py +0 -0
  193. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_gevent.py +0 -0
  194. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_import.py +0 -0
  195. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_logs.py +0 -0
  196. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_lru_cache.py +0 -0
  197. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_monitor.py +0 -0
  198. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_propagationcontext.py +0 -0
  199. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_scope.py +0 -0
  200. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_scrubber.py +0 -0
  201. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_serializer.py +0 -0
  202. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_sessions.py +0 -0
  203. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_spotlight.py +0 -0
  204. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_tracing_utils.py +0 -0
  205. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_types.py +0 -0
  206. {sentry_sdk-3.0.0a5 → sentry_sdk-3.0.0a6}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentry-sdk
3
- Version: 3.0.0a5
3
+ Version: 3.0.0a6
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
@@ -64,6 +64,8 @@ Requires-Dist: grpcio>=1.21.1; extra == "grpcio"
64
64
  Requires-Dist: protobuf>=3.8.0; extra == "grpcio"
65
65
  Provides-Extra: http2
66
66
  Requires-Dist: httpcore[http2]==1.*; extra == "http2"
67
+ Provides-Extra: asyncio
68
+ Requires-Dist: httpcore[asyncio]==1.*; extra == "asyncio"
67
69
  Provides-Extra: httpx
68
70
  Requires-Dist: httpx>=0.16.0; extra == "httpx"
69
71
  Provides-Extra: huey
@@ -126,6 +126,10 @@ ignore_missing_imports = true
126
126
  module = "langchain_core.*"
127
127
  ignore_missing_imports = true
128
128
 
129
+ [[tool.mypy.overrides]]
130
+ module = "langchain.*"
131
+ ignore_missing_imports = true
132
+
129
133
  [[tool.mypy.overrides]]
130
134
  module = "executing.*"
131
135
  ignore_missing_imports = true
@@ -8,8 +8,7 @@ from sentry_sdk.tracing import Span
8
8
  from sentry_sdk.utils import logger
9
9
 
10
10
 
11
- def _normalize_data(data: Any) -> Any:
12
-
11
+ def _normalize_data(data: Any, unpack: bool = True) -> Any:
13
12
  # convert pydantic data (e.g. OpenAI v1+) to json compatible format
14
13
  if hasattr(data, "model_dump"):
15
14
  try:
@@ -18,17 +17,17 @@ def _normalize_data(data: Any) -> Any:
18
17
  logger.warning("Could not convert pydantic data to JSON: %s", e)
19
18
  return data
20
19
  if isinstance(data, list):
21
- if len(data) == 1:
22
- return _normalize_data(data[0]) # remove empty dimensions
23
- return list(_normalize_data(x) for x in data)
20
+ if unpack and len(data) == 1:
21
+ return _normalize_data(data[0], unpack=unpack) # remove empty dimensions
22
+ return list(_normalize_data(x, unpack=unpack) for x in data)
24
23
  if isinstance(data, dict):
25
- return {k: _normalize_data(v) for (k, v) in data.items()}
24
+ return {k: _normalize_data(v, unpack=unpack) for (k, v) in data.items()}
26
25
 
27
26
  return data
28
27
 
29
28
 
30
- def set_data_normalized(span: Span, key: str, value: Any) -> None:
31
- normalized = _normalize_data(value)
29
+ def set_data_normalized(span: Span, key: str, value: Any, unpack: bool = True) -> None:
30
+ normalized = _normalize_data(value, unpack=unpack)
32
31
  if isinstance(normalized, (int, float, bool, str)):
33
32
  span.set_attribute(key, normalized)
34
33
  else:
@@ -229,6 +229,14 @@ def flush(
229
229
  return get_client().flush(timeout=timeout, callback=callback)
230
230
 
231
231
 
232
+ @clientmethod
233
+ async def flush_async(
234
+ timeout: Optional[float] = None,
235
+ callback: Optional[Callable[[int, float], None]] = None,
236
+ ) -> None:
237
+ return await get_client().flush_async(timeout=timeout, callback=callback)
238
+
239
+
232
240
  def start_span(**kwargs: Any) -> Span:
233
241
  """
234
242
  Start and return a span.
@@ -344,8 +352,11 @@ def set_transaction_name(name: str, source: Optional[str] = None) -> None:
344
352
  return get_current_scope().set_transaction_name(name, source)
345
353
 
346
354
 
347
- def update_current_span(op=None, name=None, attributes=None):
348
- # type: (Optional[str], Optional[str], Optional[dict[str, Union[str, int, float, bool]]]) -> None
355
+ def update_current_span(
356
+ op: Optional[str] = None,
357
+ name: Optional[str] = None,
358
+ attributes: Optional[dict[str, Union[str, int, float, bool]]] = None,
359
+ ) -> None:
349
360
  """
350
361
  Update the current active span with the provided parameters.
351
362
 
@@ -25,7 +25,7 @@ from sentry_sdk.utils import (
25
25
  )
26
26
  from sentry_sdk.serializer import serialize
27
27
  from sentry_sdk.tracing import trace
28
- from sentry_sdk.transport import BaseHttpTransport, make_transport
28
+ from sentry_sdk.transport import HttpTransportCore, make_transport, AsyncHttpTransport
29
29
  from sentry_sdk.consts import (
30
30
  SPANDATA,
31
31
  DEFAULT_MAX_VALUE_LENGTH,
@@ -214,6 +214,12 @@ class BaseClient:
214
214
  def flush(self, *args: Any, **kwargs: Any) -> None:
215
215
  return None
216
216
 
217
+ async def close_async(self, *args: Any, **kwargs: Any) -> None:
218
+ return None
219
+
220
+ async def flush_async(self, *args: Any, **kwargs: Any) -> None:
221
+ return None
222
+
217
223
  def __enter__(self) -> BaseClient:
218
224
  return self
219
225
 
@@ -406,7 +412,7 @@ class _Client(BaseClient):
406
412
  self.monitor
407
413
  or self.log_batcher
408
414
  or has_profiling_enabled(self.options)
409
- or isinstance(self.transport, BaseHttpTransport)
415
+ or isinstance(self.transport, HttpTransportCore)
410
416
  ):
411
417
  # If we have anything on that could spawn a background thread, we
412
418
  # need to check if it's safe to use them.
@@ -442,12 +448,12 @@ class _Client(BaseClient):
442
448
 
443
449
  previous_total_spans: Optional[int] = None
444
450
  previous_total_breadcrumbs: Optional[int] = None
451
+ is_transaction = event.get("type") == "transaction"
445
452
 
446
453
  if event.get("timestamp") is None:
447
454
  event["timestamp"] = datetime.now(timezone.utc)
448
455
 
449
456
  if scope is not None:
450
- is_transaction = event.get("type") == "transaction"
451
457
  spans_before = len(event.get("spans", []))
452
458
  event_ = scope.apply_to_event(event, hint, self.options)
453
459
 
@@ -488,7 +494,8 @@ class _Client(BaseClient):
488
494
  )
489
495
 
490
496
  if (
491
- self.options["attach_stacktrace"]
497
+ not is_transaction
498
+ and self.options["attach_stacktrace"]
492
499
  and "exception" not in event
493
500
  and "stacktrace" not in event
494
501
  and "threads" not in event
@@ -917,6 +924,14 @@ class _Client(BaseClient):
917
924
 
918
925
  return self.integrations.get(integration_name)
919
926
 
927
+ def _close_components(self) -> None:
928
+ """Kill all client components in the correct order."""
929
+ self.session_flusher.kill()
930
+ if self.log_batcher is not None:
931
+ self.log_batcher.kill()
932
+ if self.monitor:
933
+ self.monitor.kill()
934
+
920
935
  def close(
921
936
  self,
922
937
  timeout: Optional[float] = None,
@@ -927,19 +942,43 @@ class _Client(BaseClient):
927
942
  semantics as :py:meth:`Client.flush`.
928
943
  """
929
944
  if self.transport is not None:
945
+ if isinstance(self.transport, AsyncHttpTransport) and hasattr(
946
+ self.transport, "loop"
947
+ ):
948
+ logger.debug(
949
+ "close() used with AsyncHttpTransport, aborting. Please use close_async() instead."
950
+ )
951
+ return
930
952
  self.flush(timeout=timeout, callback=callback)
931
-
932
- self.session_flusher.kill()
933
-
934
- if self.log_batcher is not None:
935
- self.log_batcher.kill()
936
-
937
- if self.monitor:
938
- self.monitor.kill()
939
-
953
+ self._close_components()
940
954
  self.transport.kill()
941
955
  self.transport = None
942
956
 
957
+ async def close_async(
958
+ self,
959
+ timeout: Optional[float] = None,
960
+ callback: Optional[Callable[[int, float], None]] = None,
961
+ ) -> None:
962
+ """
963
+ Asynchronously close the client and shut down the transport. Arguments have the same
964
+ semantics as :py:meth:`Client.flush_async`.
965
+ """
966
+ if self.transport is not None:
967
+ if not (
968
+ isinstance(self.transport, AsyncHttpTransport)
969
+ and hasattr(self.transport, "loop")
970
+ ):
971
+ logger.debug(
972
+ "close_async() used with non-async transport, aborting. Please use close() instead."
973
+ )
974
+ return
975
+ await self.flush_async(timeout=timeout, callback=callback)
976
+ self._close_components()
977
+ kill_task = self.transport.kill() # type: ignore
978
+ if kill_task is not None:
979
+ await kill_task
980
+ self.transport = None
981
+
943
982
  def flush(
944
983
  self,
945
984
  timeout: Optional[float] = None,
@@ -953,15 +992,52 @@ class _Client(BaseClient):
953
992
  :param callback: Is invoked with the number of pending events and the configured timeout.
954
993
  """
955
994
  if self.transport is not None:
995
+ if isinstance(self.transport, AsyncHttpTransport) and hasattr(
996
+ self.transport, "loop"
997
+ ):
998
+ logger.debug(
999
+ "flush() used with AsyncHttpTransport, aborting. Please use flush_async() instead."
1000
+ )
1001
+ return
956
1002
  if timeout is None:
957
1003
  timeout = self.options["shutdown_timeout"]
958
- self.session_flusher.flush()
959
-
960
- if self.log_batcher is not None:
961
- self.log_batcher.flush()
1004
+ self._flush_components()
962
1005
 
963
1006
  self.transport.flush(timeout=timeout, callback=callback)
964
1007
 
1008
+ async def flush_async(
1009
+ self,
1010
+ timeout: Optional[float] = None,
1011
+ callback: Optional[Callable[[int, float], None]] = None,
1012
+ ) -> None:
1013
+ """
1014
+ Asynchronously wait for the current events to be sent.
1015
+
1016
+ :param timeout: Wait for at most `timeout` seconds. If no `timeout` is provided, the `shutdown_timeout` option value is used.
1017
+
1018
+ :param callback: Is invoked with the number of pending events and the configured timeout.
1019
+ """
1020
+ if self.transport is not None:
1021
+ if not (
1022
+ isinstance(self.transport, AsyncHttpTransport)
1023
+ and hasattr(self.transport, "loop")
1024
+ ):
1025
+ logger.debug(
1026
+ "flush_async() used with non-async transport, aborting. Please use flush() instead."
1027
+ )
1028
+ return
1029
+ if timeout is None:
1030
+ timeout = self.options["shutdown_timeout"]
1031
+ self._flush_components()
1032
+ flush_task = self.transport.flush(timeout=timeout, callback=callback) # type: ignore
1033
+ if flush_task is not None:
1034
+ await flush_task
1035
+
1036
+ def _flush_components(self) -> None:
1037
+ self.session_flusher.flush()
1038
+ if self.log_batcher is not None:
1039
+ self.log_batcher.flush()
1040
+
965
1041
  def __enter__(self) -> _Client:
966
1042
  return self
967
1043
 
@@ -78,6 +78,7 @@ if TYPE_CHECKING:
78
78
  "transport_compression_algo": Optional[CompressionAlgo],
79
79
  "transport_num_pools": Optional[int],
80
80
  "transport_http2": Optional[bool],
81
+ "transport_async": Optional[bool],
81
82
  },
82
83
  total=False,
83
84
  )
@@ -95,6 +96,17 @@ FALSE_VALUES = [
95
96
  ]
96
97
 
97
98
 
99
+ class SPANTEMPLATE(str, Enum):
100
+ DEFAULT = "default"
101
+ AI_AGENT = "ai_agent"
102
+ AI_TOOL = "ai_tool"
103
+ AI_CHAT = "ai_chat"
104
+
105
+ def __str__(self):
106
+ # type: () -> str
107
+ return self.value
108
+
109
+
98
110
  class SPANDATA:
99
111
  """
100
112
  Additional information describing the type of the span.
@@ -792,6 +804,7 @@ class OP:
792
804
  GEN_AI_EMBEDDINGS = "gen_ai.embeddings"
793
805
  GEN_AI_EXECUTE_TOOL = "gen_ai.execute_tool"
794
806
  GEN_AI_HANDOFF = "gen_ai.handoff"
807
+ GEN_AI_PIPELINE = "gen_ai.pipeline"
795
808
  GEN_AI_INVOKE_AGENT = "gen_ai.invoke_agent"
796
809
  GEN_AI_RESPONSES = "gen_ai.responses"
797
810
  GRAPHQL_EXECUTE = "graphql.execute"
@@ -821,11 +834,6 @@ class OP:
821
834
  HUGGINGFACE_HUB_CHAT_COMPLETIONS_CREATE = (
822
835
  "ai.chat_completions.create.huggingface_hub"
823
836
  )
824
- LANGCHAIN_PIPELINE = "ai.pipeline.langchain"
825
- LANGCHAIN_RUN = "ai.run.langchain"
826
- LANGCHAIN_TOOL = "ai.tool.langchain"
827
- LANGCHAIN_AGENT = "ai.agent.langchain"
828
- LANGCHAIN_CHAT_COMPLETIONS_CREATE = "ai.chat_completions.create.langchain"
829
837
  QUEUE_PROCESS = "queue.process"
830
838
  QUEUE_PUBLISH = "queue.publish"
831
839
  QUEUE_SUBMIT_ARQ = "queue.submit.arq"
@@ -1381,4 +1389,4 @@ DEFAULT_OPTIONS = _get_default_options()
1381
1389
  del _get_default_options
1382
1390
 
1383
1391
 
1384
- VERSION = "3.0.0a5"
1392
+ VERSION = "3.0.0a6"
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
  import uuid
3
3
 
4
4
  import sentry_sdk
5
+ from sentry_sdk.utils import logger
5
6
 
6
7
  from typing import TYPE_CHECKING
7
8
 
@@ -53,4 +54,8 @@ def capture_checkin(
53
54
 
54
55
  sentry_sdk.capture_event(check_in_event)
55
56
 
57
+ logger.debug(
58
+ f"[Crons] Captured check-in ({check_in_event.get('check_in_id')}): {check_in_event.get('monitor_slug')} -> {check_in_event.get('status')}"
59
+ )
60
+
56
61
  return check_in_event["check_in_id"]
@@ -1,9 +1,11 @@
1
1
  from __future__ import annotations
2
2
  from functools import wraps
3
+ import json
3
4
  from typing import TYPE_CHECKING
4
5
 
5
6
  import sentry_sdk
6
7
  from sentry_sdk.ai.monitoring import record_token_usage
8
+ from sentry_sdk.ai.utils import set_data_normalized
7
9
  from sentry_sdk.consts import OP, SPANDATA
8
10
  from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration
9
11
  from sentry_sdk.scope import should_send_default_pii
@@ -11,9 +13,15 @@ from sentry_sdk.utils import (
11
13
  capture_internal_exceptions,
12
14
  event_from_exception,
13
15
  package_version,
16
+ safe_serialize,
14
17
  )
15
18
 
16
19
  try:
20
+ try:
21
+ from anthropic import NOT_GIVEN
22
+ except ImportError:
23
+ NOT_GIVEN = None
24
+
17
25
  from anthropic.resources import AsyncMessages, Messages
18
26
 
19
27
  if TYPE_CHECKING:
@@ -51,7 +59,10 @@ def _capture_exception(exc: Any) -> None:
51
59
  sentry_sdk.capture_event(event, hint=hint)
52
60
 
53
61
 
54
- def _calculate_token_usage(result: Messages, span: Span) -> None:
62
+ def _get_token_usage(result: Messages) -> tuple[int, int]:
63
+ """
64
+ Get token usage from the Anthropic response.
65
+ """
55
66
  input_tokens = 0
56
67
  output_tokens = 0
57
68
  if hasattr(result, "usage"):
@@ -61,40 +72,18 @@ def _calculate_token_usage(result: Messages, span: Span) -> None:
61
72
  if hasattr(usage, "output_tokens") and isinstance(usage.output_tokens, int):
62
73
  output_tokens = usage.output_tokens
63
74
 
64
- total_tokens = input_tokens + output_tokens
65
-
66
- record_token_usage(
67
- span,
68
- input_tokens=input_tokens,
69
- output_tokens=output_tokens,
70
- total_tokens=total_tokens,
71
- )
72
-
73
-
74
- def _get_responses(content: list[Any]) -> list[dict[str, Any]]:
75
- """
76
- Get JSON of a Anthropic responses.
77
- """
78
- responses = []
79
- for item in content:
80
- if hasattr(item, "text"):
81
- responses.append(
82
- {
83
- "type": item.type,
84
- "text": item.text,
85
- }
86
- )
87
- return responses
75
+ return input_tokens, output_tokens
88
76
 
89
77
 
90
78
  def _collect_ai_data(
91
79
  event: MessageStreamEvent,
80
+ model: str | None,
92
81
  input_tokens: int,
93
82
  output_tokens: int,
94
83
  content_blocks: list[str],
95
- ) -> tuple[int, int, list[str]]:
84
+ ) -> tuple[str | None, int, int, list[str]]:
96
85
  """
97
- Count token usage and collect content blocks from the AI streaming response.
86
+ Collect model information, token usage, and collect content blocks from the AI streaming response.
98
87
  """
99
88
  with capture_internal_exceptions():
100
89
  if hasattr(event, "type"):
@@ -102,6 +91,7 @@ def _collect_ai_data(
102
91
  usage = event.message.usage
103
92
  input_tokens += usage.input_tokens
104
93
  output_tokens += usage.output_tokens
94
+ model = event.message.model or model
105
95
  elif event.type == "content_block_start":
106
96
  pass
107
97
  elif event.type == "content_block_delta":
@@ -114,34 +104,80 @@ def _collect_ai_data(
114
104
  elif event.type == "message_delta":
115
105
  output_tokens += event.usage.output_tokens
116
106
 
117
- return input_tokens, output_tokens, content_blocks
107
+ return model, input_tokens, output_tokens, content_blocks
118
108
 
119
109
 
120
- def _add_ai_data_to_span(
110
+ def _set_input_data(
111
+ span: Span, kwargs: dict[str, Any], integration: AnthropicIntegration
112
+ ) -> None:
113
+ """
114
+ Set input data for the span based on the provided keyword arguments for the anthropic message creation.
115
+ """
116
+ messages = kwargs.get("messages")
117
+ if (
118
+ messages is not None
119
+ and len(messages) > 0
120
+ and should_send_default_pii()
121
+ and integration.include_prompts
122
+ ):
123
+ set_data_normalized(
124
+ span, SPANDATA.GEN_AI_REQUEST_MESSAGES, safe_serialize(messages)
125
+ )
126
+
127
+ set_data_normalized(
128
+ span, SPANDATA.GEN_AI_RESPONSE_STREAMING, kwargs.get("stream", False)
129
+ )
130
+
131
+ kwargs_keys_to_attributes = {
132
+ "max_tokens": SPANDATA.GEN_AI_REQUEST_MAX_TOKENS,
133
+ "model": SPANDATA.GEN_AI_REQUEST_MODEL,
134
+ "temperature": SPANDATA.GEN_AI_REQUEST_TEMPERATURE,
135
+ "top_k": SPANDATA.GEN_AI_REQUEST_TOP_K,
136
+ "top_p": SPANDATA.GEN_AI_REQUEST_TOP_P,
137
+ }
138
+ for key, attribute in kwargs_keys_to_attributes.items():
139
+ value = kwargs.get(key)
140
+ if value is not NOT_GIVEN and value is not None:
141
+ set_data_normalized(span, attribute, value)
142
+
143
+ # Input attributes: Tools
144
+ tools = kwargs.get("tools")
145
+ if tools is not NOT_GIVEN and tools is not None and len(tools) > 0:
146
+ set_data_normalized(
147
+ span, SPANDATA.GEN_AI_REQUEST_AVAILABLE_TOOLS, safe_serialize(tools)
148
+ )
149
+
150
+
151
+ def _set_output_data(
121
152
  span: Span,
122
153
  integration: AnthropicIntegration,
154
+ model: str | None,
123
155
  input_tokens: int,
124
156
  output_tokens: int,
125
- content_blocks: list[str],
157
+ content_blocks: list[Any],
158
+ finish_span: bool = False,
126
159
  ) -> None:
127
160
  """
128
- Add token usage and content blocks from the AI streaming response to the span.
129
- """
130
- with capture_internal_exceptions():
131
- if should_send_default_pii() and integration.include_prompts:
132
- complete_message = "".join(content_blocks)
133
- span.set_attribute(
134
- SPANDATA.AI_RESPONSES,
135
- [{"type": "text", "text": complete_message}],
136
- )
137
- total_tokens = input_tokens + output_tokens
138
- record_token_usage(
161
+ Set output data for the span based on the AI response."""
162
+ span.set_attribute(SPANDATA.GEN_AI_RESPONSE_MODEL, model)
163
+ if should_send_default_pii() and integration.include_prompts:
164
+ set_data_normalized(
139
165
  span,
140
- input_tokens=input_tokens,
141
- output_tokens=output_tokens,
142
- total_tokens=total_tokens,
166
+ SPANDATA.GEN_AI_RESPONSE_TEXT,
167
+ json.dumps(content_blocks),
168
+ unpack=False,
143
169
  )
144
- span.set_attribute(SPANDATA.AI_STREAMING, True)
170
+
171
+ record_token_usage(
172
+ span,
173
+ input_tokens=input_tokens,
174
+ output_tokens=output_tokens,
175
+ )
176
+
177
+ # TODO: GEN_AI_RESPONSE_TOOL_CALLS ?
178
+
179
+ if finish_span:
180
+ span.__exit__(None, None, None)
145
181
 
146
182
 
147
183
  def _sentry_patched_create_common(f: Any, *args: Any, **kwargs: Any) -> Any:
@@ -157,70 +193,94 @@ def _sentry_patched_create_common(f: Any, *args: Any, **kwargs: Any) -> Any:
157
193
  except TypeError:
158
194
  return f(*args, **kwargs)
159
195
 
196
+ model = kwargs.get("model", "")
197
+
160
198
  span = sentry_sdk.start_span(
161
- op=OP.ANTHROPIC_MESSAGES_CREATE,
162
- description="Anthropic messages create",
199
+ op=OP.GEN_AI_CHAT,
200
+ name=f"chat {model}".strip(),
163
201
  origin=AnthropicIntegration.origin,
164
202
  only_as_child_span=True,
165
203
  )
166
204
  span.__enter__()
167
205
 
168
- result = yield f, args, kwargs
206
+ _set_input_data(span, kwargs, integration)
169
207
 
170
- # add data to span and finish it
171
- messages = list(kwargs["messages"])
172
- model = kwargs.get("model")
208
+ result = yield f, args, kwargs
173
209
 
174
210
  with capture_internal_exceptions():
175
- span.set_attribute(SPANDATA.AI_MODEL_ID, model)
176
- span.set_attribute(SPANDATA.AI_STREAMING, False)
177
-
178
- if should_send_default_pii() and integration.include_prompts:
179
- span.set_attribute(SPANDATA.AI_INPUT_MESSAGES, messages)
180
-
181
211
  if hasattr(result, "content"):
182
- if should_send_default_pii() and integration.include_prompts:
183
- span.set_attribute(
184
- SPANDATA.AI_RESPONSES, _get_responses(result.content)
185
- )
186
- _calculate_token_usage(result, span)
187
- span.__exit__(None, None, None)
212
+ input_tokens, output_tokens = _get_token_usage(result)
213
+
214
+ content_blocks = []
215
+ for content_block in result.content:
216
+ if hasattr(content_block, "to_dict"):
217
+ content_blocks.append(content_block.to_dict())
218
+ elif hasattr(content_block, "model_dump"):
219
+ content_blocks.append(content_block.model_dump())
220
+ elif hasattr(content_block, "text"):
221
+ content_blocks.append({"type": "text", "text": content_block.text})
222
+
223
+ _set_output_data(
224
+ span=span,
225
+ integration=integration,
226
+ model=getattr(result, "model", None),
227
+ input_tokens=input_tokens,
228
+ output_tokens=output_tokens,
229
+ content_blocks=content_blocks,
230
+ finish_span=True,
231
+ )
188
232
 
189
233
  # Streaming response
190
234
  elif hasattr(result, "_iterator"):
191
235
  old_iterator = result._iterator
192
236
 
193
237
  def new_iterator() -> Iterator[MessageStreamEvent]:
238
+ model = None
194
239
  input_tokens = 0
195
240
  output_tokens = 0
196
241
  content_blocks: list[str] = []
197
242
 
198
243
  for event in old_iterator:
199
- input_tokens, output_tokens, content_blocks = _collect_ai_data(
200
- event, input_tokens, output_tokens, content_blocks
244
+ model, input_tokens, output_tokens, content_blocks = (
245
+ _collect_ai_data(
246
+ event, model, input_tokens, output_tokens, content_blocks
247
+ )
201
248
  )
202
249
  yield event
203
250
 
204
- _add_ai_data_to_span(
205
- span, integration, input_tokens, output_tokens, content_blocks
251
+ _set_output_data(
252
+ span=span,
253
+ integration=integration,
254
+ model=model,
255
+ input_tokens=input_tokens,
256
+ output_tokens=output_tokens,
257
+ content_blocks=[{"text": "".join(content_blocks), "type": "text"}],
258
+ finish_span=True,
206
259
  )
207
- span.__exit__(None, None, None)
208
260
 
209
261
  async def new_iterator_async() -> AsyncIterator[MessageStreamEvent]:
262
+ model = None
210
263
  input_tokens = 0
211
264
  output_tokens = 0
212
265
  content_blocks: list[str] = []
213
266
 
214
267
  async for event in old_iterator:
215
- input_tokens, output_tokens, content_blocks = _collect_ai_data(
216
- event, input_tokens, output_tokens, content_blocks
268
+ model, input_tokens, output_tokens, content_blocks = (
269
+ _collect_ai_data(
270
+ event, model, input_tokens, output_tokens, content_blocks
271
+ )
217
272
  )
218
273
  yield event
219
274
 
220
- _add_ai_data_to_span(
221
- span, integration, input_tokens, output_tokens, content_blocks
275
+ _set_output_data(
276
+ span=span,
277
+ integration=integration,
278
+ model=model,
279
+ input_tokens=input_tokens,
280
+ output_tokens=output_tokens,
281
+ content_blocks=[{"text": "".join(content_blocks), "type": "text"}],
282
+ finish_span=True,
222
283
  )
223
- span.__exit__(None, None, None)
224
284
 
225
285
  if str(type(result._iterator)) == "<class 'async_generator'>":
226
286
  result._iterator = new_iterator_async()