feat: add FastAPI middleware for per-request emissions tracking - #1203
feat: add FastAPI middleware for per-request emissions tracking#1203davidberenstein1957 wants to merge 1 commit into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #1203 +/- ##
==========================================
+ Coverage 91.43% 91.54% +0.11%
==========================================
Files 49 52 +3
Lines 5057 5230 +173
==========================================
+ Hits 4624 4788 +164
- Misses 433 442 +9 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Hello, thanks for this. There is a problem with your branch : there are many changes that are already merged. Can you do a rebase ? |
f44740f to
15c0ccf
Compare
|
@benoit-cty I have reached out to some people at FastAPI, if they would be interested in a quick review :) For visibility, we could also consider deploying it as a standalone integration, but let's see if people like it. |
eabd526 to
bb6995c
Compare
SaboniAmine
left a comment
There was a problem hiding this comment.
Thanks David this a great PR! Left a few questions, and saw that you have already prepared a benchmark script, do you have any numbers / graph already computed to share ?
deba2ce to
86cc355
Compare
|
@inimaz This is ready for review. Rebased on v3.2.9 and benchmarked on a real HF embedder workload — middleware adds about 3 ms per request (~24 ms → ~27 ms). Details in the updated PR description and docs/how-to/fastapi.md. |
|
@SaboniAmine Thanks again for the thorough review — I've addressed the inline threads in the latest pushes:
Local |
|
Ponytail cleanup on this PR:
See |
|
Added a sync
Reproduce: |
|
@inimaz @SaboniAmine — ready for another look when you have time. This commit finishes the HTTP perf work:
Deferred middleware stays in the same ballpark as baseline on the live benchmark (~30–32 ms vs ~42 ms baseline mean on Darwin arm64). |
830edb6 to
d1e7a95
Compare
Adds an ASGI middleware that gives each HTTP request its share of a long-running tracker's energy, plus the attribution model behind it. One tracker runs for the app's lifetime. Each completed sampling window (t_prev, t_now, dE) is split across the requests in flight during it, weighted by their overlap with the window and normalised by the sum of the weights. Windows with nothing in flight are recorded as unattributed. The invariant attributed + unattributed == settled holds exactly after every window, and is what the concurrency test pins down. Why not per-request start/stop energy snapshots: with N requests in flight each request observes the whole machine's delta, so the sum overcounts by roughly N - measured up to 88x at 100 concurrent requests. Fair-share weighting is the only split that conserves the run total. A request's share is only known one or more sampling windows after its response was sent, so results are reported then, via a callback. A request that never covered a completed window reports energy_kwh=None rather than zero: there is no honest number for it. Tracker side: add_energy_window_observer / remove_energy_window_observer expose the sampling windows, and http_request_emissions() scales the run's EmissionsData down to one attributed share using the run's accumulated component ratios and carbon intensity. Depends on #1374 (duration int -> float in the emissions schemas, and dropping the duration < 1 send guard) and #1375 (scheduler pause handling around tasks). Both are carried by their own PRs rather than duplicated here, so this should merge after them. Deliberately left out, to keep the diff reviewable: hardware-tier gating of which backends can resolve a sampling window, include/exclude path filtering (endpoint labelling is two lines inline), idle-baseline subtraction, per-endpoint aggregation, routing per-request rows into the tracker's own CSV/API output handlers, a lifespan helper, and a dedicated docs page. Each is additive on top of this and can follow if there is demand. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
d1e7a95 to
e293e0c
Compare
Summary
codecarbon[fastapi]integration: middleware to track CO₂ emissions per HTTP request on FastAPI/Starlette appscreate_codecarbon_lifespanfor a shared app-level tracker, route include/exclude filters, optionalsave_to_api, and opt-inresponse_headersparaphrase-MiniLM-L3-v2): default deferred middleware ~+4 ms per request; sync headers cost more. See docs/how-to/fastapi.md.Test plan
uv run pytest tests/integrations/ -vuv run --extra fastapi uvicorn examples.fastapi_middleware:app --reloadthencurl localhost:8000/predictUsage
Full guide: docs/how-to/fastapi.md