sentry-sdk 2.39.0__tar.gz → 2.41.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.
Potentially problematic release.
This version of sentry-sdk might be problematic. Click here for more details.
- {sentry_sdk-2.39.0/sentry_sdk.egg-info → sentry_sdk-2.41.0}/PKG-INFO +3 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/pyproject.toml +45 -38
- sentry_sdk-2.41.0/sentry_sdk/_metrics.py +81 -0
- sentry_sdk-2.41.0/sentry_sdk/_metrics_batcher.py +156 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/_types.py +27 -22
- sentry_sdk-2.41.0/sentry_sdk/ai/__init__.py +7 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/ai/utils.py +48 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/client.py +87 -36
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/consts.py +15 -9
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/envelope.py +31 -17
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/feature_flags.py +0 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/hub.py +17 -9
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/__init__.py +1 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/anthropic.py +10 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/asgi.py +3 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/dramatiq.py +89 -31
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/grpc/aio/client.py +2 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/grpc/client.py +3 -4
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/langchain.py +29 -5
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/langgraph.py +5 -3
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/launchdarkly.py +0 -1
- sentry_sdk-2.41.0/sentry_sdk/integrations/litellm.py +251 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/litestar.py +4 -4
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/logging.py +1 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/loguru.py +1 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai.py +3 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/spans/ai_client.py +4 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +10 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/utils.py +60 -19
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/pure_eval.py +3 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/spark/spark_driver.py +2 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/sqlalchemy.py +2 -6
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/starlette.py +1 -3
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/starlite.py +4 -4
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/threading.py +52 -8
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/wsgi.py +3 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/logger.py +1 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/profiler/utils.py +2 -6
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/scope.py +6 -3
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/serializer.py +1 -3
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/session.py +4 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/sessions.py +4 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/tracing.py +36 -33
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/tracing_utils.py +1 -3
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/transport.py +9 -26
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/types.py +3 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/utils.py +22 -4
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0/sentry_sdk.egg-info}/PKG-INFO +3 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk.egg-info/SOURCES.txt +3 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk.egg-info/requires.txt +3 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/setup.py +2 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_basics.py +3 -3
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_client.py +4 -6
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_conftest.py +6 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_envelope.py +0 -1
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_gevent.py +2 -4
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_logs.py +2 -1
- sentry_sdk-2.41.0/tests/test_metrics.py +208 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_propagationcontext.py +1 -2
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_transport.py +2 -115
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_utils.py +3 -3
- sentry_sdk-2.39.0/sentry_sdk/integrations/redis/modules/__init__.py +0 -0
- sentry_sdk-2.39.0/sentry_sdk/metrics.py +0 -965
- sentry_sdk-2.39.0/tests/test_metrics.py +0 -971
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/LICENSE +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/MANIFEST.in +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/README.md +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/_compat.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/_init_implementation.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/_log_batcher.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/_lru_cache.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/_queue.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/_werkzeug.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/ai/monitoring.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/api.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/attachments.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/crons/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/crons/api.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/crons/consts.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/crons/decorator.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/debug.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/_asgi_common.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/_wsgi_common.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/aiohttp.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/argv.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/ariadne.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/arq.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/asyncio.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/asyncpg.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/atexit.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/aws_lambda.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/beam.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/boto3.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/bottle.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/celery/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/celery/beat.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/celery/utils.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/chalice.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/clickhouse_driver.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/cloud_resource_context.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/cohere.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/dedupe.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/asgi.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/caching.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/middleware.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/signals_handlers.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/templates.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/transactions.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/django/views.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/excepthook.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/executing.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/falcon.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/fastapi.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/flask.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/gcp.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/gnu_backtrace.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/gql.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/graphene.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/grpc/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/grpc/aio/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/grpc/aio/server.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/grpc/consts.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/grpc/server.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/httpx.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/huey.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/huggingface_hub.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/modules.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/consts.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/patches/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/patches/agent_run.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/patches/models.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/patches/runner.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/patches/tools.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/spans/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/spans/execute_tool.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openai_agents/spans/handoff.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/openfeature.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/opentelemetry/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/opentelemetry/consts.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/opentelemetry/integration.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/opentelemetry/propagator.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/opentelemetry/span_processor.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/pymongo.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/pyramid.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/quart.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/ray.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/_async_common.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/_sync_common.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/consts.py +0 -0
- {sentry_sdk-2.39.0/sentry_sdk/ai → sentry_sdk-2.41.0/sentry_sdk/integrations/redis/modules}/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/modules/caches.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/modules/queries.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/rb.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/redis.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/redis_cluster.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/redis/utils.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/rq.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/rust_tracing.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/sanic.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/serverless.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/socket.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/spark/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/spark/spark_worker.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/statsig.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/stdlib.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/strawberry.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/sys_exit.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/tornado.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/trytond.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/typer.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/unleash.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/integrations/unraisablehook.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/monitor.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/profiler/__init__.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/profiler/continuous_profiler.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/profiler/transaction_profiler.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/py.typed +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/scrubber.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/spotlight.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk/worker.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk.egg-info/dependency_links.txt +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk.egg-info/entry_points.txt +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk.egg-info/not-zip-safe +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/sentry_sdk.egg-info/top_level.txt +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/setup.cfg +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_ai_monitoring.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_api.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_crons.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_dsc.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_exceptiongroup.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_feature_flags.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_full_stack_frames.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_import.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_lru_cache.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_monitor.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_scope.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_scrubber.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_serializer.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_sessions.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_spotlight.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_tracing_utils.py +0 -0
- {sentry_sdk-2.39.0 → sentry_sdk-2.41.0}/tests/test_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sentry-sdk
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.41.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
|
|
@@ -76,6 +76,8 @@ Provides-Extra: langgraph
|
|
|
76
76
|
Requires-Dist: langgraph>=0.6.6; extra == "langgraph"
|
|
77
77
|
Provides-Extra: launchdarkly
|
|
78
78
|
Requires-Dist: launchdarkly-server-sdk>=9.8.0; extra == "launchdarkly"
|
|
79
|
+
Provides-Extra: litellm
|
|
80
|
+
Requires-Dist: litellm>=1.77.5; extra == "litellm"
|
|
79
81
|
Provides-Extra: litestar
|
|
80
82
|
Requires-Dist: litestar>=2.0.0; extra == "litestar"
|
|
81
83
|
Provides-Extra: loguru
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Tool: Black
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
[tool.black]
|
|
6
|
-
# 'extend-exclude' excludes files or directories in addition to the defaults
|
|
7
|
-
extend-exclude = '''
|
|
8
|
-
# A regex preceded with ^/ will apply only to files and directories
|
|
9
|
-
# in the root of the project.
|
|
10
|
-
(
|
|
11
|
-
.*_pb2.py # exclude autogenerated Protocol Buffer files anywhere in the project
|
|
12
|
-
| .*_pb2_grpc.py # exclude autogenerated Protocol Buffer files anywhere in the project
|
|
13
|
-
)
|
|
14
|
-
'''
|
|
15
|
-
|
|
16
|
-
|
|
17
1
|
#
|
|
18
2
|
# Tool: Coverage
|
|
19
3
|
#
|
|
@@ -195,30 +179,53 @@ ignore_missing_imports = true
|
|
|
195
179
|
module = "agents.*"
|
|
196
180
|
ignore_missing_imports = true
|
|
197
181
|
|
|
182
|
+
[[tool.mypy.overrides]]
|
|
183
|
+
module = "dramatiq.*"
|
|
184
|
+
ignore_missing_imports = true
|
|
185
|
+
|
|
198
186
|
#
|
|
199
|
-
# Tool:
|
|
187
|
+
# Tool: Ruff (linting and formatting)
|
|
200
188
|
#
|
|
201
189
|
|
|
202
|
-
[tool.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
190
|
+
[tool.ruff]
|
|
191
|
+
# Target Python 3.7+ (minimum version supported by ruff)
|
|
192
|
+
target-version = "py37"
|
|
193
|
+
|
|
194
|
+
# Exclude files and directories
|
|
195
|
+
extend-exclude = [
|
|
196
|
+
"*_pb2.py", # Protocol Buffer files (covers all pb2 files including grpc_test_service_pb2.py)
|
|
197
|
+
"*_pb2_grpc.py", # Protocol Buffer files (covers all pb2_grpc files including grpc_test_service_pb2_grpc.py)
|
|
198
|
+
"checkouts", # From flake8
|
|
199
|
+
"lol*", # From flake8
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
[tool.ruff.lint]
|
|
203
|
+
# Match flake8's default rule selection exactly
|
|
204
|
+
# Flake8 by default only enables E and W (pycodestyle) + F (pyflakes)
|
|
205
|
+
select = [
|
|
206
|
+
"E", # pycodestyle errors (same as flake8 default)
|
|
207
|
+
"W", # pycodestyle warnings (same as flake8 default)
|
|
208
|
+
"F", # Pyflakes (same as flake8 default)
|
|
209
|
+
# Note: B and N rules are NOT enabled by default in flake8
|
|
210
|
+
# They were only active through the plugins, which may not have been fully enabled
|
|
218
211
|
]
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
212
|
+
|
|
213
|
+
# Use ONLY the same ignores as the original flake8 config + compatibility for this codebase
|
|
214
|
+
ignore = [
|
|
215
|
+
"E203", # Whitespace before ':'
|
|
216
|
+
"E501", # Line too long
|
|
217
|
+
"E402", # Module level import not at top of file
|
|
218
|
+
"E731", # Do not assign a lambda expression, use a def
|
|
219
|
+
"B014", # Redundant exception types
|
|
220
|
+
"N812", # Lowercase imported as non-lowercase
|
|
221
|
+
"N804", # First argument of classmethod should be named cls
|
|
222
|
+
|
|
223
|
+
# Additional ignores for codebase compatibility
|
|
224
|
+
"F401", # Unused imports - many in TYPE_CHECKING blocks used for type comments
|
|
225
|
+
"E721", # Use isinstance instead of type() == - existing pattern in this codebase
|
|
224
226
|
]
|
|
227
|
+
|
|
228
|
+
[tool.ruff.format]
|
|
229
|
+
# ruff format already excludes the same files as specified in extend-exclude
|
|
230
|
+
# Ensure Python 3.7 compatibility - avoid using Python 3.9+ syntax features
|
|
231
|
+
skip-magic-trailing-comma = false
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NOTE: This file contains experimental code that may be changed or removed at any
|
|
3
|
+
time without prior notice.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import time
|
|
7
|
+
from typing import Any, Optional, TYPE_CHECKING, Union
|
|
8
|
+
|
|
9
|
+
import sentry_sdk
|
|
10
|
+
from sentry_sdk.utils import safe_repr
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from sentry_sdk._types import Metric, MetricType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _capture_metric(
|
|
17
|
+
name, # type: str
|
|
18
|
+
metric_type, # type: MetricType
|
|
19
|
+
value, # type: float
|
|
20
|
+
unit=None, # type: Optional[str]
|
|
21
|
+
attributes=None, # type: Optional[dict[str, Any]]
|
|
22
|
+
):
|
|
23
|
+
# type: (...) -> None
|
|
24
|
+
client = sentry_sdk.get_client()
|
|
25
|
+
|
|
26
|
+
attrs = {} # type: dict[str, Union[str, bool, float, int]]
|
|
27
|
+
if attributes:
|
|
28
|
+
for k, v in attributes.items():
|
|
29
|
+
attrs[k] = (
|
|
30
|
+
v
|
|
31
|
+
if (
|
|
32
|
+
isinstance(v, str)
|
|
33
|
+
or isinstance(v, int)
|
|
34
|
+
or isinstance(v, bool)
|
|
35
|
+
or isinstance(v, float)
|
|
36
|
+
)
|
|
37
|
+
else safe_repr(v)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
metric = {
|
|
41
|
+
"timestamp": time.time(),
|
|
42
|
+
"trace_id": None,
|
|
43
|
+
"span_id": None,
|
|
44
|
+
"name": name,
|
|
45
|
+
"type": metric_type,
|
|
46
|
+
"value": float(value),
|
|
47
|
+
"unit": unit,
|
|
48
|
+
"attributes": attrs,
|
|
49
|
+
} # type: Metric
|
|
50
|
+
|
|
51
|
+
client._capture_metric(metric)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def count(
|
|
55
|
+
name, # type: str
|
|
56
|
+
value, # type: float
|
|
57
|
+
unit=None, # type: Optional[str]
|
|
58
|
+
attributes=None, # type: Optional[dict[str, Any]]
|
|
59
|
+
):
|
|
60
|
+
# type: (...) -> None
|
|
61
|
+
_capture_metric(name, "counter", value, unit, attributes)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def gauge(
|
|
65
|
+
name, # type: str
|
|
66
|
+
value, # type: float
|
|
67
|
+
unit=None, # type: Optional[str]
|
|
68
|
+
attributes=None, # type: Optional[dict[str, Any]]
|
|
69
|
+
):
|
|
70
|
+
# type: (...) -> None
|
|
71
|
+
_capture_metric(name, "gauge", value, unit, attributes)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def distribution(
|
|
75
|
+
name, # type: str
|
|
76
|
+
value, # type: float
|
|
77
|
+
unit=None, # type: Optional[str]
|
|
78
|
+
attributes=None, # type: Optional[dict[str, Any]]
|
|
79
|
+
):
|
|
80
|
+
# type: (...) -> None
|
|
81
|
+
_capture_metric(name, "distribution", value, unit, attributes)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import random
|
|
3
|
+
import threading
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from typing import Optional, List, Callable, TYPE_CHECKING, Any, Union
|
|
6
|
+
|
|
7
|
+
from sentry_sdk.utils import format_timestamp, safe_repr
|
|
8
|
+
from sentry_sdk.envelope import Envelope, Item, PayloadRef
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from sentry_sdk._types import Metric
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MetricsBatcher:
|
|
15
|
+
MAX_METRICS_BEFORE_FLUSH = 100
|
|
16
|
+
FLUSH_WAIT_TIME = 5.0
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
capture_func, # type: Callable[[Envelope], None]
|
|
21
|
+
):
|
|
22
|
+
# type: (...) -> None
|
|
23
|
+
self._metric_buffer = [] # type: List[Metric]
|
|
24
|
+
self._capture_func = capture_func
|
|
25
|
+
self._running = True
|
|
26
|
+
self._lock = threading.Lock()
|
|
27
|
+
|
|
28
|
+
self._flush_event = threading.Event() # type: threading.Event
|
|
29
|
+
|
|
30
|
+
self._flusher = None # type: Optional[threading.Thread]
|
|
31
|
+
self._flusher_pid = None # type: Optional[int]
|
|
32
|
+
|
|
33
|
+
def _ensure_thread(self):
|
|
34
|
+
# type: (...) -> bool
|
|
35
|
+
if not self._running:
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
pid = os.getpid()
|
|
39
|
+
if self._flusher_pid == pid:
|
|
40
|
+
return True
|
|
41
|
+
|
|
42
|
+
with self._lock:
|
|
43
|
+
if self._flusher_pid == pid:
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
self._flusher_pid = pid
|
|
47
|
+
|
|
48
|
+
self._flusher = threading.Thread(target=self._flush_loop)
|
|
49
|
+
self._flusher.daemon = True
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
self._flusher.start()
|
|
53
|
+
except RuntimeError:
|
|
54
|
+
self._running = False
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
return True
|
|
58
|
+
|
|
59
|
+
def _flush_loop(self):
|
|
60
|
+
# type: (...) -> None
|
|
61
|
+
while self._running:
|
|
62
|
+
self._flush_event.wait(self.FLUSH_WAIT_TIME + random.random())
|
|
63
|
+
self._flush_event.clear()
|
|
64
|
+
self._flush()
|
|
65
|
+
|
|
66
|
+
def add(
|
|
67
|
+
self,
|
|
68
|
+
metric, # type: Metric
|
|
69
|
+
):
|
|
70
|
+
# type: (...) -> None
|
|
71
|
+
if not self._ensure_thread() or self._flusher is None:
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
with self._lock:
|
|
75
|
+
self._metric_buffer.append(metric)
|
|
76
|
+
if len(self._metric_buffer) >= self.MAX_METRICS_BEFORE_FLUSH:
|
|
77
|
+
self._flush_event.set()
|
|
78
|
+
|
|
79
|
+
def kill(self):
|
|
80
|
+
# type: (...) -> None
|
|
81
|
+
if self._flusher is None:
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
self._running = False
|
|
85
|
+
self._flush_event.set()
|
|
86
|
+
self._flusher = None
|
|
87
|
+
|
|
88
|
+
def flush(self):
|
|
89
|
+
# type: (...) -> None
|
|
90
|
+
self._flush()
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def _metric_to_transport_format(metric):
|
|
94
|
+
# type: (Metric) -> Any
|
|
95
|
+
def format_attribute(val):
|
|
96
|
+
# type: (Union[int, float, str, bool]) -> Any
|
|
97
|
+
if isinstance(val, bool):
|
|
98
|
+
return {"value": val, "type": "boolean"}
|
|
99
|
+
if isinstance(val, int):
|
|
100
|
+
return {"value": val, "type": "integer"}
|
|
101
|
+
if isinstance(val, float):
|
|
102
|
+
return {"value": val, "type": "double"}
|
|
103
|
+
if isinstance(val, str):
|
|
104
|
+
return {"value": val, "type": "string"}
|
|
105
|
+
return {"value": safe_repr(val), "type": "string"}
|
|
106
|
+
|
|
107
|
+
res = {
|
|
108
|
+
"timestamp": metric["timestamp"],
|
|
109
|
+
"trace_id": metric["trace_id"],
|
|
110
|
+
"name": metric["name"],
|
|
111
|
+
"type": metric["type"],
|
|
112
|
+
"value": metric["value"],
|
|
113
|
+
"attributes": {
|
|
114
|
+
k: format_attribute(v) for (k, v) in metric["attributes"].items()
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if metric.get("span_id") is not None:
|
|
119
|
+
res["span_id"] = metric["span_id"]
|
|
120
|
+
|
|
121
|
+
if metric.get("unit") is not None:
|
|
122
|
+
res["unit"] = metric["unit"]
|
|
123
|
+
|
|
124
|
+
return res
|
|
125
|
+
|
|
126
|
+
def _flush(self):
|
|
127
|
+
# type: (...) -> Optional[Envelope]
|
|
128
|
+
|
|
129
|
+
envelope = Envelope(
|
|
130
|
+
headers={"sent_at": format_timestamp(datetime.now(timezone.utc))}
|
|
131
|
+
)
|
|
132
|
+
with self._lock:
|
|
133
|
+
if len(self._metric_buffer) == 0:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
envelope.add_item(
|
|
137
|
+
Item(
|
|
138
|
+
type="trace_metric",
|
|
139
|
+
content_type="application/vnd.sentry.items.trace-metric+json",
|
|
140
|
+
headers={
|
|
141
|
+
"item_count": len(self._metric_buffer),
|
|
142
|
+
},
|
|
143
|
+
payload=PayloadRef(
|
|
144
|
+
json={
|
|
145
|
+
"items": [
|
|
146
|
+
self._metric_to_transport_format(metric)
|
|
147
|
+
for metric in self._metric_buffer
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
self._metric_buffer.clear()
|
|
154
|
+
|
|
155
|
+
self._capture_func(envelope)
|
|
156
|
+
return envelope
|
|
@@ -210,7 +210,6 @@ if TYPE_CHECKING:
|
|
|
210
210
|
"type": Literal["check_in", "transaction"],
|
|
211
211
|
"user": dict[str, object],
|
|
212
212
|
"_dropped_spans": int,
|
|
213
|
-
"_metrics_summary": dict[str, object],
|
|
214
213
|
},
|
|
215
214
|
total=False,
|
|
216
215
|
)
|
|
@@ -235,6 +234,32 @@ if TYPE_CHECKING:
|
|
|
235
234
|
},
|
|
236
235
|
)
|
|
237
236
|
|
|
237
|
+
MetricType = Literal["counter", "gauge", "distribution"]
|
|
238
|
+
|
|
239
|
+
MetricAttributeValue = TypedDict(
|
|
240
|
+
"MetricAttributeValue",
|
|
241
|
+
{
|
|
242
|
+
"value": Union[str, bool, float, int],
|
|
243
|
+
"type": Literal["string", "boolean", "double", "integer"],
|
|
244
|
+
},
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
Metric = TypedDict(
|
|
248
|
+
"Metric",
|
|
249
|
+
{
|
|
250
|
+
"timestamp": float,
|
|
251
|
+
"trace_id": Optional[str],
|
|
252
|
+
"span_id": Optional[str],
|
|
253
|
+
"name": str,
|
|
254
|
+
"type": MetricType,
|
|
255
|
+
"value": float,
|
|
256
|
+
"unit": Optional[str],
|
|
257
|
+
"attributes": dict[str, str | bool | float | int],
|
|
258
|
+
},
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
MetricProcessor = Callable[[Metric, Hint], Optional[Metric]]
|
|
262
|
+
|
|
238
263
|
# TODO: Make a proper type definition for this (PRs welcome!)
|
|
239
264
|
Breadcrumb = Dict[str, Any]
|
|
240
265
|
|
|
@@ -266,36 +291,16 @@ if TYPE_CHECKING:
|
|
|
266
291
|
"internal",
|
|
267
292
|
"profile",
|
|
268
293
|
"profile_chunk",
|
|
269
|
-
"metric_bucket",
|
|
270
294
|
"monitor",
|
|
271
295
|
"span",
|
|
272
296
|
"log_item",
|
|
297
|
+
"trace_metric",
|
|
273
298
|
]
|
|
274
299
|
SessionStatus = Literal["ok", "exited", "crashed", "abnormal"]
|
|
275
300
|
|
|
276
301
|
ContinuousProfilerMode = Literal["thread", "gevent", "unknown"]
|
|
277
302
|
ProfilerMode = Union[ContinuousProfilerMode, Literal["sleep"]]
|
|
278
303
|
|
|
279
|
-
# Type of the metric.
|
|
280
|
-
MetricType = Literal["d", "s", "g", "c"]
|
|
281
|
-
|
|
282
|
-
# Value of the metric.
|
|
283
|
-
MetricValue = Union[int, float, str]
|
|
284
|
-
|
|
285
|
-
# Internal representation of tags as a tuple of tuples (this is done in order to allow for the same key to exist
|
|
286
|
-
# multiple times).
|
|
287
|
-
MetricTagsInternal = Tuple[Tuple[str, str], ...]
|
|
288
|
-
|
|
289
|
-
# External representation of tags as a dictionary.
|
|
290
|
-
MetricTagValue = Union[str, int, float, None]
|
|
291
|
-
MetricTags = Mapping[str, MetricTagValue]
|
|
292
|
-
|
|
293
|
-
# Value inside the generator for the metric value.
|
|
294
|
-
FlushedMetricValue = Union[int, float]
|
|
295
|
-
|
|
296
|
-
BucketKey = Tuple[MetricType, str, MeasurementUnit, MetricTagsInternal]
|
|
297
|
-
MetricMetaKey = Tuple[MetricType, str, MeasurementUnit]
|
|
298
|
-
|
|
299
304
|
MonitorConfigScheduleType = Literal["crontab", "interval"]
|
|
300
305
|
MonitorConfigScheduleUnit = Literal[
|
|
301
306
|
"year",
|
|
@@ -10,6 +10,26 @@ import sentry_sdk
|
|
|
10
10
|
from sentry_sdk.utils import logger
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
class GEN_AI_ALLOWED_MESSAGE_ROLES:
|
|
14
|
+
SYSTEM = "system"
|
|
15
|
+
USER = "user"
|
|
16
|
+
ASSISTANT = "assistant"
|
|
17
|
+
TOOL = "tool"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
GEN_AI_MESSAGE_ROLE_REVERSE_MAPPING = {
|
|
21
|
+
GEN_AI_ALLOWED_MESSAGE_ROLES.SYSTEM: ["system"],
|
|
22
|
+
GEN_AI_ALLOWED_MESSAGE_ROLES.USER: ["user", "human"],
|
|
23
|
+
GEN_AI_ALLOWED_MESSAGE_ROLES.ASSISTANT: ["assistant", "ai"],
|
|
24
|
+
GEN_AI_ALLOWED_MESSAGE_ROLES.TOOL: ["tool", "tool_call"],
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
GEN_AI_MESSAGE_ROLE_MAPPING = {}
|
|
28
|
+
for target_role, source_roles in GEN_AI_MESSAGE_ROLE_REVERSE_MAPPING.items():
|
|
29
|
+
for source_role in source_roles:
|
|
30
|
+
GEN_AI_MESSAGE_ROLE_MAPPING[source_role] = target_role
|
|
31
|
+
|
|
32
|
+
|
|
13
33
|
def _normalize_data(data, unpack=True):
|
|
14
34
|
# type: (Any, bool) -> Any
|
|
15
35
|
# convert pydantic data (e.g. OpenAI v1+) to json compatible format
|
|
@@ -40,6 +60,34 @@ def set_data_normalized(span, key, value, unpack=True):
|
|
|
40
60
|
span.set_data(key, json.dumps(normalized))
|
|
41
61
|
|
|
42
62
|
|
|
63
|
+
def normalize_message_role(role):
|
|
64
|
+
# type: (str) -> str
|
|
65
|
+
"""
|
|
66
|
+
Normalize a message role to one of the 4 allowed gen_ai role values.
|
|
67
|
+
Maps "ai" -> "assistant" and keeps other standard roles unchanged.
|
|
68
|
+
"""
|
|
69
|
+
return GEN_AI_MESSAGE_ROLE_MAPPING.get(role, role)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def normalize_message_roles(messages):
|
|
73
|
+
# type: (list[dict[str, Any]]) -> list[dict[str, Any]]
|
|
74
|
+
"""
|
|
75
|
+
Normalize roles in a list of messages to use standard gen_ai role values.
|
|
76
|
+
Creates a deep copy to avoid modifying the original messages.
|
|
77
|
+
"""
|
|
78
|
+
normalized_messages = []
|
|
79
|
+
for message in messages:
|
|
80
|
+
if not isinstance(message, dict):
|
|
81
|
+
normalized_messages.append(message)
|
|
82
|
+
continue
|
|
83
|
+
normalized_message = message.copy()
|
|
84
|
+
if "role" in message:
|
|
85
|
+
normalized_message["role"] = normalize_message_role(message["role"])
|
|
86
|
+
normalized_messages.append(normalized_message)
|
|
87
|
+
|
|
88
|
+
return normalized_messages
|
|
89
|
+
|
|
90
|
+
|
|
43
91
|
def get_start_span_function():
|
|
44
92
|
# type: () -> Callable[..., Any]
|
|
45
93
|
current_span = sentry_sdk.get_current_span()
|