diff --git a/authentik/brands/utils.py b/authentik/brands/utils.py index 5e6ef40ed3..6c68a04998 100644 --- a/authentik/brands/utils.py +++ b/authentik/brands/utils.py @@ -5,7 +5,7 @@ from typing import Any from django.db.models import F, Q from django.db.models import Value as V from django.http.request import HttpRequest -from sentry_sdk.hub import Hub +from sentry_sdk import get_current_span from authentik import get_full_version from authentik.brands.models import Brand @@ -33,7 +33,7 @@ def context_processor(request: HttpRequest) -> dict[str, Any]: brand = getattr(request, "brand", DEFAULT_BRAND) tenant = getattr(request, "tenant", Tenant()) trace = "" - span = Hub.current.scope.span + span = get_current_span() if span: trace = span.to_traceparent() return { diff --git a/authentik/events/context_processors/asn.py b/authentik/events/context_processors/asn.py index 23288d55f7..319e7816fa 100644 --- a/authentik/events/context_processors/asn.py +++ b/authentik/events/context_processors/asn.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Optional, TypedDict from django.http import HttpRequest from geoip2.errors import GeoIP2Error from geoip2.models import ASN -from sentry_sdk import Hub +from sentry_sdk import start_span from authentik.events.context_processors.mmdb import MMDBContextProcessor from authentik.lib.config import CONFIG @@ -48,7 +48,7 @@ class ASNContextProcessor(MMDBContextProcessor): def asn(self, ip_address: str) -> ASN | None: """Wrapper for Reader.asn""" - with Hub.current.start_span( + with start_span( op="authentik.events.asn.asn", description=ip_address, ): diff --git a/authentik/events/context_processors/geoip.py b/authentik/events/context_processors/geoip.py index 543988f277..1b0c397cd0 100644 --- a/authentik/events/context_processors/geoip.py +++ b/authentik/events/context_processors/geoip.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Optional, TypedDict from django.http import HttpRequest from geoip2.errors import GeoIP2Error from geoip2.models import City -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from authentik.events.context_processors.mmdb import MMDBContextProcessor from authentik.lib.config import CONFIG @@ -49,7 +49,7 @@ class GeoIPContextProcessor(MMDBContextProcessor): def city(self, ip_address: str) -> City | None: """Wrapper for Reader.city""" - with Hub.current.start_span( + with start_span( op="authentik.events.geo.city", description=ip_address, ): diff --git a/authentik/flows/planner.py b/authentik/flows/planner.py index 5e9e3b0d33..2c7231669e 100644 --- a/authentik/flows/planner.py +++ b/authentik/flows/planner.py @@ -5,7 +5,7 @@ from typing import Any from django.core.cache import cache from django.http import HttpRequest -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from sentry_sdk.tracing import Span from structlog.stdlib import BoundLogger, get_logger @@ -151,9 +151,7 @@ class FlowPlanner: def plan(self, request: HttpRequest, default_context: dict[str, Any] | None = None) -> FlowPlan: """Check each of the flows' policies, check policies for each stage with PolicyBinding and return ordered list""" - with Hub.current.start_span( - op="authentik.flow.planner.plan", description=self.flow.slug - ) as span: + with start_span(op="authentik.flow.planner.plan", description=self.flow.slug) as span: span: Span span.set_data("flow", self.flow) span.set_data("request", request) @@ -218,7 +216,7 @@ class FlowPlanner: """Build flow plan by checking each stage in their respective order and checking the applied policies""" with ( - Hub.current.start_span( + start_span( op="authentik.flow.planner.build_plan", description=self.flow.slug, ) as span, diff --git a/authentik/flows/stage.py b/authentik/flows/stage.py index 828bb9a585..3eac86cf1d 100644 --- a/authentik/flows/stage.py +++ b/authentik/flows/stage.py @@ -10,7 +10,7 @@ from django.urls import reverse from django.views.generic.base import View from prometheus_client import Histogram from rest_framework.request import Request -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from structlog.stdlib import BoundLogger, get_logger from authentik.core.models import User @@ -123,7 +123,7 @@ class ChallengeStageView(StageView): ) return self.executor.restart_flow(keep_context) with ( - Hub.current.start_span( + start_span( op="authentik.flow.stage.challenge_invalid", description=self.__class__.__name__, ), @@ -133,7 +133,7 @@ class ChallengeStageView(StageView): ): return self.challenge_invalid(challenge) with ( - Hub.current.start_span( + start_span( op="authentik.flow.stage.challenge_valid", description=self.__class__.__name__, ), @@ -159,7 +159,7 @@ class ChallengeStageView(StageView): def _get_challenge(self, *args, **kwargs) -> Challenge: with ( - Hub.current.start_span( + start_span( op="authentik.flow.stage.get_challenge", description=self.__class__.__name__, ), @@ -172,7 +172,7 @@ class ChallengeStageView(StageView): except StageInvalidException as exc: self.logger.debug("Got StageInvalidException", exc=exc) return self.executor.stage_invalid() - with Hub.current.start_span( + with start_span( op="authentik.flow.stage._get_challenge", description=self.__class__.__name__, ): diff --git a/authentik/flows/views/executor.py b/authentik/flows/views/executor.py index df1e674fa3..30aa420293 100644 --- a/authentik/flows/views/executor.py +++ b/authentik/flows/views/executor.py @@ -18,9 +18,8 @@ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, PolymorphicProxySerializer, extend_schema from rest_framework.permissions import AllowAny from rest_framework.views import APIView -from sentry_sdk import capture_exception +from sentry_sdk import capture_exception, start_span from sentry_sdk.api import set_tag -from sentry_sdk.hub import Hub from structlog.stdlib import BoundLogger, get_logger from authentik.brands.models import Brand @@ -154,9 +153,7 @@ class FlowExecutorView(APIView): return plan def dispatch(self, request: HttpRequest, flow_slug: str) -> HttpResponse: - with Hub.current.start_span( - op="authentik.flow.executor.dispatch", description=self.flow.slug - ) as span: + with start_span(op="authentik.flow.executor.dispatch", description=self.flow.slug) as span: span.set_data("authentik Flow", self.flow.slug) get_params = QueryDict(request.GET.get(QS_QUERY, "")) if QS_KEY_TOKEN in get_params: @@ -274,7 +271,7 @@ class FlowExecutorView(APIView): ) try: with ( - Hub.current.start_span( + start_span( op="authentik.flow.executor.stage", description=class_path, ) as span, @@ -325,7 +322,7 @@ class FlowExecutorView(APIView): ) try: with ( - Hub.current.start_span( + start_span( op="authentik.flow.executor.stage", description=class_path, ) as span, diff --git a/authentik/lib/expression/evaluator.py b/authentik/lib/expression/evaluator.py index 80be9e9b39..13d33db31e 100644 --- a/authentik/lib/expression/evaluator.py +++ b/authentik/lib/expression/evaluator.py @@ -13,7 +13,7 @@ from django.core.exceptions import FieldError from django.utils.text import slugify from guardian.shortcuts import get_anonymous_user from rest_framework.serializers import ValidationError -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from sentry_sdk.tracing import Span from structlog.stdlib import get_logger @@ -195,7 +195,7 @@ class BaseEvaluator: """Parse and evaluate expression. If the syntax is incorrect, a SyntaxError is raised. If any exception is raised during execution, it is raised. The result is returned without any type-checking.""" - with Hub.current.start_span(op="authentik.lib.evaluator.evaluate") as span: + with start_span(op="authentik.lib.evaluator.evaluate") as span: span: Span span.description = self._filename span.set_data("expression", expression_source) diff --git a/authentik/lib/sentry.py b/authentik/lib/sentry.py index 434de90a0c..9027d06e62 100644 --- a/authentik/lib/sentry.py +++ b/authentik/lib/sentry.py @@ -68,7 +68,7 @@ def sentry_init(**sentry_init_kwargs): integrations=[ ArgvIntegration(), StdlibIntegration(), - DjangoIntegration(transaction_style="function_name"), + DjangoIntegration(transaction_style="function_name", cache_spans=True), CeleryIntegration(), RedisIntegration(), ThreadingIntegration(propagate_hub=True), diff --git a/authentik/policies/engine.py b/authentik/policies/engine.py index 8b24334bf6..533093925c 100644 --- a/authentik/policies/engine.py +++ b/authentik/policies/engine.py @@ -7,7 +7,7 @@ from time import perf_counter from django.core.cache import cache from django.http import HttpRequest -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from sentry_sdk.tracing import Span from structlog.stdlib import BoundLogger, get_logger @@ -111,7 +111,7 @@ class PolicyEngine: def build(self) -> "PolicyEngine": """Build wrapper which monitors performance""" with ( - Hub.current.start_span( + start_span( op="authentik.policy.engine.build", description=self.__pbm, ) as span, diff --git a/authentik/policies/process.py b/authentik/policies/process.py index cc208da103..624edf047d 100644 --- a/authentik/policies/process.py +++ b/authentik/policies/process.py @@ -4,7 +4,7 @@ from multiprocessing import get_context from multiprocessing.connection import Connection from django.core.cache import cache -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from sentry_sdk.tracing import Span from structlog.stdlib import get_logger @@ -121,7 +121,7 @@ class PolicyProcess(PROCESS_CLASS): def profiling_wrapper(self): """Run with profiling enabled""" with ( - Hub.current.start_span( + start_span( op="authentik.policy.process.execute", ) as span, HIST_POLICIES_EXECUTION_TIME.labels( diff --git a/authentik/providers/oauth2/views/token.py b/authentik/providers/oauth2/views/token.py index 747d6413d7..70ba0afd15 100644 --- a/authentik/providers/oauth2/views/token.py +++ b/authentik/providers/oauth2/views/token.py @@ -17,7 +17,7 @@ from django.views import View from django.views.decorators.csrf import csrf_exempt from guardian.shortcuts import get_anonymous_user from jwt import PyJWK, PyJWT, PyJWTError, decode -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from structlog.stdlib import get_logger from authentik.core.middleware import CTX_AUTH_VIA @@ -118,7 +118,7 @@ class TokenParams: ) def __check_policy_access(self, app: Application, request: HttpRequest, **kwargs): - with Hub.current.start_span( + with start_span( op="authentik.providers.oauth2.token.policy", ): user = self.user if self.user else get_anonymous_user() @@ -151,22 +151,22 @@ class TokenParams: raise TokenError("invalid_client") if self.grant_type == GRANT_TYPE_AUTHORIZATION_CODE: - with Hub.current.start_span( + with start_span( op="authentik.providers.oauth2.post.parse.code", ): self.__post_init_code(raw_code, request) elif self.grant_type == GRANT_TYPE_REFRESH_TOKEN: - with Hub.current.start_span( + with start_span( op="authentik.providers.oauth2.post.parse.refresh", ): self.__post_init_refresh(raw_token, request) elif self.grant_type in [GRANT_TYPE_CLIENT_CREDENTIALS, GRANT_TYPE_PASSWORD]: - with Hub.current.start_span( + with start_span( op="authentik.providers.oauth2.post.parse.client_credentials", ): self.__post_init_client_credentials(request) elif self.grant_type == GRANT_TYPE_DEVICE_CODE: - with Hub.current.start_span( + with start_span( op="authentik.providers.oauth2.post.parse.device_code", ): self.__post_init_device_code(request) @@ -508,7 +508,7 @@ class TokenView(View): def post(self, request: HttpRequest) -> HttpResponse: """Generate tokens for clients""" try: - with Hub.current.start_span( + with start_span( op="authentik.providers.oauth2.post.parse", ): client_id, client_secret = extract_client_auth(request) @@ -519,7 +519,7 @@ class TokenView(View): CTX_AUTH_VIA.set("oauth_client_secret") self.params = TokenParams.parse(request, self.provider, client_id, client_secret) - with Hub.current.start_span( + with start_span( op="authentik.providers.oauth2.post.response", ): if self.params.grant_type == GRANT_TYPE_AUTHORIZATION_CODE: diff --git a/authentik/root/middleware.py b/authentik/root/middleware.py index 017dee60c6..c8e53bc88b 100644 --- a/authentik/root/middleware.py +++ b/authentik/root/middleware.py @@ -17,7 +17,7 @@ from django.middleware.csrf import CsrfViewMiddleware as UpstreamCsrfViewMiddlew from django.utils.cache import patch_vary_headers from django.utils.http import http_date from jwt import PyJWTError, decode, encode -from sentry_sdk.hub import Hub +from sentry_sdk import Scope from structlog.stdlib import get_logger from authentik.core.models import Token, TokenIntents, User, UserTypes @@ -221,11 +221,9 @@ class ClientIPMiddleware: ) return None # Update sentry scope to include correct IP - user = Hub.current.scope._user - if not user: - user = {} + user = Scope.get_isolation_scope()._user or {} user["ip_address"] = delegated_ip - Hub.current.scope.set_user(user) + Scope.get_isolation_scope().set_user(user) # Set the outpost service account on the request setattr(request, self.request_attr_outpost_user, user) return delegated_ip diff --git a/authentik/stages/identification/stage.py b/authentik/stages/identification/stage.py index 8c5ecbcd3c..3cdccf3c00 100644 --- a/authentik/stages/identification/stage.py +++ b/authentik/stages/identification/stage.py @@ -12,7 +12,7 @@ from django.utils.translation import gettext as _ from drf_spectacular.utils import PolymorphicProxySerializer, extend_schema_field from rest_framework.fields import BooleanField, CharField, ChoiceField, DictField, ListField from rest_framework.serializers import ValidationError -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from authentik.core.api.utils import PassiveSerializer from authentik.core.models import Application, Source, User @@ -94,7 +94,7 @@ class IdentificationChallengeResponse(ChallengeResponse): pre_user = self.stage.get_user(uid_field) if not pre_user: - with Hub.current.start_span( + with start_span( op="authentik.stages.identification.validate_invalid_wait", description="Sleep random time on invalid user identifier", ): @@ -136,7 +136,7 @@ class IdentificationChallengeResponse(ChallengeResponse): if not password: self.stage.logger.warning("Password not set for ident+auth attempt") try: - with Hub.current.start_span( + with start_span( op="authentik.stages.identification.authenticate", description="User authenticate call (combo stage)", ): diff --git a/authentik/stages/password/stage.py b/authentik/stages/password/stage.py index e8c0bde3e2..873467cf80 100644 --- a/authentik/stages/password/stage.py +++ b/authentik/stages/password/stage.py @@ -10,7 +10,7 @@ from django.urls import reverse from django.utils.translation import gettext as _ from rest_framework.exceptions import ValidationError from rest_framework.fields import BooleanField, CharField -from sentry_sdk.hub import Hub +from sentry_sdk import start_span from structlog.stdlib import get_logger from authentik.core.models import User @@ -47,7 +47,7 @@ def authenticate( LOGGER.warning("Failed to import backend", path=backend_path) continue LOGGER.debug("Attempting authentication...", backend=backend_path) - with Hub.current.start_span( + with start_span( op="authentik.stages.password.authenticate", description=backend_path, ): @@ -99,7 +99,7 @@ class PasswordChallengeResponse(ChallengeResponse): "username": pending_user.username, } try: - with Hub.current.start_span( + with start_span( op="authentik.stages.password.authenticate", description="User authenticate call", ):