Registry / observability / timing-asgi

timing-asgi

JSON →
library0.3.2pypypi✓ verified 25d ago

Timing-asgi is an ASGI middleware designed to automatically instrument ASGI endpoints and emit timing metrics. Developed by GRID, it's particularly useful for integrating with statsd-based cloud monitoring services like Datadog. The library currently supports ASGI3 and is actively maintained, with version 0.3.2 being the latest release.

pip install timing-asgi
INSTALL
IMPORT
SIG · TIMING-ASGI
T
timing-asgi
observabilitypythonv0.3.2
Install
1.6s avg
Import
38ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.3.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.040s · 17.8MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.6s · import 0.036s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

TimingMiddleware
from timing_asgi import TimingMiddleware
TimingClient
from timing_asgi import TimingClient
StarletteScopeToName
from timing_asgi.integrations import StarletteScopeToName
PathToName
from timing_asgi.utils import PathToName
from timing_asgi import PathToName
`PathToName` is in `timing_asgi.utils`, not directly under `timing_asgi`.

This example demonstrates how to integrate `timing-asgi` with a Starlette application. It defines a custom `TimingClient` that prints the collected metrics to the console. The `TimingMiddleware` is added to the Starlette application, configured with the custom client and a `StarletteScopeToName` metric namer to generate meaningful metric names based on the Starlette routes.

import logging import uvicorn from starlette.applications import Starlette from starlette.responses import PlainTextResponse from timing_asgi import TimingMiddleware, TimingClient from timing_asgi.integrations import StarletteScopeToName class PrintTimings(TimingClient): """A simple TimingClient that prints metrics to stdout.""" def timing(self, metric_name: str, timing: float, tags: list[str]) -> None: print(f"Metric: {metric_name}, Time: {timing:.6f}, Tags: {tags}") app = Starlette() @app.route("/") async def homepage(request): return PlainTextResponse("hello world") app.add_middleware( TimingMiddleware, client=PrintTimings(), metric_namer=StarletteScopeToName(prefix="myapp", starlette_app=app) ) if __name__ == "__main__": logging.basicConfig(level=logging.INFO) print("Running Uvicorn on http://127.0.0.1:8000. Access / to see timing metrics.") uvicorn.run(app, host="127.0.0.1", port=8000)
Debug
Known issues
breakingAs of version 0.2.0, `timing-asgi` exclusively supports ASGI3. Applications requiring ASGI2 compatibility must use `timing-asgi` version 0.1.2.
fix
Ensure your ASGI server and application framework are ASGI3 compliant. If not, downgrade to `timing-asgi==0.1.2`.
affects: >=0.2.0
gotchaThe middleware logs a debug message indicating that 'ASGI scope of type lifespan is not supported yet'. This means lifecycle events (startup/shutdown) of your ASGI application will not be instrumented by this middleware.
fix
Currently, there is no direct fix within `timing-asgi` for lifespan event instrumentation. Consider external tools or custom instrumentation for application startup/shutdown timings.
affects: All versions
gotchaWhen implementing a custom `TimingClient`, ensure it provides a `timing` method with the signature `(self, metric_name: str, timing: float, tags: list[str]) -> None`. The middleware performs a runtime check for this method, and its absence or incorrect signature will lead to errors.
fix
Adhere strictly to the `TimingClient` interface by implementing the `timing` method as specified in the base class.
affects: All versions
gotchaBy default, if no `metric_namer` is provided, `PathToName` is used, which might generate less descriptive metric names (e.g., based on URL path). For framework-specific routing, a specialized namer like `StarletteScopeToName` is often preferred for more accurate metric names.
fix
Explicitly pass an appropriate `metric_namer` to `TimingMiddleware`. For Starlette, use `StarletteScopeToName(prefix="your_app_name", starlette_app=app)`.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'timing_asgi'
The 'timing-asgi' library is not installed in the current Python environment.
fix
pip install timing-asgi
TypeError: __init__ missing 2 required positional arguments: 'recorder' and 'channel'
The TimingMiddleware requires both 'recorder' and 'channel' arguments during initialization, but they were not provided.
fix
app.add_middleware(TimingMiddleware, recorder=DatadogRecorder(client=statsd_client), channel=StarletteInfo())
TypeError: __init__ missing 1 required positional argument: 'client'
The DatadogRecorder requires a 'statsd.StatsClient' instance to be passed via the 'client' argument during initialization.
fix
statsd_client = statsd.StatsClient(host='localhost', port=8125)
recorder=DatadogRecorder(client=statsd_client)
Upgrade
Version history
0.3.2latest on PyPI · released Feb 17, 2026
Audit
Dependencies

No dependency data recorded yet.

Agent activity
18 hits · last 30 days
node
14
OpenAI (training)
1
Resources
timing-asgi — pip install timing-asgi · libregistry