Replies: 1 comment
-
|
Checkout loopsentry It does exactly this and you can have env var based monitoring start stop. from contextlib import asynccontextmanager
from fastapi import FastAPI
from loopsentry import LoopSentry
@asynccontextmanager
async def lifespan(app: FastAPI):
# use ir in lifespan so multiple workers can get their own loopsentry monitor thread
sentry = LoopSentry(
threshold=0.05, # seconds
base_dir="sentry_logs",
async_threshold=1.0, # seconds
capture_args=True,
detect_async_bottlenecks=True,
)
sentry.start() # this you can disable on prod based on env var
yield
app = FastAPI(lifespan=lifespan)And after testing and running the system llgs will be generated on sentry_logs dir where you can run loopsentry analyze -d sentry_logs/ --htmlOr even cli view. Right now html needs update but it should do the jov |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
First Check
Commit to Help
Example Code
Description
(Originally posted in the fastapi repo: fastapi/fastapi#14603)
Feature request
I suggest to automatically warn when the event loop is stuck for 1+ seconds. I think this should be enabled by default when running
fastapi devfor a better UX.Why
The async docs explain that sync IO/... should not be used in async path operations. However, I think it is:
I've seen this happen in production applications and also found several issues related to this when searching the discussions here (e.g. fastapi/fastapi#8842 with a good overview of the problem).
How
Measure time between task schedule and task execution
For detection, I think we could regularly schedule a task and measure how long it takes until it gets executed. My assumption is that if a task takes a long time until it is executed, then FastAPI would also not be able to process requests for roughly the same time.
Example with blocking sync code within async operator:
detect_blockingto run at 12:00:00detect_blockingis called12:00:04 - 12:00:00 = 4s4s > 1s -> warningdetect_blockingagain and continue...Non-blocking example:
detect_blockingto run at 12:00:00awaits something (and thus the next task in the event loop is executed)detect_blockingis called12:00:00.123 - 12:00:00 = 0.123s0.123s < 1s -> no warningdetect_blockingagain and continue...You can take a look at the example code. After starting go to http://127.0.0.1:8000/sleep_sync?seconds=2 and observe the
WARNING:root:Event loop has been blocked for 1.9s.log. I did not yet look at how to do this internally within FastAPI and to restrict it to dev-only.Run asyncio in debug mode
Alternatively, there is an option to run asyncio in debug mode which would add in-built checks if the event loop is blocked. This would be configurable with loop.slow_callback_duration.
This option is less flexible (e.g. I don't know if we could modify the logged message) and enabling debug mode may come with other side effects, so I would prefer the other option for maintainability.
PR / Feedback
I could work on a PR, but first wanted to ask if this is desired and if there is more I should consider / what I should verify to prevent false positives warnings.
Operating System
Linux
Operating System Details
Ubuntu 24
Python Version
3.13.5
Additional Context
No response
Beta Was this translation helpful? Give feedback.
All reactions