您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

476 行
12 KiB

  1. import inspect
  2. import warnings
  3. from contextlib import contextmanager
  4. from sentry_sdk import tracing_utils, Client
  5. from sentry_sdk._init_implementation import init
  6. from sentry_sdk.consts import INSTRUMENTER
  7. from sentry_sdk.scope import Scope, _ScopeManager, new_scope, isolation_scope
  8. from sentry_sdk.tracing import NoOpSpan, Transaction, trace
  9. from sentry_sdk.crons import monitor
  10. from typing import TYPE_CHECKING
  11. if TYPE_CHECKING:
  12. from collections.abc import Mapping
  13. from typing import Any
  14. from typing import Dict
  15. from typing import Generator
  16. from typing import Optional
  17. from typing import overload
  18. from typing import Callable
  19. from typing import TypeVar
  20. from typing import ContextManager
  21. from typing import Union
  22. from typing_extensions import Unpack
  23. from sentry_sdk.client import BaseClient
  24. from sentry_sdk._types import (
  25. Event,
  26. Hint,
  27. Breadcrumb,
  28. BreadcrumbHint,
  29. ExcInfo,
  30. MeasurementUnit,
  31. LogLevelStr,
  32. SamplingContext,
  33. )
  34. from sentry_sdk.tracing import Span, TransactionKwargs
  35. T = TypeVar("T")
  36. F = TypeVar("F", bound=Callable[..., Any])
  37. else:
  38. def overload(x):
  39. # type: (T) -> T
  40. return x
  41. # When changing this, update __all__ in __init__.py too
  42. __all__ = [
  43. "init",
  44. "add_attachment",
  45. "add_breadcrumb",
  46. "capture_event",
  47. "capture_exception",
  48. "capture_message",
  49. "configure_scope",
  50. "continue_trace",
  51. "flush",
  52. "get_baggage",
  53. "get_client",
  54. "get_global_scope",
  55. "get_isolation_scope",
  56. "get_current_scope",
  57. "get_current_span",
  58. "get_traceparent",
  59. "is_initialized",
  60. "isolation_scope",
  61. "last_event_id",
  62. "new_scope",
  63. "push_scope",
  64. "set_context",
  65. "set_extra",
  66. "set_level",
  67. "set_measurement",
  68. "set_tag",
  69. "set_tags",
  70. "set_user",
  71. "start_span",
  72. "start_transaction",
  73. "trace",
  74. "monitor",
  75. "start_session",
  76. "end_session",
  77. "set_transaction_name",
  78. ]
  79. def scopemethod(f):
  80. # type: (F) -> F
  81. f.__doc__ = "%s\n\n%s" % (
  82. "Alias for :py:meth:`sentry_sdk.Scope.%s`" % f.__name__,
  83. inspect.getdoc(getattr(Scope, f.__name__)),
  84. )
  85. return f
  86. def clientmethod(f):
  87. # type: (F) -> F
  88. f.__doc__ = "%s\n\n%s" % (
  89. "Alias for :py:meth:`sentry_sdk.Client.%s`" % f.__name__,
  90. inspect.getdoc(getattr(Client, f.__name__)),
  91. )
  92. return f
  93. @scopemethod
  94. def get_client():
  95. # type: () -> BaseClient
  96. return Scope.get_client()
  97. def is_initialized():
  98. # type: () -> bool
  99. """
  100. .. versionadded:: 2.0.0
  101. Returns whether Sentry has been initialized or not.
  102. If a client is available and the client is active
  103. (meaning it is configured to send data) then
  104. Sentry is initialized.
  105. """
  106. return get_client().is_active()
  107. @scopemethod
  108. def get_global_scope():
  109. # type: () -> Scope
  110. return Scope.get_global_scope()
  111. @scopemethod
  112. def get_isolation_scope():
  113. # type: () -> Scope
  114. return Scope.get_isolation_scope()
  115. @scopemethod
  116. def get_current_scope():
  117. # type: () -> Scope
  118. return Scope.get_current_scope()
  119. @scopemethod
  120. def last_event_id():
  121. # type: () -> Optional[str]
  122. """
  123. See :py:meth:`sentry_sdk.Scope.last_event_id` documentation regarding
  124. this method's limitations.
  125. """
  126. return Scope.last_event_id()
  127. @scopemethod
  128. def capture_event(
  129. event, # type: Event
  130. hint=None, # type: Optional[Hint]
  131. scope=None, # type: Optional[Any]
  132. **scope_kwargs, # type: Any
  133. ):
  134. # type: (...) -> Optional[str]
  135. return get_current_scope().capture_event(event, hint, scope=scope, **scope_kwargs)
  136. @scopemethod
  137. def capture_message(
  138. message, # type: str
  139. level=None, # type: Optional[LogLevelStr]
  140. scope=None, # type: Optional[Any]
  141. **scope_kwargs, # type: Any
  142. ):
  143. # type: (...) -> Optional[str]
  144. return get_current_scope().capture_message(
  145. message, level, scope=scope, **scope_kwargs
  146. )
  147. @scopemethod
  148. def capture_exception(
  149. error=None, # type: Optional[Union[BaseException, ExcInfo]]
  150. scope=None, # type: Optional[Any]
  151. **scope_kwargs, # type: Any
  152. ):
  153. # type: (...) -> Optional[str]
  154. return get_current_scope().capture_exception(error, scope=scope, **scope_kwargs)
  155. @scopemethod
  156. def add_attachment(
  157. bytes=None, # type: Union[None, bytes, Callable[[], bytes]]
  158. filename=None, # type: Optional[str]
  159. path=None, # type: Optional[str]
  160. content_type=None, # type: Optional[str]
  161. add_to_transactions=False, # type: bool
  162. ):
  163. # type: (...) -> None
  164. return get_isolation_scope().add_attachment(
  165. bytes, filename, path, content_type, add_to_transactions
  166. )
  167. @scopemethod
  168. def add_breadcrumb(
  169. crumb=None, # type: Optional[Breadcrumb]
  170. hint=None, # type: Optional[BreadcrumbHint]
  171. **kwargs, # type: Any
  172. ):
  173. # type: (...) -> None
  174. return get_isolation_scope().add_breadcrumb(crumb, hint, **kwargs)
  175. @overload
  176. def configure_scope():
  177. # type: () -> ContextManager[Scope]
  178. pass
  179. @overload
  180. def configure_scope( # noqa: F811
  181. callback, # type: Callable[[Scope], None]
  182. ):
  183. # type: (...) -> None
  184. pass
  185. def configure_scope( # noqa: F811
  186. callback=None, # type: Optional[Callable[[Scope], None]]
  187. ):
  188. # type: (...) -> Optional[ContextManager[Scope]]
  189. """
  190. Reconfigures the scope.
  191. :param callback: If provided, call the callback with the current scope.
  192. :returns: If no callback is provided, returns a context manager that returns the scope.
  193. """
  194. warnings.warn(
  195. "sentry_sdk.configure_scope is deprecated and will be removed in the next major version. "
  196. "Please consult our migration guide to learn how to migrate to the new API: "
  197. "https://docs.sentry.io/platforms/python/migration/1.x-to-2.x#scope-configuring",
  198. DeprecationWarning,
  199. stacklevel=2,
  200. )
  201. scope = get_isolation_scope()
  202. scope.generate_propagation_context()
  203. if callback is not None:
  204. # TODO: used to return None when client is None. Check if this changes behavior.
  205. callback(scope)
  206. return None
  207. @contextmanager
  208. def inner():
  209. # type: () -> Generator[Scope, None, None]
  210. yield scope
  211. return inner()
  212. @overload
  213. def push_scope():
  214. # type: () -> ContextManager[Scope]
  215. pass
  216. @overload
  217. def push_scope( # noqa: F811
  218. callback, # type: Callable[[Scope], None]
  219. ):
  220. # type: (...) -> None
  221. pass
  222. def push_scope( # noqa: F811
  223. callback=None, # type: Optional[Callable[[Scope], None]]
  224. ):
  225. # type: (...) -> Optional[ContextManager[Scope]]
  226. """
  227. Pushes a new layer on the scope stack.
  228. :param callback: If provided, this method pushes a scope, calls
  229. `callback`, and pops the scope again.
  230. :returns: If no `callback` is provided, a context manager that should
  231. be used to pop the scope again.
  232. """
  233. warnings.warn(
  234. "sentry_sdk.push_scope is deprecated and will be removed in the next major version. "
  235. "Please consult our migration guide to learn how to migrate to the new API: "
  236. "https://docs.sentry.io/platforms/python/migration/1.x-to-2.x#scope-pushing",
  237. DeprecationWarning,
  238. stacklevel=2,
  239. )
  240. if callback is not None:
  241. with warnings.catch_warnings():
  242. warnings.simplefilter("ignore", DeprecationWarning)
  243. with push_scope() as scope:
  244. callback(scope)
  245. return None
  246. return _ScopeManager()
  247. @scopemethod
  248. def set_tag(key, value):
  249. # type: (str, Any) -> None
  250. return get_isolation_scope().set_tag(key, value)
  251. @scopemethod
  252. def set_tags(tags):
  253. # type: (Mapping[str, object]) -> None
  254. return get_isolation_scope().set_tags(tags)
  255. @scopemethod
  256. def set_context(key, value):
  257. # type: (str, Dict[str, Any]) -> None
  258. return get_isolation_scope().set_context(key, value)
  259. @scopemethod
  260. def set_extra(key, value):
  261. # type: (str, Any) -> None
  262. return get_isolation_scope().set_extra(key, value)
  263. @scopemethod
  264. def set_user(value):
  265. # type: (Optional[Dict[str, Any]]) -> None
  266. return get_isolation_scope().set_user(value)
  267. @scopemethod
  268. def set_level(value):
  269. # type: (LogLevelStr) -> None
  270. return get_isolation_scope().set_level(value)
  271. @clientmethod
  272. def flush(
  273. timeout=None, # type: Optional[float]
  274. callback=None, # type: Optional[Callable[[int, float], None]]
  275. ):
  276. # type: (...) -> None
  277. return get_client().flush(timeout=timeout, callback=callback)
  278. @scopemethod
  279. def start_span(
  280. **kwargs, # type: Any
  281. ):
  282. # type: (...) -> Span
  283. return get_current_scope().start_span(**kwargs)
  284. @scopemethod
  285. def start_transaction(
  286. transaction=None, # type: Optional[Transaction]
  287. instrumenter=INSTRUMENTER.SENTRY, # type: str
  288. custom_sampling_context=None, # type: Optional[SamplingContext]
  289. **kwargs, # type: Unpack[TransactionKwargs]
  290. ):
  291. # type: (...) -> Union[Transaction, NoOpSpan]
  292. """
  293. Start and return a transaction on the current scope.
  294. Start an existing transaction if given, otherwise create and start a new
  295. transaction with kwargs.
  296. This is the entry point to manual tracing instrumentation.
  297. A tree structure can be built by adding child spans to the transaction,
  298. and child spans to other spans. To start a new child span within the
  299. transaction or any span, call the respective `.start_child()` method.
  300. Every child span must be finished before the transaction is finished,
  301. otherwise the unfinished spans are discarded.
  302. When used as context managers, spans and transactions are automatically
  303. finished at the end of the `with` block. If not using context managers,
  304. call the `.finish()` method.
  305. When the transaction is finished, it will be sent to Sentry with all its
  306. finished child spans.
  307. :param transaction: The transaction to start. If omitted, we create and
  308. start a new transaction.
  309. :param instrumenter: This parameter is meant for internal use only. It
  310. will be removed in the next major version.
  311. :param custom_sampling_context: The transaction's custom sampling context.
  312. :param kwargs: Optional keyword arguments to be passed to the Transaction
  313. constructor. See :py:class:`sentry_sdk.tracing.Transaction` for
  314. available arguments.
  315. """
  316. return get_current_scope().start_transaction(
  317. transaction, instrumenter, custom_sampling_context, **kwargs
  318. )
  319. def set_measurement(name, value, unit=""):
  320. # type: (str, float, MeasurementUnit) -> None
  321. """
  322. .. deprecated:: 2.28.0
  323. This function is deprecated and will be removed in the next major release.
  324. """
  325. transaction = get_current_scope().transaction
  326. if transaction is not None:
  327. transaction.set_measurement(name, value, unit)
  328. def get_current_span(scope=None):
  329. # type: (Optional[Scope]) -> Optional[Span]
  330. """
  331. Returns the currently active span if there is one running, otherwise `None`
  332. """
  333. return tracing_utils.get_current_span(scope)
  334. def get_traceparent():
  335. # type: () -> Optional[str]
  336. """
  337. Returns the traceparent either from the active span or from the scope.
  338. """
  339. return get_current_scope().get_traceparent()
  340. def get_baggage():
  341. # type: () -> Optional[str]
  342. """
  343. Returns Baggage either from the active span or from the scope.
  344. """
  345. baggage = get_current_scope().get_baggage()
  346. if baggage is not None:
  347. return baggage.serialize()
  348. return None
  349. def continue_trace(
  350. environ_or_headers, op=None, name=None, source=None, origin="manual"
  351. ):
  352. # type: (Dict[str, Any], Optional[str], Optional[str], Optional[str], str) -> Transaction
  353. """
  354. Sets the propagation context from environment or headers and returns a transaction.
  355. """
  356. return get_isolation_scope().continue_trace(
  357. environ_or_headers, op, name, source, origin
  358. )
  359. @scopemethod
  360. def start_session(
  361. session_mode="application", # type: str
  362. ):
  363. # type: (...) -> None
  364. return get_isolation_scope().start_session(session_mode=session_mode)
  365. @scopemethod
  366. def end_session():
  367. # type: () -> None
  368. return get_isolation_scope().end_session()
  369. @scopemethod
  370. def set_transaction_name(name, source=None):
  371. # type: (str, Optional[str]) -> None
  372. return get_current_scope().set_transaction_name(name, source)