sentry-sdk 3.0.0a2__py2.py3-none-any.whl → 3.0.0a4__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.
Potentially problematic release.
This version of sentry-sdk might be problematic. Click here for more details.
- sentry_sdk/__init__.py +4 -0
- sentry_sdk/_compat.py +5 -12
- sentry_sdk/_init_implementation.py +7 -7
- sentry_sdk/_log_batcher.py +17 -29
- sentry_sdk/_lru_cache.py +7 -9
- sentry_sdk/_queue.py +2 -4
- sentry_sdk/_types.py +9 -16
- sentry_sdk/_werkzeug.py +5 -7
- sentry_sdk/ai/monitoring.py +45 -33
- sentry_sdk/ai/utils.py +8 -5
- sentry_sdk/api.py +91 -87
- sentry_sdk/attachments.py +10 -12
- sentry_sdk/client.py +119 -159
- sentry_sdk/consts.py +432 -223
- sentry_sdk/crons/api.py +16 -17
- sentry_sdk/crons/decorator.py +25 -27
- sentry_sdk/debug.py +4 -6
- sentry_sdk/envelope.py +46 -112
- sentry_sdk/feature_flags.py +9 -15
- sentry_sdk/integrations/__init__.py +24 -19
- sentry_sdk/integrations/_asgi_common.py +16 -18
- sentry_sdk/integrations/_wsgi_common.py +22 -33
- sentry_sdk/integrations/aiohttp.py +33 -31
- sentry_sdk/integrations/anthropic.py +43 -38
- sentry_sdk/integrations/argv.py +3 -4
- sentry_sdk/integrations/ariadne.py +16 -18
- sentry_sdk/integrations/arq.py +20 -29
- sentry_sdk/integrations/asgi.py +63 -37
- sentry_sdk/integrations/asyncio.py +15 -17
- sentry_sdk/integrations/asyncpg.py +1 -1
- sentry_sdk/integrations/atexit.py +6 -10
- sentry_sdk/integrations/aws_lambda.py +26 -36
- sentry_sdk/integrations/beam.py +10 -18
- sentry_sdk/integrations/boto3.py +20 -18
- sentry_sdk/integrations/bottle.py +25 -34
- sentry_sdk/integrations/celery/__init__.py +40 -59
- sentry_sdk/integrations/celery/beat.py +22 -26
- sentry_sdk/integrations/celery/utils.py +15 -17
- sentry_sdk/integrations/chalice.py +8 -10
- sentry_sdk/integrations/clickhouse_driver.py +22 -32
- sentry_sdk/integrations/cloud_resource_context.py +9 -16
- sentry_sdk/integrations/cohere.py +19 -25
- sentry_sdk/integrations/dedupe.py +5 -8
- sentry_sdk/integrations/django/__init__.py +69 -74
- sentry_sdk/integrations/django/asgi.py +25 -33
- sentry_sdk/integrations/django/caching.py +24 -20
- sentry_sdk/integrations/django/middleware.py +18 -21
- sentry_sdk/integrations/django/signals_handlers.py +12 -11
- sentry_sdk/integrations/django/templates.py +21 -18
- sentry_sdk/integrations/django/transactions.py +16 -11
- sentry_sdk/integrations/django/views.py +8 -12
- sentry_sdk/integrations/dramatiq.py +21 -21
- sentry_sdk/integrations/excepthook.py +10 -10
- sentry_sdk/integrations/executing.py +3 -4
- sentry_sdk/integrations/falcon.py +27 -42
- sentry_sdk/integrations/fastapi.py +13 -16
- sentry_sdk/integrations/flask.py +31 -38
- sentry_sdk/integrations/gcp.py +13 -16
- sentry_sdk/integrations/gnu_backtrace.py +7 -20
- sentry_sdk/integrations/gql.py +16 -17
- sentry_sdk/integrations/graphene.py +14 -13
- sentry_sdk/integrations/grpc/__init__.py +3 -2
- sentry_sdk/integrations/grpc/aio/client.py +2 -2
- sentry_sdk/integrations/grpc/aio/server.py +15 -14
- sentry_sdk/integrations/grpc/client.py +21 -11
- sentry_sdk/integrations/grpc/consts.py +2 -0
- sentry_sdk/integrations/grpc/server.py +12 -8
- sentry_sdk/integrations/httpx.py +11 -14
- sentry_sdk/integrations/huey.py +14 -21
- sentry_sdk/integrations/huggingface_hub.py +17 -17
- sentry_sdk/integrations/langchain.py +204 -114
- sentry_sdk/integrations/launchdarkly.py +13 -10
- sentry_sdk/integrations/litestar.py +40 -38
- sentry_sdk/integrations/logging.py +29 -36
- sentry_sdk/integrations/loguru.py +16 -20
- sentry_sdk/integrations/modules.py +3 -4
- sentry_sdk/integrations/openai.py +421 -204
- sentry_sdk/integrations/openai_agents/__init__.py +49 -0
- sentry_sdk/integrations/openai_agents/consts.py +1 -0
- sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
- sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
- sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
- sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
- sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
- sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
- sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
- sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
- sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
- sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
- sentry_sdk/integrations/openai_agents/utils.py +153 -0
- sentry_sdk/integrations/openfeature.py +12 -8
- sentry_sdk/integrations/pure_eval.py +6 -10
- sentry_sdk/integrations/pymongo.py +14 -18
- sentry_sdk/integrations/pyramid.py +31 -36
- sentry_sdk/integrations/quart.py +23 -28
- sentry_sdk/integrations/ray.py +73 -64
- sentry_sdk/integrations/redis/__init__.py +7 -4
- sentry_sdk/integrations/redis/_async_common.py +18 -12
- sentry_sdk/integrations/redis/_sync_common.py +16 -15
- sentry_sdk/integrations/redis/modules/caches.py +17 -8
- sentry_sdk/integrations/redis/modules/queries.py +9 -8
- sentry_sdk/integrations/redis/rb.py +3 -2
- sentry_sdk/integrations/redis/redis.py +4 -4
- sentry_sdk/integrations/redis/redis_cluster.py +10 -8
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
- sentry_sdk/integrations/redis/utils.py +21 -22
- sentry_sdk/integrations/rq.py +13 -16
- sentry_sdk/integrations/rust_tracing.py +10 -7
- sentry_sdk/integrations/sanic.py +34 -46
- sentry_sdk/integrations/serverless.py +22 -27
- sentry_sdk/integrations/socket.py +29 -17
- sentry_sdk/integrations/spark/__init__.py +1 -0
- sentry_sdk/integrations/spark/spark_driver.py +45 -83
- sentry_sdk/integrations/spark/spark_worker.py +7 -11
- sentry_sdk/integrations/sqlalchemy.py +22 -19
- sentry_sdk/integrations/starlette.py +89 -93
- sentry_sdk/integrations/starlite.py +31 -37
- sentry_sdk/integrations/statsig.py +5 -4
- sentry_sdk/integrations/stdlib.py +32 -28
- sentry_sdk/integrations/strawberry.py +63 -50
- sentry_sdk/integrations/sys_exit.py +7 -11
- sentry_sdk/integrations/threading.py +13 -15
- sentry_sdk/integrations/tornado.py +28 -32
- sentry_sdk/integrations/trytond.py +4 -3
- sentry_sdk/integrations/typer.py +8 -6
- sentry_sdk/integrations/unleash.py +5 -4
- sentry_sdk/integrations/wsgi.py +47 -46
- sentry_sdk/logger.py +13 -9
- sentry_sdk/monitor.py +16 -28
- sentry_sdk/opentelemetry/consts.py +11 -4
- sentry_sdk/opentelemetry/contextvars_context.py +17 -15
- sentry_sdk/opentelemetry/propagator.py +38 -21
- sentry_sdk/opentelemetry/sampler.py +51 -34
- sentry_sdk/opentelemetry/scope.py +46 -37
- sentry_sdk/opentelemetry/span_processor.py +43 -59
- sentry_sdk/opentelemetry/tracing.py +32 -12
- sentry_sdk/opentelemetry/utils.py +180 -196
- sentry_sdk/profiler/continuous_profiler.py +108 -97
- sentry_sdk/profiler/transaction_profiler.py +70 -97
- sentry_sdk/profiler/utils.py +11 -15
- sentry_sdk/scope.py +251 -264
- sentry_sdk/scrubber.py +22 -26
- sentry_sdk/serializer.py +48 -65
- sentry_sdk/session.py +44 -61
- sentry_sdk/sessions.py +35 -49
- sentry_sdk/spotlight.py +15 -21
- sentry_sdk/tracing.py +118 -184
- sentry_sdk/tracing_utils.py +103 -123
- sentry_sdk/transport.py +131 -157
- sentry_sdk/utils.py +278 -309
- sentry_sdk/worker.py +16 -28
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/METADATA +1 -1
- sentry_sdk-3.0.0a4.dist-info/RECORD +168 -0
- sentry_sdk-3.0.0a2.dist-info/RECORD +0 -154
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/WHEEL +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/entry_points.txt +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
from collections.abc import Set
|
|
2
3
|
import sentry_sdk
|
|
3
4
|
from sentry_sdk.consts import OP, TransactionSource, SOURCE_FOR_STYLE
|
|
@@ -52,13 +53,12 @@ class LitestarIntegration(Integration):
|
|
|
52
53
|
|
|
53
54
|
def __init__(
|
|
54
55
|
self,
|
|
55
|
-
failed_request_status_codes
|
|
56
|
+
failed_request_status_codes: Set[int] = _DEFAULT_FAILED_REQUEST_STATUS_CODES,
|
|
56
57
|
) -> None:
|
|
57
58
|
self.failed_request_status_codes = failed_request_status_codes
|
|
58
59
|
|
|
59
60
|
@staticmethod
|
|
60
|
-
def setup_once():
|
|
61
|
-
# type: () -> None
|
|
61
|
+
def setup_once() -> None:
|
|
62
62
|
patch_app_init()
|
|
63
63
|
patch_middlewares()
|
|
64
64
|
patch_http_route_handle()
|
|
@@ -75,8 +75,9 @@ class LitestarIntegration(Integration):
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
class SentryLitestarASGIMiddleware(SentryAsgiMiddleware):
|
|
78
|
-
def __init__(
|
|
79
|
-
|
|
78
|
+
def __init__(
|
|
79
|
+
self, app: ASGIApp, span_origin: str = LitestarIntegration.origin
|
|
80
|
+
) -> None:
|
|
80
81
|
|
|
81
82
|
super().__init__(
|
|
82
83
|
app=app,
|
|
@@ -86,9 +87,16 @@ class SentryLitestarASGIMiddleware(SentryAsgiMiddleware):
|
|
|
86
87
|
span_origin=span_origin,
|
|
87
88
|
)
|
|
88
89
|
|
|
90
|
+
def _capture_request_exception(self, exc: Exception) -> None:
|
|
91
|
+
"""Avoid catching exceptions from request handlers.
|
|
92
|
+
|
|
93
|
+
Those exceptions are already handled in Litestar.after_exception handler.
|
|
94
|
+
We still catch exceptions from application lifespan handlers.
|
|
95
|
+
"""
|
|
96
|
+
pass
|
|
97
|
+
|
|
89
98
|
|
|
90
|
-
def patch_app_init():
|
|
91
|
-
# type: () -> None
|
|
99
|
+
def patch_app_init() -> None:
|
|
92
100
|
"""
|
|
93
101
|
Replaces the Litestar class's `__init__` function in order to inject `after_exception` handlers and set the
|
|
94
102
|
`SentryLitestarASGIMiddleware` as the outmost middleware in the stack.
|
|
@@ -99,8 +107,7 @@ def patch_app_init():
|
|
|
99
107
|
old__init__ = Litestar.__init__
|
|
100
108
|
|
|
101
109
|
@ensure_integration_enabled(LitestarIntegration, old__init__)
|
|
102
|
-
def injection_wrapper(self, *args, **kwargs):
|
|
103
|
-
# type: (Litestar, *Any, **Any) -> None
|
|
110
|
+
def injection_wrapper(self: Litestar, *args: Any, **kwargs: Any) -> None:
|
|
104
111
|
kwargs["after_exception"] = [
|
|
105
112
|
exception_handler,
|
|
106
113
|
*(kwargs.get("after_exception") or []),
|
|
@@ -114,13 +121,11 @@ def patch_app_init():
|
|
|
114
121
|
Litestar.__init__ = injection_wrapper
|
|
115
122
|
|
|
116
123
|
|
|
117
|
-
def patch_middlewares():
|
|
118
|
-
# type: () -> None
|
|
124
|
+
def patch_middlewares() -> None:
|
|
119
125
|
old_resolve_middleware_stack = BaseRouteHandler.resolve_middleware
|
|
120
126
|
|
|
121
127
|
@ensure_integration_enabled(LitestarIntegration, old_resolve_middleware_stack)
|
|
122
|
-
def resolve_middleware_wrapper(self):
|
|
123
|
-
# type: (BaseRouteHandler) -> list[Middleware]
|
|
128
|
+
def resolve_middleware_wrapper(self: BaseRouteHandler) -> list[Middleware]:
|
|
124
129
|
return [
|
|
125
130
|
enable_span_for_middleware(middleware)
|
|
126
131
|
for middleware in old_resolve_middleware_stack(self)
|
|
@@ -129,8 +134,7 @@ def patch_middlewares():
|
|
|
129
134
|
BaseRouteHandler.resolve_middleware = resolve_middleware_wrapper
|
|
130
135
|
|
|
131
136
|
|
|
132
|
-
def enable_span_for_middleware(middleware):
|
|
133
|
-
# type: (Middleware) -> Middleware
|
|
137
|
+
def enable_span_for_middleware(middleware: Middleware) -> Middleware:
|
|
134
138
|
if (
|
|
135
139
|
not hasattr(middleware, "__call__") # noqa: B004
|
|
136
140
|
or middleware is SentryLitestarASGIMiddleware
|
|
@@ -138,12 +142,13 @@ def enable_span_for_middleware(middleware):
|
|
|
138
142
|
return middleware
|
|
139
143
|
|
|
140
144
|
if isinstance(middleware, DefineMiddleware):
|
|
141
|
-
old_call = middleware.middleware.__call__
|
|
145
|
+
old_call: ASGIApp = middleware.middleware.__call__
|
|
142
146
|
else:
|
|
143
147
|
old_call = middleware.__call__
|
|
144
148
|
|
|
145
|
-
async def _create_span_call(
|
|
146
|
-
|
|
149
|
+
async def _create_span_call(
|
|
150
|
+
self: MiddlewareProtocol, scope: LitestarScope, receive: Receive, send: Send
|
|
151
|
+
) -> None:
|
|
147
152
|
if sentry_sdk.get_client().get_integration(LitestarIntegration) is None:
|
|
148
153
|
return await old_call(self, scope, receive, send)
|
|
149
154
|
|
|
@@ -152,20 +157,21 @@ def enable_span_for_middleware(middleware):
|
|
|
152
157
|
op=OP.MIDDLEWARE_LITESTAR,
|
|
153
158
|
name=middleware_name,
|
|
154
159
|
origin=LitestarIntegration.origin,
|
|
155
|
-
|
|
160
|
+
only_as_child_span=True,
|
|
156
161
|
) as middleware_span:
|
|
157
162
|
middleware_span.set_tag("litestar.middleware_name", middleware_name)
|
|
158
163
|
|
|
159
164
|
# Creating spans for the "receive" callback
|
|
160
|
-
async def _sentry_receive(
|
|
161
|
-
|
|
165
|
+
async def _sentry_receive(
|
|
166
|
+
*args: Any, **kwargs: Any
|
|
167
|
+
) -> Union[HTTPReceiveMessage, WebSocketReceiveMessage]:
|
|
162
168
|
if sentry_sdk.get_client().get_integration(LitestarIntegration) is None:
|
|
163
169
|
return await receive(*args, **kwargs)
|
|
164
170
|
with sentry_sdk.start_span(
|
|
165
171
|
op=OP.MIDDLEWARE_LITESTAR_RECEIVE,
|
|
166
172
|
name=getattr(receive, "__qualname__", str(receive)),
|
|
167
173
|
origin=LitestarIntegration.origin,
|
|
168
|
-
|
|
174
|
+
only_as_child_span=True,
|
|
169
175
|
) as span:
|
|
170
176
|
span.set_tag("litestar.middleware_name", middleware_name)
|
|
171
177
|
return await receive(*args, **kwargs)
|
|
@@ -175,15 +181,14 @@ def enable_span_for_middleware(middleware):
|
|
|
175
181
|
new_receive = _sentry_receive if not receive_patched else receive
|
|
176
182
|
|
|
177
183
|
# Creating spans for the "send" callback
|
|
178
|
-
async def _sentry_send(message):
|
|
179
|
-
# type: (Message) -> None
|
|
184
|
+
async def _sentry_send(message: Message) -> None:
|
|
180
185
|
if sentry_sdk.get_client().get_integration(LitestarIntegration) is None:
|
|
181
186
|
return await send(message)
|
|
182
187
|
with sentry_sdk.start_span(
|
|
183
188
|
op=OP.MIDDLEWARE_LITESTAR_SEND,
|
|
184
189
|
name=getattr(send, "__qualname__", str(send)),
|
|
185
190
|
origin=LitestarIntegration.origin,
|
|
186
|
-
|
|
191
|
+
only_as_child_span=True,
|
|
187
192
|
) as span:
|
|
188
193
|
span.set_tag("litestar.middleware_name", middleware_name)
|
|
189
194
|
return await send(message)
|
|
@@ -205,19 +210,19 @@ def enable_span_for_middleware(middleware):
|
|
|
205
210
|
return middleware
|
|
206
211
|
|
|
207
212
|
|
|
208
|
-
def patch_http_route_handle():
|
|
209
|
-
# type: () -> None
|
|
213
|
+
def patch_http_route_handle() -> None:
|
|
210
214
|
old_handle = HTTPRoute.handle
|
|
211
215
|
|
|
212
|
-
async def handle_wrapper(
|
|
213
|
-
|
|
216
|
+
async def handle_wrapper(
|
|
217
|
+
self: HTTPRoute, scope: HTTPScope, receive: Receive, send: Send
|
|
218
|
+
) -> None:
|
|
214
219
|
if sentry_sdk.get_client().get_integration(LitestarIntegration) is None:
|
|
215
220
|
return await old_handle(self, scope, receive, send)
|
|
216
221
|
|
|
217
222
|
sentry_scope = sentry_sdk.get_isolation_scope()
|
|
218
|
-
request = scope["app"].request_class(
|
|
223
|
+
request: Request[Any, Any] = scope["app"].request_class(
|
|
219
224
|
scope=scope, receive=receive, send=send
|
|
220
|
-
)
|
|
225
|
+
)
|
|
221
226
|
extracted_request_data = ConnectionDataExtractor(
|
|
222
227
|
parse_body=True, parse_query=True
|
|
223
228
|
)(request)
|
|
@@ -225,8 +230,7 @@ def patch_http_route_handle():
|
|
|
225
230
|
|
|
226
231
|
request_data = await body
|
|
227
232
|
|
|
228
|
-
def event_processor(event, _):
|
|
229
|
-
# type: (Event, Hint) -> Event
|
|
233
|
+
def event_processor(event: Event, _: Hint) -> Event:
|
|
230
234
|
route_handler = scope.get("route_handler")
|
|
231
235
|
|
|
232
236
|
request_info = event.get("request", {})
|
|
@@ -270,8 +274,7 @@ def patch_http_route_handle():
|
|
|
270
274
|
HTTPRoute.handle = handle_wrapper
|
|
271
275
|
|
|
272
276
|
|
|
273
|
-
def retrieve_user_from_scope(scope):
|
|
274
|
-
# type: (LitestarScope) -> Optional[dict[str, Any]]
|
|
277
|
+
def retrieve_user_from_scope(scope: LitestarScope) -> Optional[dict[str, Any]]:
|
|
275
278
|
scope_user = scope.get("user")
|
|
276
279
|
if isinstance(scope_user, dict):
|
|
277
280
|
return scope_user
|
|
@@ -282,9 +285,8 @@ def retrieve_user_from_scope(scope):
|
|
|
282
285
|
|
|
283
286
|
|
|
284
287
|
@ensure_integration_enabled(LitestarIntegration)
|
|
285
|
-
def exception_handler(exc, scope):
|
|
286
|
-
|
|
287
|
-
user_info = None # type: Optional[dict[str, Any]]
|
|
288
|
+
def exception_handler(exc: Exception, scope: LitestarScope) -> None:
|
|
289
|
+
user_info: Optional[dict[str, Any]] = None
|
|
288
290
|
if should_send_default_pii():
|
|
289
291
|
user_info = retrieve_user_from_scope(scope)
|
|
290
292
|
if user_info and isinstance(user_info, dict):
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import logging
|
|
2
3
|
import sys
|
|
3
4
|
from datetime import datetime, timezone
|
|
@@ -64,9 +65,8 @@ _IGNORED_LOGGERS = set(
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
def ignore_logger(
|
|
67
|
-
name
|
|
68
|
-
):
|
|
69
|
-
# type: (...) -> None
|
|
68
|
+
name: str,
|
|
69
|
+
) -> None:
|
|
70
70
|
"""This disables recording (both in breadcrumbs and as events) calls to
|
|
71
71
|
a logger of a specific name. Among other uses, many of our integrations
|
|
72
72
|
use this to prevent their actions being recorded as breadcrumbs. Exposed
|
|
@@ -82,11 +82,10 @@ class LoggingIntegration(Integration):
|
|
|
82
82
|
|
|
83
83
|
def __init__(
|
|
84
84
|
self,
|
|
85
|
-
level=DEFAULT_LEVEL,
|
|
86
|
-
event_level=DEFAULT_EVENT_LEVEL,
|
|
87
|
-
sentry_logs_level=DEFAULT_LEVEL,
|
|
88
|
-
):
|
|
89
|
-
# type: (Optional[int], Optional[int], Optional[int]) -> None
|
|
85
|
+
level: Optional[int] = DEFAULT_LEVEL,
|
|
86
|
+
event_level: Optional[int] = DEFAULT_EVENT_LEVEL,
|
|
87
|
+
sentry_logs_level: Optional[int] = DEFAULT_LEVEL,
|
|
88
|
+
) -> None:
|
|
90
89
|
self._handler = None
|
|
91
90
|
self._breadcrumb_handler = None
|
|
92
91
|
self._sentry_logs_handler = None
|
|
@@ -100,8 +99,7 @@ class LoggingIntegration(Integration):
|
|
|
100
99
|
if event_level is not None:
|
|
101
100
|
self._handler = EventHandler(level=event_level)
|
|
102
101
|
|
|
103
|
-
def _handle_record(self, record):
|
|
104
|
-
# type: (LogRecord) -> None
|
|
102
|
+
def _handle_record(self, record: LogRecord) -> None:
|
|
105
103
|
if self._handler is not None and record.levelno >= self._handler.level:
|
|
106
104
|
self._handler.handle(record)
|
|
107
105
|
|
|
@@ -118,12 +116,10 @@ class LoggingIntegration(Integration):
|
|
|
118
116
|
self._sentry_logs_handler.handle(record)
|
|
119
117
|
|
|
120
118
|
@staticmethod
|
|
121
|
-
def setup_once():
|
|
122
|
-
# type: () -> None
|
|
119
|
+
def setup_once() -> None:
|
|
123
120
|
old_callhandlers = logging.Logger.callHandlers
|
|
124
121
|
|
|
125
|
-
def sentry_patched_callhandlers(self, record):
|
|
126
|
-
# type: (Any, LogRecord) -> Any
|
|
122
|
+
def sentry_patched_callhandlers(self: Any, record: LogRecord) -> Any:
|
|
127
123
|
# keeping a local reference because the
|
|
128
124
|
# global might be discarded on shutdown
|
|
129
125
|
ignored_loggers = _IGNORED_LOGGERS
|
|
@@ -179,22 +175,19 @@ class _BaseHandler(logging.Handler):
|
|
|
179
175
|
)
|
|
180
176
|
)
|
|
181
177
|
|
|
182
|
-
def _can_record(self, record):
|
|
183
|
-
# type: (LogRecord) -> bool
|
|
178
|
+
def _can_record(self, record: LogRecord) -> bool:
|
|
184
179
|
"""Prevents ignored loggers from recording"""
|
|
185
180
|
for logger in _IGNORED_LOGGERS:
|
|
186
181
|
if fnmatch(record.name.strip(), logger):
|
|
187
182
|
return False
|
|
188
183
|
return True
|
|
189
184
|
|
|
190
|
-
def _logging_to_event_level(self, record):
|
|
191
|
-
# type: (LogRecord) -> str
|
|
185
|
+
def _logging_to_event_level(self, record: LogRecord) -> str:
|
|
192
186
|
return LOGGING_TO_EVENT_LEVEL.get(
|
|
193
187
|
record.levelno, record.levelname.lower() if record.levelname else ""
|
|
194
188
|
)
|
|
195
189
|
|
|
196
|
-
def _extra_from_record(self, record):
|
|
197
|
-
# type: (LogRecord) -> MutableMapping[str, object]
|
|
190
|
+
def _extra_from_record(self, record: LogRecord) -> MutableMapping[str, object]:
|
|
198
191
|
return {
|
|
199
192
|
k: v
|
|
200
193
|
for k, v in vars(record).items()
|
|
@@ -210,14 +203,12 @@ class EventHandler(_BaseHandler):
|
|
|
210
203
|
Note that you do not have to use this class if the logging integration is enabled, which it is by default.
|
|
211
204
|
"""
|
|
212
205
|
|
|
213
|
-
def emit(self, record):
|
|
214
|
-
# type: (LogRecord) -> Any
|
|
206
|
+
def emit(self, record: LogRecord) -> Any:
|
|
215
207
|
with capture_internal_exceptions():
|
|
216
208
|
self.format(record)
|
|
217
209
|
return self._emit(record)
|
|
218
210
|
|
|
219
|
-
def _emit(self, record):
|
|
220
|
-
# type: (LogRecord) -> None
|
|
211
|
+
def _emit(self, record: LogRecord) -> None:
|
|
221
212
|
if not self._can_record(record):
|
|
222
213
|
return
|
|
223
214
|
|
|
@@ -304,14 +295,12 @@ class BreadcrumbHandler(_BaseHandler):
|
|
|
304
295
|
Note that you do not have to use this class if the logging integration is enabled, which it is by default.
|
|
305
296
|
"""
|
|
306
297
|
|
|
307
|
-
def emit(self, record):
|
|
308
|
-
# type: (LogRecord) -> Any
|
|
298
|
+
def emit(self, record: LogRecord) -> Any:
|
|
309
299
|
with capture_internal_exceptions():
|
|
310
300
|
self.format(record)
|
|
311
301
|
return self._emit(record)
|
|
312
302
|
|
|
313
|
-
def _emit(self, record):
|
|
314
|
-
# type: (LogRecord) -> None
|
|
303
|
+
def _emit(self, record: LogRecord) -> None:
|
|
315
304
|
if not self._can_record(record):
|
|
316
305
|
return
|
|
317
306
|
|
|
@@ -319,8 +308,7 @@ class BreadcrumbHandler(_BaseHandler):
|
|
|
319
308
|
self._breadcrumb_from_record(record), hint={"log_record": record}
|
|
320
309
|
)
|
|
321
310
|
|
|
322
|
-
def _breadcrumb_from_record(self, record):
|
|
323
|
-
# type: (LogRecord) -> Dict[str, Any]
|
|
311
|
+
def _breadcrumb_from_record(self, record: LogRecord) -> Dict[str, Any]:
|
|
324
312
|
return {
|
|
325
313
|
"type": "log",
|
|
326
314
|
"level": self._logging_to_event_level(record),
|
|
@@ -338,8 +326,7 @@ class SentryLogsHandler(_BaseHandler):
|
|
|
338
326
|
Note that you do not have to use this class if the logging integration is enabled, which it is by default.
|
|
339
327
|
"""
|
|
340
328
|
|
|
341
|
-
def emit(self, record):
|
|
342
|
-
# type: (LogRecord) -> Any
|
|
329
|
+
def emit(self, record: LogRecord) -> Any:
|
|
343
330
|
with capture_internal_exceptions():
|
|
344
331
|
self.format(record)
|
|
345
332
|
if not self._can_record(record):
|
|
@@ -349,18 +336,17 @@ class SentryLogsHandler(_BaseHandler):
|
|
|
349
336
|
if not client.is_active():
|
|
350
337
|
return
|
|
351
338
|
|
|
352
|
-
if
|
|
339
|
+
if client.options.get("enable_logs") is not True:
|
|
353
340
|
return
|
|
354
341
|
|
|
355
342
|
self._capture_log_from_record(client, record)
|
|
356
343
|
|
|
357
|
-
def _capture_log_from_record(self, client, record):
|
|
358
|
-
# type: (BaseClient, LogRecord) -> None
|
|
344
|
+
def _capture_log_from_record(self, client: BaseClient, record: LogRecord) -> None:
|
|
359
345
|
otel_severity_number, otel_severity_text = _log_level_to_otel(
|
|
360
346
|
record.levelno, SEVERITY_TO_OTEL_SEVERITY
|
|
361
347
|
)
|
|
362
348
|
project_root = client.options["project_root"]
|
|
363
|
-
attrs = self._extra_from_record(record)
|
|
349
|
+
attrs: Any = self._extra_from_record(record)
|
|
364
350
|
attrs["sentry.origin"] = "auto.logger.log"
|
|
365
351
|
if isinstance(record.msg, str):
|
|
366
352
|
attrs["sentry.message.template"] = record.msg
|
|
@@ -372,6 +358,13 @@ class SentryLogsHandler(_BaseHandler):
|
|
|
372
358
|
if isinstance(arg, (str, float, int, bool))
|
|
373
359
|
else safe_repr(arg)
|
|
374
360
|
)
|
|
361
|
+
elif isinstance(record.args, dict):
|
|
362
|
+
for key, value in record.args.items():
|
|
363
|
+
attrs[f"sentry.message.parameter.{key}"] = (
|
|
364
|
+
value
|
|
365
|
+
if isinstance(value, (str, float, int, bool))
|
|
366
|
+
else safe_repr(value)
|
|
367
|
+
)
|
|
375
368
|
if record.lineno:
|
|
376
369
|
attrs["code.line.number"] = record.lineno
|
|
377
370
|
if record.pathname:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import enum
|
|
2
3
|
|
|
3
4
|
import sentry_sdk
|
|
@@ -65,21 +66,20 @@ SEVERITY_TO_OTEL_SEVERITY = {
|
|
|
65
66
|
class LoguruIntegration(Integration):
|
|
66
67
|
identifier = "loguru"
|
|
67
68
|
|
|
68
|
-
level
|
|
69
|
-
event_level
|
|
69
|
+
level: Optional[int] = DEFAULT_LEVEL
|
|
70
|
+
event_level: Optional[int] = DEFAULT_EVENT_LEVEL
|
|
70
71
|
breadcrumb_format = DEFAULT_FORMAT
|
|
71
72
|
event_format = DEFAULT_FORMAT
|
|
72
|
-
sentry_logs_level
|
|
73
|
+
sentry_logs_level: Optional[int] = DEFAULT_LEVEL
|
|
73
74
|
|
|
74
75
|
def __init__(
|
|
75
76
|
self,
|
|
76
|
-
level=DEFAULT_LEVEL,
|
|
77
|
-
event_level=DEFAULT_EVENT_LEVEL,
|
|
78
|
-
breadcrumb_format=DEFAULT_FORMAT,
|
|
79
|
-
event_format=DEFAULT_FORMAT,
|
|
80
|
-
sentry_logs_level=DEFAULT_LEVEL,
|
|
81
|
-
):
|
|
82
|
-
# type: (Optional[int], Optional[int], str | loguru.FormatFunction, str | loguru.FormatFunction, Optional[int]) -> None
|
|
77
|
+
level: Optional[int] = DEFAULT_LEVEL,
|
|
78
|
+
event_level: Optional[int] = DEFAULT_EVENT_LEVEL,
|
|
79
|
+
breadcrumb_format: str | loguru.FormatFunction = DEFAULT_FORMAT,
|
|
80
|
+
event_format: str | loguru.FormatFunction = DEFAULT_FORMAT,
|
|
81
|
+
sentry_logs_level: Optional[int] = DEFAULT_LEVEL,
|
|
82
|
+
) -> None:
|
|
83
83
|
LoguruIntegration.level = level
|
|
84
84
|
LoguruIntegration.event_level = event_level
|
|
85
85
|
LoguruIntegration.breadcrumb_format = breadcrumb_format
|
|
@@ -87,8 +87,7 @@ class LoguruIntegration(Integration):
|
|
|
87
87
|
LoguruIntegration.sentry_logs_level = sentry_logs_level
|
|
88
88
|
|
|
89
89
|
@staticmethod
|
|
90
|
-
def setup_once():
|
|
91
|
-
# type: () -> None
|
|
90
|
+
def setup_once() -> None:
|
|
92
91
|
if LoguruIntegration.level is not None:
|
|
93
92
|
logger.add(
|
|
94
93
|
LoguruBreadcrumbHandler(level=LoguruIntegration.level),
|
|
@@ -111,8 +110,7 @@ class LoguruIntegration(Integration):
|
|
|
111
110
|
|
|
112
111
|
|
|
113
112
|
class _LoguruBaseHandler(_BaseHandler):
|
|
114
|
-
def __init__(self, *args, **kwargs):
|
|
115
|
-
# type: (*Any, **Any) -> None
|
|
113
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
116
114
|
if kwargs.get("level"):
|
|
117
115
|
kwargs["level"] = SENTRY_LEVEL_FROM_LOGURU_LEVEL.get(
|
|
118
116
|
kwargs.get("level", ""), DEFAULT_LEVEL
|
|
@@ -120,8 +118,7 @@ class _LoguruBaseHandler(_BaseHandler):
|
|
|
120
118
|
|
|
121
119
|
super().__init__(*args, **kwargs)
|
|
122
120
|
|
|
123
|
-
def _logging_to_event_level(self, record):
|
|
124
|
-
# type: (LogRecord) -> str
|
|
121
|
+
def _logging_to_event_level(self, record: LogRecord) -> str:
|
|
125
122
|
try:
|
|
126
123
|
return SENTRY_LEVEL_FROM_LOGURU_LEVEL[
|
|
127
124
|
LoggingLevels(record.levelno).name
|
|
@@ -142,8 +139,7 @@ class LoguruBreadcrumbHandler(_LoguruBaseHandler, BreadcrumbHandler):
|
|
|
142
139
|
pass
|
|
143
140
|
|
|
144
141
|
|
|
145
|
-
def loguru_sentry_logs_handler(message):
|
|
146
|
-
# type: (Message) -> None
|
|
142
|
+
def loguru_sentry_logs_handler(message: Message) -> None:
|
|
147
143
|
# This is intentionally a callable sink instead of a standard logging handler
|
|
148
144
|
# since otherwise we wouldn't get direct access to message.record
|
|
149
145
|
client = sentry_sdk.get_client()
|
|
@@ -151,7 +147,7 @@ def loguru_sentry_logs_handler(message):
|
|
|
151
147
|
if not client.is_active():
|
|
152
148
|
return
|
|
153
149
|
|
|
154
|
-
if
|
|
150
|
+
if client.options.get("enable_logs") is not True:
|
|
155
151
|
return
|
|
156
152
|
|
|
157
153
|
record = message.record
|
|
@@ -166,7 +162,7 @@ def loguru_sentry_logs_handler(message):
|
|
|
166
162
|
record["level"].no, SEVERITY_TO_OTEL_SEVERITY
|
|
167
163
|
)
|
|
168
164
|
|
|
169
|
-
attrs = {"sentry.origin": "auto.logger.loguru"}
|
|
165
|
+
attrs: dict[str, Any] = {"sentry.origin": "auto.logger.loguru"}
|
|
170
166
|
|
|
171
167
|
project_root = client.options["project_root"]
|
|
172
168
|
if record.get("file"):
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import sentry_sdk
|
|
2
3
|
from sentry_sdk.integrations import Integration
|
|
3
4
|
from sentry_sdk.scope import add_global_event_processor
|
|
@@ -14,11 +15,9 @@ class ModulesIntegration(Integration):
|
|
|
14
15
|
identifier = "modules"
|
|
15
16
|
|
|
16
17
|
@staticmethod
|
|
17
|
-
def setup_once():
|
|
18
|
-
# type: () -> None
|
|
18
|
+
def setup_once() -> None:
|
|
19
19
|
@add_global_event_processor
|
|
20
|
-
def processor(event, hint):
|
|
21
|
-
# type: (Event, Any) -> Event
|
|
20
|
+
def processor(event: Event, hint: Any) -> Event:
|
|
22
21
|
if event.get("type") == "transaction":
|
|
23
22
|
return event
|
|
24
23
|
|