sentry-python: Sanic integration does not send any errors outside a request (like in a background task)
How do you use Sentry?
Sentry Saas (sentry.io)
Version
1.9.9
Steps to Reproduce
Sanic is using Sentry Hub by plugging the ‘http.lifecycle.request’ signal to start the Hub, and the ‘http.lifecycle.response’ to exit it.
The problem is that when errors occurs outside the HTTP lifecycle request, like in a background task, no errors are reported by Sentry/Sanic.
Here’s a reproducible bug:
from sanic import Sanic
from sanic.response import text
import asyncio, sentry_sdk
from sentry_sdk.integrations.sanic import SanicIntegration
app = Sanic("Sanic-Sentry-Test")
async def fail_later(*args, **kwargs):
print('Starting task, might take a while...')
await asyncio.sleep(5)
value = 0
print('Value is: {}'.format(value))
print('Output is {}'.format(5/value)) # This should raise a ZeroDivisionError exception, but nothing
print('Done task.')
@app.get("/")
async def hello_world(request):
request.app.add_task(fail_later(), name="fail_later")
return text("Hello, world.")
sentry_sdk.init('...url', integrations=[SanicIntegration()])
if __name__ == "__main__":
app.run()
Of course, the same code, but with the ZeroDivisionError directly on hello_world properly appears at Sentry, which means the integration is working as expected when inside a request, but not when outside.
I’ve seen with the team at Sanic, including @ahopkins about this on sanic-org/sanic#2576.
Expected Result
The exception should be logged at Sentry
Actual Result
Nothing is logged
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 22 (12 by maintainers)
A month after having implemented it, I can confirm that this resolves the issue. I stopped having the
"types.SimpleNamespace" object has no attribute "_sentry_hub".I’ll close this ticket.
Thanks for your help!
Ahh, okay. So this ticket should probably wait for that.
It appears that this issue is caused by an Asyncio integration bug documented in #2328 and #2333, rather than a problem with the Sanic integration. To work around the issue, whenever you are using the Sentry SDK in an async application, the Sentry SDK needs to be initialized from within an async function. We would eventually like to fix this behavior so that the Asyncio integration can still work when the SDK is initialized from outside an async function, but because fixing this bug would likely require us to rewrite significant portions of our Asyncio integration, it will likely take some time before we get around to fixing this issue.
In this case (and with Sanic apps generally), you can work around the bug by initializing the SDK from within a
"before_server_start"listener, like so:@cnicodeme Please let us know if you have any questions, or if you encounter any difficulties while implementing the workaround.
I hope to get something out today. We have a PR ready for the change: https://github.com/getsentry/sentry-python/pull/1695 Some work still needs to be done. But if this is merged we are ready for a release and will deploy a new version of the SDK today.