# 🔍 FastAPI Block Hunter
This is a tool to help you debug blocking calls in your FastAPI application.
It works by:
- 🔄 Adding a middleware to the FastAPI application that will store the current request URL in a context variable.
- 🛠️ Patching the `_format_handle` function from the `asyncio.base_events` module with a custom formatter to print a custom message when a blocking call is detected.
This allows you to identify the blocking call that has blocked the event loop and print the stack trace of the blocking call.

## 📦 Installation
```bash
pip install fastapi-block-hunter
```
## 🚀 Usage
To use the package, you need to add the middleware to your FastAPI application and set up the asyncio debug mode.
```python
from fastapi import FastAPI
from fastapi_block_hunter import add_block_hunter_middleware, setup_asyncio_debug_mode
# You may set up the asyncio debug mode by defining ASYNgCIO_DEBUG_MODE=1 as an environment variable.
# Or by calling the setup_asyncio_debug_mode function in your app lifespan
@asynccontextmanager
async def lifespan(app: FastAPI):
await setup_asyncio_debug_mode()
yield {}
app = FastAPI(lifespan=lifespan)
app = add_block_hunter_middleware(app, verbose=True)
```
You also need to make sure you use `asyncio` as your `FastAPI` event loop for the package to work. If you have `uvloop` installed, you will need to manually tell your web server to use `asyncio` instead of `uvloop`.
For uvicorn, set the `--loop` option to `asyncio`.
From the uvicorn command line:
```bash
uvicorn --loop asyncio # rest of your startup command
```
Or from your launch script:
```python
from fastapi import FastAPI
import uvicorn
app = FastAPI()
# ... your FastAPI app setup
if __name__ == "__main__":
uvicorn.run(app, loop="asyncio")
```
Or from the code:
```python
from fastapi import FastAPI
from fastapi_block_hunter import add_custom_slow_callback_logger
app = FastAPI()
app = add_custom_slow_callback_logger(app)
```
## 📚 Documentation
A complete example of how to use the package can be found in the [example/app.py](example/app.py) file.
## 📄 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Raw data
{
"_id": null,
"home_page": "https://github.com/yourusername/fastapi-block-hunter",
"name": "fastapi-block-hunter",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.11",
"maintainer_email": null,
"keywords": "fastapi, block-hunter",
"author": "Manuel Angel Suarez Alvarez",
"author_email": "Manuel_Angel99@outlook.com",
"download_url": "https://files.pythonhosted.org/packages/35/58/be9ebc908b6c374569c23193232f003a4a79cda98e9f4ea237fbfa293997/fastapi_block_hunter-0.0.1.tar.gz",
"platform": null,
"description": "# \ud83d\udd0d FastAPI Block Hunter\n\nThis is a tool to help you debug blocking calls in your FastAPI application.\n\nIt works by:\n\n- \ud83d\udd04 Adding a middleware to the FastAPI application that will store the current request URL in a context variable.\n- \ud83d\udee0\ufe0f Patching the `_format_handle` function from the `asyncio.base_events` module with a custom formatter to print a custom message when a blocking call is detected.\n\nThis allows you to identify the blocking call that has blocked the event loop and print the stack trace of the blocking call.\n\n\n\n## \ud83d\udce6 Installation\n\n```bash\npip install fastapi-block-hunter\n```\n\n## \ud83d\ude80 Usage\n\nTo use the package, you need to add the middleware to your FastAPI application and set up the asyncio debug mode.\n\n```python\nfrom fastapi import FastAPI\nfrom fastapi_block_hunter import add_block_hunter_middleware, setup_asyncio_debug_mode\n\n# You may set up the asyncio debug mode by defining ASYNgCIO_DEBUG_MODE=1 as an environment variable.\n# Or by calling the setup_asyncio_debug_mode function in your app lifespan\n\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n await setup_asyncio_debug_mode()\n yield {}\n\n\napp = FastAPI(lifespan=lifespan)\napp = add_block_hunter_middleware(app, verbose=True)\n\n\n```\n\nYou also need to make sure you use `asyncio` as your `FastAPI` event loop for the package to work. If you have `uvloop` installed, you will need to manually tell your web server to use `asyncio` instead of `uvloop`.\n\nFor uvicorn, set the `--loop` option to `asyncio`.\n\nFrom the uvicorn command line:\n\n```bash\nuvicorn --loop asyncio # rest of your startup command\n```\n\nOr from your launch script:\n\n```python\nfrom fastapi import FastAPI\n import uvicorn\n\napp = FastAPI()\n\n# ... your FastAPI app setup\n\nif __name__ == \"__main__\":\n uvicorn.run(app, loop=\"asyncio\")\n```\n\nOr from the code:\n\n```python\nfrom fastapi import FastAPI\nfrom fastapi_block_hunter import add_custom_slow_callback_logger\n\napp = FastAPI()\napp = add_custom_slow_callback_logger(app)\n```\n\n## \ud83d\udcda Documentation\n\nA complete example of how to use the package can be found in the [example/app.py](example/app.py) file.\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A FastAPI-based block hunter application",
"version": "0.0.1",
"project_urls": {
"Homepage": "https://github.com/yourusername/fastapi-block-hunter",
"Repository": "https://github.com/yourusername/fastapi-block-hunter"
},
"split_keywords": [
"fastapi",
" block-hunter"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8879f2622ae81c0205e4ab8270bb9654fe588c8fbf8ab1c469454f914a1c5a46",
"md5": "73cfcc4528230def9ab79fff0d278269",
"sha256": "f680613aa1b039179b4cab4d723a37f4620990be53d34866b375b0a3f4b1751e"
},
"downloads": -1,
"filename": "fastapi_block_hunter-0.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "73cfcc4528230def9ab79fff0d278269",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.11",
"size": 4906,
"upload_time": "2025-01-12T01:05:14",
"upload_time_iso_8601": "2025-01-12T01:05:14.874476Z",
"url": "https://files.pythonhosted.org/packages/88/79/f2622ae81c0205e4ab8270bb9654fe588c8fbf8ab1c469454f914a1c5a46/fastapi_block_hunter-0.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3558be9ebc908b6c374569c23193232f003a4a79cda98e9f4ea237fbfa293997",
"md5": "b5d8b50d707782e462867650e36c9954",
"sha256": "e93a08de335cbfa6be7653d38ffcf1c1672ccc8a5a377e5780974cd0804d14db"
},
"downloads": -1,
"filename": "fastapi_block_hunter-0.0.1.tar.gz",
"has_sig": false,
"md5_digest": "b5d8b50d707782e462867650e36c9954",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.11",
"size": 3932,
"upload_time": "2025-01-12T01:05:18",
"upload_time_iso_8601": "2025-01-12T01:05:18.389907Z",
"url": "https://files.pythonhosted.org/packages/35/58/be9ebc908b6c374569c23193232f003a4a79cda98e9f4ea237fbfa293997/fastapi_block_hunter-0.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-12 01:05:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yourusername",
"github_project": "fastapi-block-hunter",
"github_not_found": true,
"lcname": "fastapi-block-hunter"
}