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.

Files changed (159) hide show
  1. sentry_sdk/__init__.py +4 -0
  2. sentry_sdk/_compat.py +5 -12
  3. sentry_sdk/_init_implementation.py +7 -7
  4. sentry_sdk/_log_batcher.py +17 -29
  5. sentry_sdk/_lru_cache.py +7 -9
  6. sentry_sdk/_queue.py +2 -4
  7. sentry_sdk/_types.py +9 -16
  8. sentry_sdk/_werkzeug.py +5 -7
  9. sentry_sdk/ai/monitoring.py +45 -33
  10. sentry_sdk/ai/utils.py +8 -5
  11. sentry_sdk/api.py +91 -87
  12. sentry_sdk/attachments.py +10 -12
  13. sentry_sdk/client.py +119 -159
  14. sentry_sdk/consts.py +432 -223
  15. sentry_sdk/crons/api.py +16 -17
  16. sentry_sdk/crons/decorator.py +25 -27
  17. sentry_sdk/debug.py +4 -6
  18. sentry_sdk/envelope.py +46 -112
  19. sentry_sdk/feature_flags.py +9 -15
  20. sentry_sdk/integrations/__init__.py +24 -19
  21. sentry_sdk/integrations/_asgi_common.py +16 -18
  22. sentry_sdk/integrations/_wsgi_common.py +22 -33
  23. sentry_sdk/integrations/aiohttp.py +33 -31
  24. sentry_sdk/integrations/anthropic.py +43 -38
  25. sentry_sdk/integrations/argv.py +3 -4
  26. sentry_sdk/integrations/ariadne.py +16 -18
  27. sentry_sdk/integrations/arq.py +20 -29
  28. sentry_sdk/integrations/asgi.py +63 -37
  29. sentry_sdk/integrations/asyncio.py +15 -17
  30. sentry_sdk/integrations/asyncpg.py +1 -1
  31. sentry_sdk/integrations/atexit.py +6 -10
  32. sentry_sdk/integrations/aws_lambda.py +26 -36
  33. sentry_sdk/integrations/beam.py +10 -18
  34. sentry_sdk/integrations/boto3.py +20 -18
  35. sentry_sdk/integrations/bottle.py +25 -34
  36. sentry_sdk/integrations/celery/__init__.py +40 -59
  37. sentry_sdk/integrations/celery/beat.py +22 -26
  38. sentry_sdk/integrations/celery/utils.py +15 -17
  39. sentry_sdk/integrations/chalice.py +8 -10
  40. sentry_sdk/integrations/clickhouse_driver.py +22 -32
  41. sentry_sdk/integrations/cloud_resource_context.py +9 -16
  42. sentry_sdk/integrations/cohere.py +19 -25
  43. sentry_sdk/integrations/dedupe.py +5 -8
  44. sentry_sdk/integrations/django/__init__.py +69 -74
  45. sentry_sdk/integrations/django/asgi.py +25 -33
  46. sentry_sdk/integrations/django/caching.py +24 -20
  47. sentry_sdk/integrations/django/middleware.py +18 -21
  48. sentry_sdk/integrations/django/signals_handlers.py +12 -11
  49. sentry_sdk/integrations/django/templates.py +21 -18
  50. sentry_sdk/integrations/django/transactions.py +16 -11
  51. sentry_sdk/integrations/django/views.py +8 -12
  52. sentry_sdk/integrations/dramatiq.py +21 -21
  53. sentry_sdk/integrations/excepthook.py +10 -10
  54. sentry_sdk/integrations/executing.py +3 -4
  55. sentry_sdk/integrations/falcon.py +27 -42
  56. sentry_sdk/integrations/fastapi.py +13 -16
  57. sentry_sdk/integrations/flask.py +31 -38
  58. sentry_sdk/integrations/gcp.py +13 -16
  59. sentry_sdk/integrations/gnu_backtrace.py +7 -20
  60. sentry_sdk/integrations/gql.py +16 -17
  61. sentry_sdk/integrations/graphene.py +14 -13
  62. sentry_sdk/integrations/grpc/__init__.py +3 -2
  63. sentry_sdk/integrations/grpc/aio/client.py +2 -2
  64. sentry_sdk/integrations/grpc/aio/server.py +15 -14
  65. sentry_sdk/integrations/grpc/client.py +21 -11
  66. sentry_sdk/integrations/grpc/consts.py +2 -0
  67. sentry_sdk/integrations/grpc/server.py +12 -8
  68. sentry_sdk/integrations/httpx.py +11 -14
  69. sentry_sdk/integrations/huey.py +14 -21
  70. sentry_sdk/integrations/huggingface_hub.py +17 -17
  71. sentry_sdk/integrations/langchain.py +204 -114
  72. sentry_sdk/integrations/launchdarkly.py +13 -10
  73. sentry_sdk/integrations/litestar.py +40 -38
  74. sentry_sdk/integrations/logging.py +29 -36
  75. sentry_sdk/integrations/loguru.py +16 -20
  76. sentry_sdk/integrations/modules.py +3 -4
  77. sentry_sdk/integrations/openai.py +421 -204
  78. sentry_sdk/integrations/openai_agents/__init__.py +49 -0
  79. sentry_sdk/integrations/openai_agents/consts.py +1 -0
  80. sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
  81. sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
  82. sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
  83. sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
  84. sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
  85. sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
  86. sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
  87. sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
  88. sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
  89. sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
  90. sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
  91. sentry_sdk/integrations/openai_agents/utils.py +153 -0
  92. sentry_sdk/integrations/openfeature.py +12 -8
  93. sentry_sdk/integrations/pure_eval.py +6 -10
  94. sentry_sdk/integrations/pymongo.py +14 -18
  95. sentry_sdk/integrations/pyramid.py +31 -36
  96. sentry_sdk/integrations/quart.py +23 -28
  97. sentry_sdk/integrations/ray.py +73 -64
  98. sentry_sdk/integrations/redis/__init__.py +7 -4
  99. sentry_sdk/integrations/redis/_async_common.py +18 -12
  100. sentry_sdk/integrations/redis/_sync_common.py +16 -15
  101. sentry_sdk/integrations/redis/modules/caches.py +17 -8
  102. sentry_sdk/integrations/redis/modules/queries.py +9 -8
  103. sentry_sdk/integrations/redis/rb.py +3 -2
  104. sentry_sdk/integrations/redis/redis.py +4 -4
  105. sentry_sdk/integrations/redis/redis_cluster.py +10 -8
  106. sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
  107. sentry_sdk/integrations/redis/utils.py +21 -22
  108. sentry_sdk/integrations/rq.py +13 -16
  109. sentry_sdk/integrations/rust_tracing.py +10 -7
  110. sentry_sdk/integrations/sanic.py +34 -46
  111. sentry_sdk/integrations/serverless.py +22 -27
  112. sentry_sdk/integrations/socket.py +29 -17
  113. sentry_sdk/integrations/spark/__init__.py +1 -0
  114. sentry_sdk/integrations/spark/spark_driver.py +45 -83
  115. sentry_sdk/integrations/spark/spark_worker.py +7 -11
  116. sentry_sdk/integrations/sqlalchemy.py +22 -19
  117. sentry_sdk/integrations/starlette.py +89 -93
  118. sentry_sdk/integrations/starlite.py +31 -37
  119. sentry_sdk/integrations/statsig.py +5 -4
  120. sentry_sdk/integrations/stdlib.py +32 -28
  121. sentry_sdk/integrations/strawberry.py +63 -50
  122. sentry_sdk/integrations/sys_exit.py +7 -11
  123. sentry_sdk/integrations/threading.py +13 -15
  124. sentry_sdk/integrations/tornado.py +28 -32
  125. sentry_sdk/integrations/trytond.py +4 -3
  126. sentry_sdk/integrations/typer.py +8 -6
  127. sentry_sdk/integrations/unleash.py +5 -4
  128. sentry_sdk/integrations/wsgi.py +47 -46
  129. sentry_sdk/logger.py +13 -9
  130. sentry_sdk/monitor.py +16 -28
  131. sentry_sdk/opentelemetry/consts.py +11 -4
  132. sentry_sdk/opentelemetry/contextvars_context.py +17 -15
  133. sentry_sdk/opentelemetry/propagator.py +38 -21
  134. sentry_sdk/opentelemetry/sampler.py +51 -34
  135. sentry_sdk/opentelemetry/scope.py +46 -37
  136. sentry_sdk/opentelemetry/span_processor.py +43 -59
  137. sentry_sdk/opentelemetry/tracing.py +32 -12
  138. sentry_sdk/opentelemetry/utils.py +180 -196
  139. sentry_sdk/profiler/continuous_profiler.py +108 -97
  140. sentry_sdk/profiler/transaction_profiler.py +70 -97
  141. sentry_sdk/profiler/utils.py +11 -15
  142. sentry_sdk/scope.py +251 -264
  143. sentry_sdk/scrubber.py +22 -26
  144. sentry_sdk/serializer.py +48 -65
  145. sentry_sdk/session.py +44 -61
  146. sentry_sdk/sessions.py +35 -49
  147. sentry_sdk/spotlight.py +15 -21
  148. sentry_sdk/tracing.py +118 -184
  149. sentry_sdk/tracing_utils.py +103 -123
  150. sentry_sdk/transport.py +131 -157
  151. sentry_sdk/utils.py +278 -309
  152. sentry_sdk/worker.py +16 -28
  153. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/METADATA +1 -1
  154. sentry_sdk-3.0.0a4.dist-info/RECORD +168 -0
  155. sentry_sdk-3.0.0a2.dist-info/RECORD +0 -154
  156. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/WHEEL +0 -0
  157. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/entry_points.txt +0 -0
  158. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/licenses/LICENSE +0 -0
  159. {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=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Set[int]
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__(self, app, span_origin=LitestarIntegration.origin):
79
- # type: (ASGIApp, str) -> None
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__ # type: ASGIApp
145
+ old_call: ASGIApp = middleware.middleware.__call__
142
146
  else:
143
147
  old_call = middleware.__call__
144
148
 
145
- async def _create_span_call(self, scope, receive, send):
146
- # type: (MiddlewareProtocol, LitestarScope, Receive, Send) -> None
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
- only_if_parent=True,
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(*args, **kwargs):
161
- # type: (*Any, **Any) -> Union[HTTPReceiveMessage, WebSocketReceiveMessage]
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
- only_if_parent=True,
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
- only_if_parent=True,
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(self, scope, receive, send):
213
- # type: (HTTPRoute, HTTPScope, Receive, Send) -> None
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
- ) # type: Request[Any, Any]
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
- # type: (Exception, LitestarScope) -> None
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, # type: str
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 not client.options["_experiments"].get("enable_logs", False):
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) # type: Any
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 = DEFAULT_LEVEL # type: Optional[int]
69
- event_level = DEFAULT_EVENT_LEVEL # type: Optional[int]
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 = DEFAULT_LEVEL # type: Optional[int]
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 not client.options["_experiments"].get("enable_logs", False):
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"} # type: dict[str, Any]
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