Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
- Dropped support for Starlette below 0.20.
- Dropped support for FastAPI below 0.85.
- Dropped support for trytond below 5.4.
- Dropped support for Sanic below 22.0.
- Removed the possibility to supply a specific client to the LaunchDarklyIntegration.
- The `enable_tracing` option was removed. Use `traces_sample_rate=1.0` instead.
- The deprecated `push_scope` and `configure_scope` APIs have been removed. Use `with new_scope():` to push a new scope and `scope = get_current_scope()` to retrieve the current scope instead.
Expand Down
4 changes: 2 additions & 2 deletions scripts/populate_tox/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@
"sanic": {
"package": "sanic",
"deps": {
"*": ["websockets<11.0", "aiohttp"],
">=22": ["sanic-testing"],
"*": ["websockets<11.0", "aiohttp", "sanic-testing"],
"<22.9": ["sanic-testing<22.9", "httpx<0.24"],
# tracerite imports pkg_resources before https://github.com/sanic-org/tracerite/commit/2f68543fab726d12d5c5d71fab584eb42140f410
"py3.8": ["tracerite<1.1.2", "setuptools<82"],
},
Expand Down
61 changes: 54 additions & 7 deletions scripts/populate_tox/package_dependencies.jsonl

Large diffs are not rendered by default.

216 changes: 216 additions & 0 deletions scripts/populate_tox/releases.jsonl

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion sentry_sdk/integrations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def iter_default_integrations(
"redis": (2, 10, 0),
"requests": (2, 30, 0),
"rq": (0, 6),
"sanic": (0, 8),
"sanic": (22, 0),
"spark": (3, 0), # pyspark
"sqlalchemy": (1, 4),
"starlette": (0, 20),
Expand Down
71 changes: 0 additions & 71 deletions sentry_sdk/integrations/sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
)
from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version
from sentry_sdk.integrations._wsgi_common import RequestExtractor, _filter_headers
from sentry_sdk.integrations.logging import ignore_logger
from sentry_sdk.scope import should_send_default_pii
from sentry_sdk.traces import SegmentNameSource, StreamedSpan
from sentry_sdk.tracing import TransactionSource
Expand Down Expand Up @@ -78,22 +77,6 @@ def setup_once() -> None:
SanicIntegration.version = parse_version(SANIC_VERSION)
_check_minimum_version(SanicIntegration, SanicIntegration.version)

if SANIC_VERSION.startswith("0.8."):
# Sanic 0.8 and older creates a logger named "root" and puts a
# stringified version of every exception in there (without exc_info),
# which our error deduplication can't detect.
#
# We explicitly check the version here because it is a very
# invasive step to ignore this logger and not necessary in newer
# versions at all.
#
# https://github.com/huge-success/sanic/issues/1332
ignore_logger("root")

if SanicIntegration.version is not None and SanicIntegration.version < (21, 9):
_setup_legacy_sanic()
return

_setup_sanic()


Expand Down Expand Up @@ -130,12 +113,6 @@ def _setup_sanic() -> None:
ErrorHandler.lookup = _sentry_error_handler_lookup


def _setup_legacy_sanic() -> None:
Sanic.handle_request = _legacy_handle_request
Router.get = _legacy_router_get
ErrorHandler.lookup = _sentry_error_handler_lookup


async def _startup(self: "Sanic") -> None:
# This happens about as early in the lifecycle as possible, just after the
# Request object is created. The body has not yet been consumed.
Expand Down Expand Up @@ -300,54 +277,6 @@ async def sentry_wrapped_error_handler(
return sentry_wrapped_error_handler


async def _legacy_handle_request(
self: "Any", request: "Request", *args: "Any", **kwargs: "Any"
) -> "Any":
if sentry_sdk.get_client().get_integration(SanicIntegration) is None:
return await old_handle_request(self, request, *args, **kwargs)

weak_request = weakref.ref(request)

with sentry_sdk.isolation_scope() as scope:
scope.clear_breadcrumbs()
scope.add_event_processor(_make_request_processor(weak_request))

response = old_handle_request(self, request, *args, **kwargs)
if isawaitable(response):
response = await response

return response


def _legacy_router_get(self: "Any", *args: "Union[Any, Request]") -> "Any":
rv = old_router_get(self, *args)
if sentry_sdk.get_client().get_integration(SanicIntegration) is not None:
with capture_internal_exceptions():
scope = sentry_sdk.get_isolation_scope()
if SanicIntegration.version and SanicIntegration.version >= (21, 3):
# Sanic versions above and including 21.3 append the app name to the
# route name, and so we need to remove it from Route name so the
# transaction name is consistent across all versions
sanic_app_name = self.ctx.app.name
sanic_route = rv[0].name

if sanic_route.startswith("%s." % sanic_app_name):
# We add a 1 to the len of the sanic_app_name because there is a dot
# that joins app name and the route name
# Format: app_name.route_name
sanic_route = sanic_route[len(sanic_app_name) + 1 :]

scope.set_transaction_name(
sanic_route, source=TransactionSource.COMPONENT
)
else:
scope.set_transaction_name(
rv[0].__name__, source=TransactionSource.COMPONENT
)

return rv


@ensure_integration_enabled(SanicIntegration)
def _capture_exception(exception: "Union[ExcInfo, BaseException]") -> None:
with capture_internal_exceptions():
Expand Down
12 changes: 11 additions & 1 deletion tests/integrations/sanic/test_sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,17 @@ def simple_client(app):
yield app.test_client

if ReusableClient is not None:
return ReusableClient(app, port=get_free_port())

@contextlib.contextmanager
def reusable_client(app):
client = ReusableClient(app, port=get_free_port())
client.__enter__()
try:
yield client
finally:
client.__exit__(None, None, None)

return reusable_client(app)
else:
return simple_client(app)

Expand Down
Loading
Loading