Skip to content

Commit

Permalink
feat: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
klen committed Oct 4, 2023
1 parent 5b9215b commit 21b66df
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 56 deletions.
41 changes: 20 additions & 21 deletions muffin_sentry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from sentry_sdk import Hub
from sentry_sdk import Scope as SentryScope
from sentry_sdk import init as sentry_init
from sentry_sdk.sessions import auto_session_tracking
from sentry_sdk.tracing import Transaction

if TYPE_CHECKING:
Expand All @@ -18,6 +19,8 @@
TProcess = Callable[[Dict, Dict, Request], Dict]
TVProcess = TypeVar("TVProcess", bound=TProcess)

SENTRY_SCOPE: ContextVar[Optional[SentryScope]] = ContextVar("sentry_scope", default=None)


class Plugin(BasePlugin):
"""Setup Sentry and send exceptions and messages."""
Expand All @@ -26,21 +29,21 @@ class Plugin(BasePlugin):
client = None
defaults: ClassVar[Dict] = {
"dsn": "", # Sentry DSN
"transaction_style": "url", # url | endpoint
"sdk_options": {}, # See https://docs.sentry.io/platforms/python/configuration/options/
"ignore_errors": (ResponseError, ResponseRedirect),
}
current_scope: ContextVar[Optional[SentryScope]] = ContextVar(
"sentry_scope",
default=None,
)
processors: List[TProcess]

def __init__(self, *args, **kwargs):
"""Initialize the plugin."""
super(Plugin, self).__init__(*args, **kwargs)
self.processors = []

@property
def current_scope(self):
"""Get current Sentry Scope."""
return SENTRY_SCOPE

def setup(self, app: Application, **options):
"""Initialize Sentry Client."""
super().setup(app, **options)
Expand All @@ -63,28 +66,24 @@ async def middleware( # type: ignore[override]
url = request.url
scope = request.scope
scope_type = scope["type"]
transaction_style = cfg.transaction_style
with hub.configure_scope() as sentry_scope:
sentry_scope.clear_breadcrumbs()
sentry_scope._name = "muffin"
self.current_scope.set(sentry_scope)
sentry_scope.add_event_processor(partial(self.process_data, request=request))
trans_name = url.path
if transaction_style == "endpoint":
endpoint = scope.get("endpoint")
trans_name = endpoint.__qualname__ if endpoint else trans_name
with auto_session_tracking(hub, session_mode="request"), hub:
with hub.configure_scope() as sentry_scope:
sentry_scope._name = "muffin"
sentry_scope.clear_breadcrumbs()
sentry_scope.add_event_processor(partial(self.process_data, request=request))
SENTRY_SCOPE.set(sentry_scope)

trans = Transaction.continue_from_headers(
request.headers,
name=url.path,
source="url",
op=f"{scope_type}.muffin",
name=trans_name,
source=transaction_style,
)
trans.set_tag("asgi.type", scope_type)

with hub.start_transaction(
trans,
custom_sampling_context={"asgi_scope": sentry_scope},
custom_sampling_context={"asgi_scope": scope},
):
try:
response = await handler(request, receive, send)
Expand All @@ -94,7 +93,7 @@ async def middleware( # type: ignore[override]
except Exception as exc:
if type(exc) not in cfg.ignore_errors:
hub.capture_exception(exc)
raise exc from None
raise exc from exc

def processor(self, fn: TVProcess) -> TVProcess:
"""Register a custom processor."""
Expand Down Expand Up @@ -124,13 +123,13 @@ def process_data(self, event: Dict, hint: Dict, *, request: Request) -> Dict:
def capture_exception(self, *args, **kwargs):
"""Capture exception."""
if self.cfg.dsn:
with Hub(Hub.current, self.current_scope.get()) as hub:
with Hub(Hub.current, SENTRY_SCOPE.get()) as hub:
return hub.capture_exception(*args, **kwargs)
return None

def capture_message(self, *args, **kwargs):
"""Capture message."""
if self.cfg.dsn:
with Hub(Hub.current, self.current_scope.get()) as hub:
with Hub(Hub.current, SENTRY_SCOPE.get()) as hub:
return hub.capture_message(*args, **kwargs)
return None
66 changes: 33 additions & 33 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def sentry(app):

return muffin_sentry.Plugin(
app,
transaction_style="endpoint",
sdk_options={"environment": "tests", "release": version},
)

Expand Down Expand Up @@ -74,8 +75,9 @@ async def md(handler, request, receive, send):

@sentry.processor
def user(event, hint, request):
if hasattr(request, "user"):
event["user"] = request.user
scope = request.scope
if "user" in scope:
event["user"] = scope["user"]
return event

await app.lifespan.run("startup")
Expand All @@ -85,6 +87,7 @@ def user(event, hint, request):
assert res.status_code == 500
assert mocked.called
(event,), _ = mocked.call_args
assert event["transaction"] == "/error"
assert event["request"]
assert event["request"]["url"] == "http://localhost/error"

Expand Down

0 comments on commit 21b66df

Please sign in to comment.