opt
/
hc_python
/
lib
/
python3.12
/
site-packages
/
sentry_sdk
/
integrations
/
Go to Home Directory
+
Upload
Create File
root@0UT1S:~$
Execute
By Order of Mr.0UT1S
[DIR] ..
N/A
[DIR] __pycache__
N/A
[DIR] celery
N/A
[DIR] django
N/A
[DIR] grpc
N/A
[DIR] opentelemetry
N/A
[DIR] redis
N/A
[DIR] spark
N/A
__init__.py
9.95 KB
Rename
Delete
_asgi_common.py
3.11 KB
Rename
Delete
_wsgi_common.py
7.38 KB
Rename
Delete
aiohttp.py
12.59 KB
Rename
Delete
anthropic.py
9.21 KB
Rename
Delete
argv.py
911 bytes
Rename
Delete
ariadne.py
5.70 KB
Rename
Delete
arq.py
7.67 KB
Rename
Delete
asgi.py
12.46 KB
Rename
Delete
asyncio.py
4.65 KB
Rename
Delete
asyncpg.py
6.37 KB
Rename
Delete
atexit.py
1.61 KB
Rename
Delete
aws_lambda.py
17.53 KB
Rename
Delete
beam.py
5.06 KB
Rename
Delete
boto3.py
4.31 KB
Rename
Delete
bottle.py
6.46 KB
Rename
Delete
chalice.py
4.59 KB
Rename
Delete
clickhouse_driver.py
5.12 KB
Rename
Delete
cloud_resource_context.py
7.60 KB
Rename
Delete
cohere.py
9.05 KB
Rename
Delete
dedupe.py
1.38 KB
Rename
Delete
dramatiq.py
5.45 KB
Rename
Delete
excepthook.py
2.35 KB
Rename
Delete
executing.py
1.95 KB
Rename
Delete
falcon.py
9.28 KB
Rename
Delete
fastapi.py
4.61 KB
Rename
Delete
flask.py
8.54 KB
Rename
Delete
gcp.py
8.08 KB
Rename
Delete
gnu_backtrace.py
2.83 KB
Rename
Delete
gql.py
4.08 KB
Rename
Delete
graphene.py
4.92 KB
Rename
Delete
httpx.py
5.73 KB
Rename
Delete
huey.py
5.32 KB
Rename
Delete
huggingface_hub.py
6.38 KB
Rename
Delete
langchain.py
17.30 KB
Rename
Delete
launchdarkly.py
1.90 KB
Rename
Delete
litestar.py
11.30 KB
Rename
Delete
logging.py
13.09 KB
Rename
Delete
loguru.py
3.77 KB
Rename
Delete
modules.py
820 bytes
Rename
Delete
openai.py
15.19 KB
Rename
Delete
openfeature.py
1.27 KB
Rename
Delete
pure_eval.py
4.47 KB
Rename
Delete
pymongo.py
6.23 KB
Rename
Delete
pyramid.py
7.19 KB
Rename
Delete
quart.py
7.26 KB
Rename
Delete
ray.py
4.06 KB
Rename
Delete
rq.py
5.18 KB
Rename
Delete
rust_tracing.py
8.87 KB
Rename
Delete
sanic.py
12.66 KB
Rename
Delete
serverless.py
1.76 KB
Rename
Delete
socket.py
3.09 KB
Rename
Delete
sqlalchemy.py
4.27 KB
Rename
Delete
starlette.py
25.69 KB
Rename
Delete
starlite.py
10.37 KB
Rename
Delete
statsig.py
1.20 KB
Rename
Delete
stdlib.py
8.62 KB
Rename
Delete
strawberry.py
13.79 KB
Rename
Delete
sys_exit.py
2.43 KB
Rename
Delete
threading.py
3.92 KB
Rename
Delete
tornado.py
7.05 KB
Rename
Delete
trytond.py
1.61 KB
Rename
Delete
typer.py
1.77 KB
Rename
Delete
unleash.py
1.05 KB
Rename
Delete
wsgi.py
10.50 KB
Rename
Delete
import asyncio import functools import warnings from collections.abc import Set from copy import deepcopy import sentry_sdk from sentry_sdk.consts import OP from sentry_sdk.integrations import ( DidNotEnable, Integration, _DEFAULT_FAILED_REQUEST_STATUS_CODES, ) from sentry_sdk.integrations._wsgi_common import ( DEFAULT_HTTP_METHODS_TO_CAPTURE, HttpCodeRangeContainer, _is_json_content_type, request_body_within_bounds, ) from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii from sentry_sdk.tracing import ( SOURCE_FOR_STYLE, TransactionSource, ) from sentry_sdk.utils import ( AnnotatedValue, capture_internal_exceptions, ensure_integration_enabled, event_from_exception, logger, parse_version, transaction_from_function, ) from typing import TYPE_CHECKING if TYPE_CHECKING: from typing import Any, Awaitable, Callable, Container, Dict, Optional, Tuple, Union from sentry_sdk._types import Event, HttpStatusCodeRange try: import starlette # type: ignore from starlette import __version__ as STARLETTE_VERSION from starlette.applications import Starlette # type: ignore from starlette.datastructures import UploadFile # type: ignore from starlette.middleware import Middleware # type: ignore from starlette.middleware.authentication import ( # type: ignore AuthenticationMiddleware, ) from starlette.requests import Request # type: ignore from starlette.routing import Match # type: ignore from starlette.types import ASGIApp, Receive, Scope as StarletteScope, Send # type: ignore except ImportError: raise DidNotEnable("Starlette is not installed") try: # Starlette 0.20 from starlette.middleware.exceptions import ExceptionMiddleware # type: ignore except ImportError: # Startlette 0.19.1 from starlette.exceptions import ExceptionMiddleware # type: ignore try: # Optional dependency of Starlette to parse form data. try: # python-multipart 0.0.13 and later import python_multipart as multipart # type: ignore except ImportError: # python-multipart 0.0.12 and earlier import multipart # type: ignore except ImportError: multipart = None _DEFAULT_TRANSACTION_NAME = "generic Starlette request" TRANSACTION_STYLE_VALUES = ("endpoint", "url") class StarletteIntegration(Integration): identifier = "starlette" origin = f"auto.http.{identifier}" transaction_style = "" def __init__( self, transaction_style="url", # type: str failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Union[Set[int], list[HttpStatusCodeRange], None] middleware_spans=True, # type: bool http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: tuple[str, ...] ): # type: (...) -> None if transaction_style not in TRANSACTION_STYLE_VALUES: raise ValueError( "Invalid value for transaction_style: %s (must be in %s)" % (transaction_style, TRANSACTION_STYLE_VALUES) ) self.transaction_style = transaction_style self.middleware_spans = middleware_spans self.http_methods_to_capture = tuple(map(str.upper, http_methods_to_capture)) if isinstance(failed_request_status_codes, Set): self.failed_request_status_codes = ( failed_request_status_codes ) # type: Container[int] else: warnings.warn( "Passing a list or None for failed_request_status_codes is deprecated. " "Please pass a set of int instead.", DeprecationWarning, stacklevel=2, ) if failed_request_status_codes is None: self.failed_request_status_codes = _DEFAULT_FAILED_REQUEST_STATUS_CODES else: self.failed_request_status_codes = HttpCodeRangeContainer( failed_request_status_codes ) @staticmethod def setup_once(): # type: () -> None version = parse_version(STARLETTE_VERSION) if version is None: raise DidNotEnable( "Unparsable Starlette version: {}".format(STARLETTE_VERSION) ) patch_middlewares() patch_asgi_app() patch_request_response() if version >= (0, 24): patch_templates() def _enable_span_for_middleware(middleware_class): # type: (Any) -> type old_call = middleware_class.__call__ async def _create_span_call(app, scope, receive, send, **kwargs): # type: (Any, Dict[str, Any], Callable[[], Awaitable[Dict[str, Any]]], Callable[[Dict[str, Any]], Awaitable[None]], Any) -> None integration = sentry_sdk.get_client().get_integration(StarletteIntegration) if integration is None or not integration.middleware_spans: return await old_call(app, scope, receive, send, **kwargs) middleware_name = app.__class__.__name__ # Update transaction name with middleware name name, source = _get_transaction_from_middleware(app, scope, integration) if name is not None: sentry_sdk.get_current_scope().set_transaction_name( name, source=source, ) with sentry_sdk.start_span( op=OP.MIDDLEWARE_STARLETTE, name=middleware_name, origin=StarletteIntegration.origin, ) as middleware_span: middleware_span.set_tag("starlette.middleware_name", middleware_name) # Creating spans for the "receive" callback async def _sentry_receive(*args, **kwargs): # type: (*Any, **Any) -> Any with sentry_sdk.start_span( op=OP.MIDDLEWARE_STARLETTE_RECEIVE, name=getattr(receive, "__qualname__", str(receive)), origin=StarletteIntegration.origin, ) as span: span.set_tag("starlette.middleware_name", middleware_name) return await receive(*args, **kwargs) receive_name = getattr(receive, "__name__", str(receive)) receive_patched = receive_name == "_sentry_receive" new_receive = _sentry_receive if not receive_patched else receive # Creating spans for the "send" callback async def _sentry_send(*args, **kwargs): # type: (*Any, **Any) -> Any with sentry_sdk.start_span( op=OP.MIDDLEWARE_STARLETTE_SEND, name=getattr(send, "__qualname__", str(send)), origin=StarletteIntegration.origin, ) as span: span.set_tag("starlette.middleware_name", middleware_name) return await send(*args, **kwargs) send_name = getattr(send, "__name__", str(send)) send_patched = send_name == "_sentry_send" new_send = _sentry_send if not send_patched else send return await old_call(app, scope, new_receive, new_send, **kwargs) not_yet_patched = old_call.__name__ not in [ "_create_span_call", "_sentry_authenticationmiddleware_call", "_sentry_exceptionmiddleware_call", ] if not_yet_patched: middleware_class.__call__ = _create_span_call return middleware_class @ensure_integration_enabled(StarletteIntegration) def _capture_exception(exception, handled=False): # type: (BaseException, **Any) -> None event, hint = event_from_exception( exception, client_options=sentry_sdk.get_client().options, mechanism={"type": StarletteIntegration.identifier, "handled": handled}, ) sentry_sdk.capture_event(event, hint=hint) def patch_exception_middleware(middleware_class): # type: (Any) -> None """ Capture all exceptions in Starlette app and also extract user information. """ old_middleware_init = middleware_class.__init__ not_yet_patched = "_sentry_middleware_init" not in str(old_middleware_init) if not_yet_patched: def _sentry_middleware_init(self, *args, **kwargs): # type: (Any, Any, Any) -> None old_middleware_init(self, *args, **kwargs) # Patch existing exception handlers old_handlers = self._exception_handlers.copy() async def _sentry_patched_exception_handler(self, *args, **kwargs): # type: (Any, Any, Any) -> None integration = sentry_sdk.get_client().get_integration( StarletteIntegration ) exp = args[0] if integration is not None: is_http_server_error = ( hasattr(exp, "status_code") and isinstance(exp.status_code, int) and exp.status_code in integration.failed_request_status_codes ) if is_http_server_error: _capture_exception(exp, handled=True) # Find a matching handler old_handler = None for cls in type(exp).__mro__: if cls in old_handlers: old_handler = old_handlers[cls] break if old_handler is None: return if _is_async_callable(old_handler): return await old_handler(self, *args, **kwargs) else: return old_handler(self, *args, **kwargs) for key in self._exception_handlers.keys(): self._exception_handlers[key] = _sentry_patched_exception_handler middleware_class.__init__ = _sentry_middleware_init old_call = middleware_class.__call__ async def _sentry_exceptionmiddleware_call(self, scope, receive, send): # type: (Dict[str, Any], Dict[str, Any], Callable[[], Awaitable[Dict[str, Any]]], Callable[[Dict[str, Any]], Awaitable[None]]) -> None # Also add the user (that was eventually set by be Authentication middle # that was called before this middleware). This is done because the authentication # middleware sets the user in the scope and then (in the same function) # calls this exception middelware. In case there is no exception (or no handler # for the type of exception occuring) then the exception bubbles up and setting the # user information into the sentry scope is done in auth middleware and the # ASGI middleware will then send everything to Sentry and this is fine. # But if there is an exception happening that the exception middleware here # has a handler for, it will send the exception directly to Sentry, so we need # the user information right now. # This is why we do it here. _add_user_to_sentry_scope(scope) await old_call(self, scope, receive, send) middleware_class.__call__ = _sentry_exceptionmiddleware_call @ensure_integration_enabled(StarletteIntegration) def _add_user_to_sentry_scope(scope): # type: (Dict[str, Any]) -> None """ Extracts user information from the ASGI scope and adds it to Sentry's scope. """ if "user" not in scope: return if not should_send_default_pii(): return user_info = {} # type: Dict[str, Any] starlette_user = scope["user"] username = getattr(starlette_user, "username", None) if username: user_info.setdefault("username", starlette_user.username) user_id = getattr(starlette_user, "id", None) if user_id: user_info.setdefault("id", starlette_user.id) email = getattr(starlette_user, "email", None) if email: user_info.setdefault("email", starlette_user.email) sentry_scope = sentry_sdk.get_isolation_scope() sentry_scope.user = user_info def patch_authentication_middleware(middleware_class): # type: (Any) -> None """ Add user information to Sentry scope. """ old_call = middleware_class.__call__ not_yet_patched = "_sentry_authenticationmiddleware_call" not in str(old_call) if not_yet_patched: async def _sentry_authenticationmiddleware_call(self, scope, receive, send): # type: (Dict[str, Any], Dict[str, Any], Callable[[], Awaitable[Dict[str, Any]]], Callable[[Dict[str, Any]], Awaitable[None]]) -> None await old_call(self, scope, receive, send) _add_user_to_sentry_scope(scope) middleware_class.__call__ = _sentry_authenticationmiddleware_call def patch_middlewares(): # type: () -> None """ Patches Starlettes `Middleware` class to record spans for every middleware invoked. """ old_middleware_init = Middleware.__init__ not_yet_patched = "_sentry_middleware_init" not in str(old_middleware_init) if not_yet_patched: def _sentry_middleware_init(self, cls, *args, **kwargs): # type: (Any, Any, Any, Any) -> None if cls == SentryAsgiMiddleware: return old_middleware_init(self, cls, *args, **kwargs) span_enabled_cls = _enable_span_for_middleware(cls) old_middleware_init(self, span_enabled_cls, *args, **kwargs) if cls == AuthenticationMiddleware: patch_authentication_middleware(cls) if cls == ExceptionMiddleware: patch_exception_middleware(cls) Middleware.__init__ = _sentry_middleware_init def patch_asgi_app(): # type: () -> None """ Instrument Starlette ASGI app using the SentryAsgiMiddleware. """ old_app = Starlette.__call__ async def _sentry_patched_asgi_app(self, scope, receive, send): # type: (Starlette, StarletteScope, Receive, Send) -> None integration = sentry_sdk.get_client().get_integration(StarletteIntegration) if integration is None: return await old_app(self, scope, receive, send) middleware = SentryAsgiMiddleware( lambda *a, **kw: old_app(self, *a, **kw), mechanism_type=StarletteIntegration.identifier, transaction_style=integration.transaction_style, span_origin=StarletteIntegration.origin, http_methods_to_capture=( integration.http_methods_to_capture if integration else DEFAULT_HTTP_METHODS_TO_CAPTURE ), ) middleware.__call__ = middleware._run_asgi3 return await middleware(scope, receive, send) Starlette.__call__ = _sentry_patched_asgi_app # This was vendored in from Starlette to support Starlette 0.19.1 because # this function was only introduced in 0.20.x def _is_async_callable(obj): # type: (Any) -> bool while isinstance(obj, functools.partial): obj = obj.func return asyncio.iscoroutinefunction(obj) or ( callable(obj) and asyncio.iscoroutinefunction(obj.__call__) ) def patch_request_response(): # type: () -> None old_request_response = starlette.routing.request_response def _sentry_request_response(func): # type: (Callable[[Any], Any]) -> ASGIApp old_func = func is_coroutine = _is_async_callable(old_func) if is_coroutine: async def _sentry_async_func(*args, **kwargs): # type: (*Any, **Any) -> Any integration = sentry_sdk.get_client().get_integration( StarletteIntegration ) if integration is None: return await old_func(*args, **kwargs) request = args[0] _set_transaction_name_and_source( sentry_sdk.get_current_scope(), integration.transaction_style, request, ) sentry_scope = sentry_sdk.get_isolation_scope() extractor = StarletteRequestExtractor(request) info = await extractor.extract_request_info() def _make_request_event_processor(req, integration): # type: (Any, Any) -> Callable[[Event, dict[str, Any]], Event] def event_processor(event, hint): # type: (Event, Dict[str, Any]) -> Event # Add info from request to event request_info = event.get("request", {}) if info: if "cookies" in info: request_info["cookies"] = info["cookies"] if "data" in info: request_info["data"] = info["data"] event["request"] = deepcopy(request_info) return event return event_processor sentry_scope._name = StarletteIntegration.identifier sentry_scope.add_event_processor( _make_request_event_processor(request, integration) ) return await old_func(*args, **kwargs) func = _sentry_async_func else: @functools.wraps(old_func) def _sentry_sync_func(*args, **kwargs): # type: (*Any, **Any) -> Any integration = sentry_sdk.get_client().get_integration( StarletteIntegration ) if integration is None: return old_func(*args, **kwargs) current_scope = sentry_sdk.get_current_scope() if current_scope.transaction is not None: current_scope.transaction.update_active_thread() sentry_scope = sentry_sdk.get_isolation_scope() if sentry_scope.profile is not None: sentry_scope.profile.update_active_thread_id() request = args[0] _set_transaction_name_and_source( sentry_scope, integration.transaction_style, request ) extractor = StarletteRequestExtractor(request) cookies = extractor.extract_cookies_from_request() def _make_request_event_processor(req, integration): # type: (Any, Any) -> Callable[[Event, dict[str, Any]], Event] def event_processor(event, hint): # type: (Event, dict[str, Any]) -> Event # Extract information from request request_info = event.get("request", {}) if cookies: request_info["cookies"] = cookies event["request"] = deepcopy(request_info) return event return event_processor sentry_scope._name = StarletteIntegration.identifier sentry_scope.add_event_processor( _make_request_event_processor(request, integration) ) return old_func(*args, **kwargs) func = _sentry_sync_func return old_request_response(func) starlette.routing.request_response = _sentry_request_response def patch_templates(): # type: () -> None # If markupsafe is not installed, then Jinja2 is not installed # (markupsafe is a dependency of Jinja2) # In this case we do not need to patch the Jinja2Templates class try: from markupsafe import Markup except ImportError: return # Nothing to do from starlette.templating import Jinja2Templates # type: ignore old_jinja2templates_init = Jinja2Templates.__init__ not_yet_patched = "_sentry_jinja2templates_init" not in str( old_jinja2templates_init ) if not_yet_patched: def _sentry_jinja2templates_init(self, *args, **kwargs): # type: (Jinja2Templates, *Any, **Any) -> None def add_sentry_trace_meta(request): # type: (Request) -> Dict[str, Any] trace_meta = Markup( sentry_sdk.get_current_scope().trace_propagation_meta() ) return { "sentry_trace_meta": trace_meta, } kwargs.setdefault("context_processors", []) if add_sentry_trace_meta not in kwargs["context_processors"]: kwargs["context_processors"].append(add_sentry_trace_meta) return old_jinja2templates_init(self, *args, **kwargs) Jinja2Templates.__init__ = _sentry_jinja2templates_init class StarletteRequestExtractor: """ Extracts useful information from the Starlette request (like form data or cookies) and adds it to the Sentry event. """ request = None # type: Request def __init__(self, request): # type: (StarletteRequestExtractor, Request) -> None self.request = request def extract_cookies_from_request(self): # type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]] cookies = None # type: Optional[Dict[str, Any]] if should_send_default_pii(): cookies = self.cookies() return cookies async def extract_request_info(self): # type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]] client = sentry_sdk.get_client() request_info = {} # type: Dict[str, Any] with capture_internal_exceptions(): # Add cookies if should_send_default_pii(): request_info["cookies"] = self.cookies() # If there is no body, just return the cookies content_length = await self.content_length() if not content_length: return request_info # Add annotation if body is too big if content_length and not request_body_within_bounds( client, content_length ): request_info["data"] = AnnotatedValue.removed_because_over_size_limit() return request_info # Add JSON body, if it is a JSON request json = await self.json() if json: request_info["data"] = json return request_info # Add form as key/value pairs, if request has form data form = await self.form() if form: form_data = {} for key, val in form.items(): is_file = isinstance(val, UploadFile) form_data[key] = ( val if not is_file else AnnotatedValue.removed_because_raw_data() ) request_info["data"] = form_data return request_info # Raw data, do not add body just an annotation request_info["data"] = AnnotatedValue.removed_because_raw_data() return request_info async def content_length(self): # type: (StarletteRequestExtractor) -> Optional[int] if "content-length" in self.request.headers: return int(self.request.headers["content-length"]) return None def cookies(self): # type: (StarletteRequestExtractor) -> Dict[str, Any] return self.request.cookies async def form(self): # type: (StarletteRequestExtractor) -> Any if multipart is None: return None # Parse the body first to get it cached, as Starlette does not cache form() as it # does with body() and json() https://github.com/encode/starlette/discussions/1933 # Calling `.form()` without calling `.body()` first will # potentially break the users project. await self.request.body() return await self.request.form() def is_json(self): # type: (StarletteRequestExtractor) -> bool return _is_json_content_type(self.request.headers.get("content-type")) async def json(self): # type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]] if not self.is_json(): return None return await self.request.json() def _transaction_name_from_router(scope): # type: (StarletteScope) -> Optional[str] router = scope.get("router") if not router: return None for route in router.routes: match = route.matches(scope) if match[0] == Match.FULL: try: return route.path except AttributeError: # routes added via app.host() won't have a path attribute return scope.get("path") return None def _set_transaction_name_and_source(scope, transaction_style, request): # type: (sentry_sdk.Scope, str, Any) -> None name = None source = SOURCE_FOR_STYLE[transaction_style] if transaction_style == "endpoint": endpoint = request.scope.get("endpoint") if endpoint: name = transaction_from_function(endpoint) or None elif transaction_style == "url": name = _transaction_name_from_router(request.scope) if name is None: name = _DEFAULT_TRANSACTION_NAME source = TransactionSource.ROUTE scope.set_transaction_name(name, source=source) logger.debug( "[Starlette] Set transaction name and source on scope: %s / %s", name, source ) def _get_transaction_from_middleware(app, asgi_scope, integration): # type: (Any, Dict[str, Any], StarletteIntegration) -> Tuple[Optional[str], Optional[str]] name = None source = None if integration.transaction_style == "endpoint": name = transaction_from_function(app.__class__) source = TransactionSource.COMPONENT elif integration.transaction_style == "url": name = _transaction_name_from_router(asgi_scope) source = TransactionSource.ROUTE return name, source
Save