Skip to main content

neva-asgi

ASGI middleware for the Neva framework.

python-neva is the framework-agnostic core: it must not import an ASGI framework. This package holds the middleware that used to live in neva.obs.middleware, so that boundary holds.

It sits below the protocol integrations rather than inside one — neva-fastapi and neva-faststream (in its ASGI mode) can both consume it without depending on each other.

Install

uv add neva-asgi

Middleware

CorrelationMiddleware

Assigns a correlation ID to every HTTP and WebSocket request, reusing an inbound X-Request-ID or X-Correlation-ID when it is a valid UUID and generating one otherwise. The ID is published on scope["state"]["correlation_id"] and echoed on the response. It is also bound into structlog's context, so every log line emitted while handling the request carries correlation_id without the caller threading it through — structlog's default processor chain merges contextvars, so this needs no logging configuration.

from neva.asgi import CorrelationMiddleware

app.add_middleware(CorrelationMiddleware, header_name="X-Request-ID")

generator and validator are both injectable, so a service that uses ULIDs or a non-UUID scheme can swap them.

ProfilerMiddleware

Profiles each HTTP request with pyinstrument and writes an HTML report per request. It names the file after the correlation ID when CorrelationMiddleware runs ahead of it, and falls back to a timestamp.

from neva.asgi import ProfilerMiddleware

app.add_middleware(ProfilerMiddleware, path="./profiles", interval=0.001)

Intended for local and staging use: it profiles every request and writes a file per request.

TracingMiddleware

Requires the otel extra:

uv add "neva-asgi[otel]"

Emits an OpenTelemetry HTTP server span per request, carrying the matched route's template rather than the resolved path — /users/{id}, not /users/42. Without that, every request is its own operation name and no endpoint can be aggregated, so a trace backend has nothing to graph.

from neva.asgi import CorrelationMiddleware
from neva.asgi.tracing import TracingMiddleware
from neva.fastapi import route_template

app.add_middleware(TracingMiddleware, route_resolver=route_template)
app.add_middleware(CorrelationMiddleware)

The span is not written here: opentelemetry-instrumentation-asgi already carries the semantic conventions, the server metrics, header capture, context propagation and WebSockets. This middleware composes it and adds the one thing it cannot know — the route — because it runs outside the application, where nothing has matched yet. opentelemetry-instrumentation-fastapi is not the answer either: it re-walks app.routes to resolve the route, and since FastAPI 0.137 made include_router lazy that walk no longer reaches the prefixed template.

  • route_resolver is injected rather than imported, so this package depends on no web framework and neva-fastapi depends on no OpenTelemetry. neva.fastapi.route_template is the FastAPI implementation; any (scope) -> str | None will do.
  • The correlation ID is stamped on the span as correlation_id when CorrelationMiddleware has run, which is what pivots a client-reported request ID to the trace that served it. Either middleware order works — the span is stamped once routing is done, by which point both have run.
  • Unmatched requests keep a bare method as the span name (GET, or HTTP for a method the client invented) and carry no http.route. Upstream's default appends the request path, which lets a bot sweep mint one operation name per URL it probes.
  • Unknown keyword arguments are forwarded to the instrumentor, so excluded_urls, the request hooks, header capture and an explicit tracer_provider all still work. Two upstream defaults are overridden and can be set back: default_span_details and exclude_spans, the latter because upstream emits a child span per ASGI receive and send event.

Importing neva.asgi does not import OpenTelemetry — neva.asgi.tracing is the only module that does, and nothing re-exports it. A test asserts that in a subprocess, because a single convenience re-export would quietly make the extra mandatory for every CorrelationMiddleware user.

Develop

uv sync --all-extras
poe lint && poe fmt && poe tc && poe test

Agent guidelines

neva/asgi/guidelines/fragments/ is what this package contributes to neva-boost. Those files are the source and the thing to edit; poe guidelines holds them to the frontmatter contract and runs in CI.

Renders are not committed — requires is evaluated against installed versions, so one is only correct for the environment that produced it. Compose your own:

poe guidelines-render                        # .claude/skills/, gitignored
uv run neva-boost install --target agents    # AGENTS.md instead

Commits follow Conventional Commits with gitmoji via cz commit; releases are cut with cz bump.

Metadata

Release files for neva-asgi 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for neva-asgi 0.2.0
File Size Uploaded
neva_asgi-0.2.0.tar.gz 118.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for neva-asgi 0.2.0
File Interpreter ABI Platform
neva_asgi-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 134.2 kB

Release files / neva_asgi-0.2.0.tar.gz

Download URL neva_asgi-0.2.0.tar.gz
Size 118.6 kB
Tags Source
SHA-256 checksum
How to use checksums
a4e27b674eb573f28e0e8b37afec1c4ce3a507bbc94b5d5f33a318e67aee5c25
BLAKE2b-256 checksum
How to use checksums
d204bfe9d7a6c2db9ab1482a26a4948eb513afb92778f4a99500af3628b33e88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.22

Release files / neva_asgi-0.2.0-py3-none-any.whl

Download URL neva_asgi-0.2.0-py3-none-any.whl
Size 15.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b99849bc515ce14aa6524de98b2a97da5489e7e20782990c24eaaab0e68a0620
BLAKE2b-256 checksum
How to use checksums
77e3e1b8c6599ba934a4ad92bf96f66d93a28af2841261ac595e501c9ba8ecd1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.22

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page