sentry-sdk 0.7.5__py2.py3-none-any.whl → 2.46.0__py2.py3-none-any.whl
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.
- sentry_sdk/__init__.py +48 -30
- sentry_sdk/_compat.py +74 -61
- sentry_sdk/_init_implementation.py +84 -0
- sentry_sdk/_log_batcher.py +172 -0
- sentry_sdk/_lru_cache.py +47 -0
- sentry_sdk/_metrics_batcher.py +167 -0
- sentry_sdk/_queue.py +289 -0
- sentry_sdk/_types.py +338 -0
- sentry_sdk/_werkzeug.py +98 -0
- sentry_sdk/ai/__init__.py +7 -0
- sentry_sdk/ai/monitoring.py +137 -0
- sentry_sdk/ai/utils.py +144 -0
- sentry_sdk/api.py +496 -80
- sentry_sdk/attachments.py +75 -0
- sentry_sdk/client.py +1023 -103
- sentry_sdk/consts.py +1438 -66
- sentry_sdk/crons/__init__.py +10 -0
- sentry_sdk/crons/api.py +62 -0
- sentry_sdk/crons/consts.py +4 -0
- sentry_sdk/crons/decorator.py +135 -0
- sentry_sdk/debug.py +15 -14
- sentry_sdk/envelope.py +369 -0
- sentry_sdk/feature_flags.py +71 -0
- sentry_sdk/hub.py +611 -280
- sentry_sdk/integrations/__init__.py +276 -49
- sentry_sdk/integrations/_asgi_common.py +108 -0
- sentry_sdk/integrations/_wsgi_common.py +180 -44
- sentry_sdk/integrations/aiohttp.py +291 -42
- sentry_sdk/integrations/anthropic.py +439 -0
- sentry_sdk/integrations/argv.py +9 -8
- sentry_sdk/integrations/ariadne.py +161 -0
- sentry_sdk/integrations/arq.py +247 -0
- sentry_sdk/integrations/asgi.py +341 -0
- sentry_sdk/integrations/asyncio.py +144 -0
- sentry_sdk/integrations/asyncpg.py +208 -0
- sentry_sdk/integrations/atexit.py +17 -10
- sentry_sdk/integrations/aws_lambda.py +377 -62
- sentry_sdk/integrations/beam.py +176 -0
- sentry_sdk/integrations/boto3.py +137 -0
- sentry_sdk/integrations/bottle.py +221 -0
- sentry_sdk/integrations/celery/__init__.py +529 -0
- sentry_sdk/integrations/celery/beat.py +293 -0
- sentry_sdk/integrations/celery/utils.py +43 -0
- sentry_sdk/integrations/chalice.py +134 -0
- sentry_sdk/integrations/clickhouse_driver.py +177 -0
- sentry_sdk/integrations/cloud_resource_context.py +280 -0
- sentry_sdk/integrations/cohere.py +274 -0
- sentry_sdk/integrations/dedupe.py +48 -14
- sentry_sdk/integrations/django/__init__.py +584 -191
- sentry_sdk/integrations/django/asgi.py +245 -0
- sentry_sdk/integrations/django/caching.py +204 -0
- sentry_sdk/integrations/django/middleware.py +187 -0
- sentry_sdk/integrations/django/signals_handlers.py +91 -0
- sentry_sdk/integrations/django/templates.py +79 -5
- sentry_sdk/integrations/django/transactions.py +49 -22
- sentry_sdk/integrations/django/views.py +96 -0
- sentry_sdk/integrations/dramatiq.py +226 -0
- sentry_sdk/integrations/excepthook.py +50 -13
- sentry_sdk/integrations/executing.py +67 -0
- sentry_sdk/integrations/falcon.py +272 -0
- sentry_sdk/integrations/fastapi.py +141 -0
- sentry_sdk/integrations/flask.py +142 -88
- sentry_sdk/integrations/gcp.py +239 -0
- sentry_sdk/integrations/gnu_backtrace.py +99 -0
- sentry_sdk/integrations/google_genai/__init__.py +301 -0
- sentry_sdk/integrations/google_genai/consts.py +16 -0
- sentry_sdk/integrations/google_genai/streaming.py +155 -0
- sentry_sdk/integrations/google_genai/utils.py +576 -0
- sentry_sdk/integrations/gql.py +162 -0
- sentry_sdk/integrations/graphene.py +151 -0
- sentry_sdk/integrations/grpc/__init__.py +168 -0
- sentry_sdk/integrations/grpc/aio/__init__.py +7 -0
- sentry_sdk/integrations/grpc/aio/client.py +95 -0
- sentry_sdk/integrations/grpc/aio/server.py +100 -0
- sentry_sdk/integrations/grpc/client.py +91 -0
- sentry_sdk/integrations/grpc/consts.py +1 -0
- sentry_sdk/integrations/grpc/server.py +66 -0
- sentry_sdk/integrations/httpx.py +178 -0
- sentry_sdk/integrations/huey.py +174 -0
- sentry_sdk/integrations/huggingface_hub.py +378 -0
- sentry_sdk/integrations/langchain.py +1132 -0
- sentry_sdk/integrations/langgraph.py +337 -0
- sentry_sdk/integrations/launchdarkly.py +61 -0
- sentry_sdk/integrations/litellm.py +287 -0
- sentry_sdk/integrations/litestar.py +315 -0
- sentry_sdk/integrations/logging.py +307 -96
- sentry_sdk/integrations/loguru.py +213 -0
- sentry_sdk/integrations/mcp.py +566 -0
- sentry_sdk/integrations/modules.py +14 -31
- sentry_sdk/integrations/openai.py +725 -0
- sentry_sdk/integrations/openai_agents/__init__.py +61 -0
- sentry_sdk/integrations/openai_agents/consts.py +1 -0
- sentry_sdk/integrations/openai_agents/patches/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/patches/agent_run.py +140 -0
- sentry_sdk/integrations/openai_agents/patches/error_tracing.py +77 -0
- sentry_sdk/integrations/openai_agents/patches/models.py +50 -0
- sentry_sdk/integrations/openai_agents/patches/runner.py +45 -0
- sentry_sdk/integrations/openai_agents/patches/tools.py +77 -0
- sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +21 -0
- sentry_sdk/integrations/openai_agents/spans/ai_client.py +42 -0
- sentry_sdk/integrations/openai_agents/spans/execute_tool.py +48 -0
- sentry_sdk/integrations/openai_agents/spans/handoff.py +19 -0
- sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +86 -0
- sentry_sdk/integrations/openai_agents/utils.py +199 -0
- sentry_sdk/integrations/openfeature.py +35 -0
- sentry_sdk/integrations/opentelemetry/__init__.py +7 -0
- sentry_sdk/integrations/opentelemetry/consts.py +5 -0
- sentry_sdk/integrations/opentelemetry/integration.py +58 -0
- sentry_sdk/integrations/opentelemetry/propagator.py +117 -0
- sentry_sdk/integrations/opentelemetry/span_processor.py +391 -0
- sentry_sdk/integrations/otlp.py +82 -0
- sentry_sdk/integrations/pure_eval.py +141 -0
- sentry_sdk/integrations/pydantic_ai/__init__.py +47 -0
- sentry_sdk/integrations/pydantic_ai/consts.py +1 -0
- sentry_sdk/integrations/pydantic_ai/patches/__init__.py +4 -0
- sentry_sdk/integrations/pydantic_ai/patches/agent_run.py +215 -0
- sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py +110 -0
- sentry_sdk/integrations/pydantic_ai/patches/model_request.py +40 -0
- sentry_sdk/integrations/pydantic_ai/patches/tools.py +98 -0
- sentry_sdk/integrations/pydantic_ai/spans/__init__.py +3 -0
- sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +246 -0
- sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py +49 -0
- sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py +112 -0
- sentry_sdk/integrations/pydantic_ai/utils.py +223 -0
- sentry_sdk/integrations/pymongo.py +214 -0
- sentry_sdk/integrations/pyramid.py +112 -68
- sentry_sdk/integrations/quart.py +237 -0
- sentry_sdk/integrations/ray.py +165 -0
- sentry_sdk/integrations/redis/__init__.py +48 -0
- sentry_sdk/integrations/redis/_async_common.py +116 -0
- sentry_sdk/integrations/redis/_sync_common.py +119 -0
- sentry_sdk/integrations/redis/consts.py +19 -0
- sentry_sdk/integrations/redis/modules/__init__.py +0 -0
- sentry_sdk/integrations/redis/modules/caches.py +118 -0
- sentry_sdk/integrations/redis/modules/queries.py +65 -0
- sentry_sdk/integrations/redis/rb.py +32 -0
- sentry_sdk/integrations/redis/redis.py +69 -0
- sentry_sdk/integrations/redis/redis_cluster.py +107 -0
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +50 -0
- sentry_sdk/integrations/redis/utils.py +148 -0
- sentry_sdk/integrations/rq.py +95 -37
- sentry_sdk/integrations/rust_tracing.py +284 -0
- sentry_sdk/integrations/sanic.py +294 -123
- sentry_sdk/integrations/serverless.py +48 -19
- sentry_sdk/integrations/socket.py +96 -0
- sentry_sdk/integrations/spark/__init__.py +4 -0
- sentry_sdk/integrations/spark/spark_driver.py +316 -0
- sentry_sdk/integrations/spark/spark_worker.py +116 -0
- sentry_sdk/integrations/sqlalchemy.py +142 -0
- sentry_sdk/integrations/starlette.py +737 -0
- sentry_sdk/integrations/starlite.py +292 -0
- sentry_sdk/integrations/statsig.py +37 -0
- sentry_sdk/integrations/stdlib.py +235 -29
- sentry_sdk/integrations/strawberry.py +394 -0
- sentry_sdk/integrations/sys_exit.py +70 -0
- sentry_sdk/integrations/threading.py +158 -28
- sentry_sdk/integrations/tornado.py +84 -52
- sentry_sdk/integrations/trytond.py +50 -0
- sentry_sdk/integrations/typer.py +60 -0
- sentry_sdk/integrations/unleash.py +33 -0
- sentry_sdk/integrations/unraisablehook.py +53 -0
- sentry_sdk/integrations/wsgi.py +201 -119
- sentry_sdk/logger.py +96 -0
- sentry_sdk/metrics.py +81 -0
- sentry_sdk/monitor.py +120 -0
- sentry_sdk/profiler/__init__.py +49 -0
- sentry_sdk/profiler/continuous_profiler.py +730 -0
- sentry_sdk/profiler/transaction_profiler.py +839 -0
- sentry_sdk/profiler/utils.py +195 -0
- sentry_sdk/py.typed +0 -0
- sentry_sdk/scope.py +1713 -85
- sentry_sdk/scrubber.py +177 -0
- sentry_sdk/serializer.py +405 -0
- sentry_sdk/session.py +177 -0
- sentry_sdk/sessions.py +275 -0
- sentry_sdk/spotlight.py +242 -0
- sentry_sdk/tracing.py +1486 -0
- sentry_sdk/tracing_utils.py +1236 -0
- sentry_sdk/transport.py +806 -134
- sentry_sdk/types.py +52 -0
- sentry_sdk/utils.py +1625 -465
- sentry_sdk/worker.py +54 -25
- sentry_sdk-2.46.0.dist-info/METADATA +268 -0
- sentry_sdk-2.46.0.dist-info/RECORD +189 -0
- {sentry_sdk-0.7.5.dist-info → sentry_sdk-2.46.0.dist-info}/WHEEL +1 -1
- sentry_sdk-2.46.0.dist-info/entry_points.txt +2 -0
- sentry_sdk-2.46.0.dist-info/licenses/LICENSE +21 -0
- sentry_sdk/integrations/celery.py +0 -119
- sentry_sdk-0.7.5.dist-info/LICENSE +0 -9
- sentry_sdk-0.7.5.dist-info/METADATA +0 -36
- sentry_sdk-0.7.5.dist-info/RECORD +0 -39
- {sentry_sdk-0.7.5.dist-info → sentry_sdk-2.46.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from collections import deque
|
|
3
|
+
|
|
4
|
+
from sentry_sdk._compat import PY311
|
|
5
|
+
from sentry_sdk.utils import filename_for_module
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from sentry_sdk._lru_cache import LRUCache
|
|
11
|
+
from types import FrameType
|
|
12
|
+
from typing import Deque
|
|
13
|
+
from typing import List
|
|
14
|
+
from typing import Optional
|
|
15
|
+
from typing import Sequence
|
|
16
|
+
from typing import Tuple
|
|
17
|
+
from typing_extensions import TypedDict
|
|
18
|
+
|
|
19
|
+
ThreadId = str
|
|
20
|
+
|
|
21
|
+
ProcessedStack = List[int]
|
|
22
|
+
|
|
23
|
+
ProcessedFrame = TypedDict(
|
|
24
|
+
"ProcessedFrame",
|
|
25
|
+
{
|
|
26
|
+
"abs_path": str,
|
|
27
|
+
"filename": Optional[str],
|
|
28
|
+
"function": str,
|
|
29
|
+
"lineno": int,
|
|
30
|
+
"module": Optional[str],
|
|
31
|
+
},
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
ProcessedThreadMetadata = TypedDict(
|
|
35
|
+
"ProcessedThreadMetadata",
|
|
36
|
+
{"name": str},
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
FrameId = Tuple[
|
|
40
|
+
str, # abs_path
|
|
41
|
+
int, # lineno
|
|
42
|
+
str, # function
|
|
43
|
+
]
|
|
44
|
+
FrameIds = Tuple[FrameId, ...]
|
|
45
|
+
|
|
46
|
+
# The exact value of this id is not very meaningful. The purpose
|
|
47
|
+
# of this id is to give us a compact and unique identifier for a
|
|
48
|
+
# raw stack that can be used as a key to a dictionary so that it
|
|
49
|
+
# can be used during the sampled format generation.
|
|
50
|
+
StackId = Tuple[int, int]
|
|
51
|
+
|
|
52
|
+
ExtractedStack = Tuple[StackId, FrameIds, List[ProcessedFrame]]
|
|
53
|
+
ExtractedSample = Sequence[Tuple[ThreadId, ExtractedStack]]
|
|
54
|
+
|
|
55
|
+
# The default sampling frequency to use. This is set at 101 in order to
|
|
56
|
+
# mitigate the effects of lockstep sampling.
|
|
57
|
+
DEFAULT_SAMPLING_FREQUENCY = 101
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# We want to impose a stack depth limit so that samples aren't too large.
|
|
61
|
+
MAX_STACK_DEPTH = 128
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if PY311:
|
|
65
|
+
|
|
66
|
+
def get_frame_name(frame):
|
|
67
|
+
# type: (FrameType) -> str
|
|
68
|
+
return frame.f_code.co_qualname
|
|
69
|
+
|
|
70
|
+
else:
|
|
71
|
+
|
|
72
|
+
def get_frame_name(frame):
|
|
73
|
+
# type: (FrameType) -> str
|
|
74
|
+
|
|
75
|
+
f_code = frame.f_code
|
|
76
|
+
co_varnames = f_code.co_varnames
|
|
77
|
+
|
|
78
|
+
# co_name only contains the frame name. If the frame was a method,
|
|
79
|
+
# the class name will NOT be included.
|
|
80
|
+
name = f_code.co_name
|
|
81
|
+
|
|
82
|
+
# if it was a method, we can get the class name by inspecting
|
|
83
|
+
# the f_locals for the `self` argument
|
|
84
|
+
try:
|
|
85
|
+
if (
|
|
86
|
+
# the co_varnames start with the frame's positional arguments
|
|
87
|
+
# and we expect the first to be `self` if its an instance method
|
|
88
|
+
co_varnames and co_varnames[0] == "self" and "self" in frame.f_locals
|
|
89
|
+
):
|
|
90
|
+
for cls in type(frame.f_locals["self"]).__mro__:
|
|
91
|
+
if name in cls.__dict__:
|
|
92
|
+
return "{}.{}".format(cls.__name__, name)
|
|
93
|
+
except (AttributeError, ValueError):
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
# if it was a class method, (decorated with `@classmethod`)
|
|
97
|
+
# we can get the class name by inspecting the f_locals for the `cls` argument
|
|
98
|
+
try:
|
|
99
|
+
if (
|
|
100
|
+
# the co_varnames start with the frame's positional arguments
|
|
101
|
+
# and we expect the first to be `cls` if its a class method
|
|
102
|
+
co_varnames and co_varnames[0] == "cls" and "cls" in frame.f_locals
|
|
103
|
+
):
|
|
104
|
+
for cls in frame.f_locals["cls"].__mro__:
|
|
105
|
+
if name in cls.__dict__:
|
|
106
|
+
return "{}.{}".format(cls.__name__, name)
|
|
107
|
+
except (AttributeError, ValueError):
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
# nothing we can do if it is a staticmethod (decorated with @staticmethod)
|
|
111
|
+
|
|
112
|
+
# we've done all we can, time to give up and return what we have
|
|
113
|
+
return name
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def frame_id(raw_frame):
|
|
117
|
+
# type: (FrameType) -> FrameId
|
|
118
|
+
return (raw_frame.f_code.co_filename, raw_frame.f_lineno, get_frame_name(raw_frame))
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def extract_frame(fid, raw_frame, cwd):
|
|
122
|
+
# type: (FrameId, FrameType, str) -> ProcessedFrame
|
|
123
|
+
abs_path = raw_frame.f_code.co_filename
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
module = raw_frame.f_globals["__name__"]
|
|
127
|
+
except Exception:
|
|
128
|
+
module = None
|
|
129
|
+
|
|
130
|
+
# namedtuples can be many times slower when initialing
|
|
131
|
+
# and accessing attribute so we opt to use a tuple here instead
|
|
132
|
+
return {
|
|
133
|
+
# This originally was `os.path.abspath(abs_path)` but that had
|
|
134
|
+
# a large performance overhead.
|
|
135
|
+
#
|
|
136
|
+
# According to docs, this is equivalent to
|
|
137
|
+
# `os.path.normpath(os.path.join(os.getcwd(), path))`.
|
|
138
|
+
# The `os.getcwd()` call is slow here, so we precompute it.
|
|
139
|
+
#
|
|
140
|
+
# Additionally, since we are using normalized path already,
|
|
141
|
+
# we skip calling `os.path.normpath` entirely.
|
|
142
|
+
"abs_path": os.path.join(cwd, abs_path),
|
|
143
|
+
"module": module,
|
|
144
|
+
"filename": filename_for_module(module, abs_path) or None,
|
|
145
|
+
"function": fid[2],
|
|
146
|
+
"lineno": raw_frame.f_lineno,
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def extract_stack(
|
|
151
|
+
raw_frame, # type: Optional[FrameType]
|
|
152
|
+
cache, # type: LRUCache
|
|
153
|
+
cwd, # type: str
|
|
154
|
+
max_stack_depth=MAX_STACK_DEPTH, # type: int
|
|
155
|
+
):
|
|
156
|
+
# type: (...) -> ExtractedStack
|
|
157
|
+
"""
|
|
158
|
+
Extracts the stack starting the specified frame. The extracted stack
|
|
159
|
+
assumes the specified frame is the top of the stack, and works back
|
|
160
|
+
to the bottom of the stack.
|
|
161
|
+
|
|
162
|
+
In the event that the stack is more than `MAX_STACK_DEPTH` frames deep,
|
|
163
|
+
only the first `MAX_STACK_DEPTH` frames will be returned.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
raw_frames = deque(maxlen=max_stack_depth) # type: Deque[FrameType]
|
|
167
|
+
|
|
168
|
+
while raw_frame is not None:
|
|
169
|
+
f_back = raw_frame.f_back
|
|
170
|
+
raw_frames.append(raw_frame)
|
|
171
|
+
raw_frame = f_back
|
|
172
|
+
|
|
173
|
+
frame_ids = tuple(frame_id(raw_frame) for raw_frame in raw_frames)
|
|
174
|
+
frames = []
|
|
175
|
+
for i, fid in enumerate(frame_ids):
|
|
176
|
+
frame = cache.get(fid)
|
|
177
|
+
if frame is None:
|
|
178
|
+
frame = extract_frame(fid, raw_frames[i], cwd)
|
|
179
|
+
cache.set(fid, frame)
|
|
180
|
+
frames.append(frame)
|
|
181
|
+
|
|
182
|
+
# Instead of mapping the stack into frame ids and hashing
|
|
183
|
+
# that as a tuple, we can directly hash the stack.
|
|
184
|
+
# This saves us from having to generate yet another list.
|
|
185
|
+
# Additionally, using the stack as the key directly is
|
|
186
|
+
# costly because the stack can be large, so we pre-hash
|
|
187
|
+
# the stack, and use the hash as the key as this will be
|
|
188
|
+
# needed a few times to improve performance.
|
|
189
|
+
#
|
|
190
|
+
# To Reduce the likelihood of hash collisions, we include
|
|
191
|
+
# the stack depth. This means that only stacks of the same
|
|
192
|
+
# depth can suffer from hash collisions.
|
|
193
|
+
stack_id = len(raw_frames), hash(frame_ids)
|
|
194
|
+
|
|
195
|
+
return stack_id, frame_ids, frames
|
sentry_sdk/py.typed
ADDED
|
File without changes
|