A asgi middleware to measure the request duration
Project description
ASGI Request Duration ⏱️
ASGI Request Duration is a middleware for ASGI applications that measures the duration of HTTP requests and integrates this information into response headers and log records. This middleware is designed to be easy to integrate and configure, providing valuable insights into the performance of your ASGI application.
Note: If you find this project useful, please consider giving it a star ⭐ on GitHub. This helps prioritize its maintenance and development. If you encounter any typos, bugs 🐛, or have new feature requests, feel free to open an issue. I will be happy to address them.
Table of Contents 📚
Features ✨
- Measure the duration of each HTTP request.
- Add the request duration to response headers.
- Integrate the request duration into log records.
- Configurable header name and precision.
- Exclude specific paths from timing.
Installation 🛠️
You can install the package using pip:
pip install asgi-request-duration
Usage 🚀
Middleware 🧩
To use the middleware, add it to your ASGI application:
from asgi_request_duration.middleware import RequestDurationMiddleware
from starlette.applications import Starlette
app = Starlette()
app.add_middleware(RequestDurationMiddleware)
Logging Filter 📝
To use the logging filter, configure your logger to use the RequestDurationFilter:
import logging
from asgi_request_duration.filters import RequestDurationFilter
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("myapp")
logger.addFilter(RequestDurationFilter())
Configuration ⚙️
Middleware Configuration 🔧
You can configure the middleware by passing parameters to the RequestDurationMiddleware:
excluded_paths: List of paths to exclude from timing.header_name: The name of the header to store the request duration.precision: The precision of the recorded duration.skip_validate_header_name: Flag to skip header name validation.skip_validate_precision: Flag to skip precision validation.time_granularity: Specifies the unit of time measurement (default:Seconds).
Example:
app.add_middleware(
RequestDurationMiddleware,
excluded_paths=["^/health/?$"],
header_name="x-request-duration",
precision=3,
skip_validate_header_name=False,
skip_validate_precision=False,
time_granularity=TimeGranularity.MILLISECONDS,
)
Logging Filter Configuration 🔍
You can configure the logging filter by passing parameters to the RequestDurationFilter:
context_key: The key to retrieve the request duration context value.default_value: The default value if the request duration context key is not found.
Example:
logger.addFilter(RequestDurationFilter(context_key="request_duration", default_value="-"))
Examples 📖
Here is a complete example of how to use the middleware with the Starlette framework. For more examples and detailed usage, please refer to the examples folder in the repository.
Example with Starlette 🌟
from asgi_request_duration import RequestDurationMiddleware, TimeGranularity
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route
from uvicorn import run
async def info_endpoint(request: Request) -> JSONResponse:
return JSONResponse({"message": "info"})
async def excluded_endpoint(request: Request) -> JSONResponse:
return JSONResponse({"message": "excluded"})
routes = [
Route("/info", info_endpoint, methods=["GET"]),
Route("/excluded", excluded_endpoint, methods=["GET"]),
]
app = Starlette(routes=routes)
app.add_middleware(
RequestDurationMiddleware,
excluded_paths=["/excluded"],
header_name="x-request-duration",
precision=4,
skip_validate_header_name=False,
skip_validate_precision=False,
time_granularity=TimeGranularity.MILLISECONDS,
)
if __name__ == "__main__":
run(app, host='127.0.0.1', port=8000)
Contributing 🤝
Contributions are welcome! Please refer to the CONTRIBUTING.md file for guidelines on how to contribute to this project.
License 📜
This project is licensed under the GNU GPLv3 License. See the LICENSE file for more details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asgi_request_duration-1.0.6.tar.gz.
File metadata
- Download URL: asgi_request_duration-1.0.6.tar.gz
- Upload date:
- Size: 18.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.0.1 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7359dd163d737469327baaff639f1eaa4f164f7f53db091d1b7fd24e490ff5ab
|
|
| MD5 |
ad0cd297545f43455ced588eb976439f
|
|
| BLAKE2b-256 |
85814617df3941a06a85331f108879f7746253171301f496a3feceb6e14b6a8b
|
Provenance
The following attestation bundles were made for asgi_request_duration-1.0.6.tar.gz:
Publisher:
publish-pypi.yaml on feteu/asgi-request-duration
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
asgi_request_duration-1.0.6.tar.gz -
Subject digest:
7359dd163d737469327baaff639f1eaa4f164f7f53db091d1b7fd24e490ff5ab - Sigstore transparency entry: 272652475
- Sigstore integration time:
-
Permalink:
feteu/asgi-request-duration@3477aa56a21b32ab931da44eed0ac88b28e708e9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/feteu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yaml@3477aa56a21b32ab931da44eed0ac88b28e708e9 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file asgi_request_duration-1.0.6-py3-none-any.whl.
File metadata
- Download URL: asgi_request_duration-1.0.6-py3-none-any.whl
- Upload date:
- Size: 21.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.0.1 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4543c8b6feb33ad1004f4c9213db8c3e8429dbab9286c63f0279164979b3d7dd
|
|
| MD5 |
6cd1b9bc5a908b99cdf6d1582f72fe54
|
|
| BLAKE2b-256 |
d0b7db3ea4d054da00f37b6f7be76e8376e9473104c3006b5239ab748560ee0b
|
Provenance
The following attestation bundles were made for asgi_request_duration-1.0.6-py3-none-any.whl:
Publisher:
publish-pypi.yaml on feteu/asgi-request-duration
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
asgi_request_duration-1.0.6-py3-none-any.whl -
Subject digest:
4543c8b6feb33ad1004f4c9213db8c3e8429dbab9286c63f0279164979b3d7dd - Sigstore transparency entry: 272652478
- Sigstore integration time:
-
Permalink:
feteu/asgi-request-duration@3477aa56a21b32ab931da44eed0ac88b28e708e9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/feteu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yaml@3477aa56a21b32ab931da44eed0ac88b28e708e9 -
Trigger Event:
workflow_dispatch
-
Statement type: