fix: send measurement time to the API - #1325
Conversation
ApiClient.add_emission discarded the timestamp carried by EmissionsData and stamped the moment the payload was built instead, so stored rows were dated by send time rather than by the measurement window they summarise. Use the payload's timestamp when present, localised to an offset-aware ISO string, and fall back to now only for hand-built dicts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1325 +/- ##
==========================================
+ Coverage 91.39% 91.44% +0.05%
==========================================
Files 49 49
Lines 5056 5063 +7
==========================================
+ Hits 4621 4630 +9
+ Misses 435 433 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Closing as a duplicate of #1341, which fixes the same bug — the API client stamping emissions with the send time instead of the measurement time. #1341 is the more complete version: it has broader fallback coverage (missing, The one thing this PR has that #1341 lacks is the producer-side comment noting that Nothing wrong with the work here — the two were developed in parallel against the same bug report. |
What changed
ApiClient.add_emissionnow sends the timestamp carried by the emission payload instead of generating a new one at payload-build time. A smallget_measurement_timestamphelper localises the naiveEmissionsData.timestampto an offset-aware ISO string, falls back toget_datetime_with_timezone()when no timestamp is present (hand-built dicts), and logs a warning rather than failing on an unparseable value.Why
EmissionsData.timestamprecords when the measurement window ended (codecarbon/emissions_tracker.py:1063), survives all the way intoHTTPOutput._emit(codecarbon/output_methods/http.py:65-68), and was then thrown away byadd_emission, which stampedget_datetime_with_timezone()instead (codecarbon/core/api_client.py:191). Every other field in the payload describes the measurement window; the one field that dates it described the HTTP call. Users running bothfileandapioutput methods see the CSV and the API disagree.The stored value is left offset-aware, so no existing rows shift and the CSV output format is unchanged.
This is also a prerequisite for any future client-side batching or retry/spill-buffer work: without it, every replayed or batched emission would be stored at its send time, turning a sub-second skew into an outage-length one.
Closes #1312
How it was verified
tests/test_api_call.py::TestApi::test_add_emission_keeps_measurement_timestampasserts the POSTedtimestampstarts with the supplied measurement time and is offset-aware, and that the no-timestamp payload still yields a parseable aware ISO string. It fails on master and passes here.uv run pytest tests/test_api_call.py -q→ 27 passed.Note:
uv run task formatreformats a large number of unrelated files on current master, so only the two files touched here are included in this PR.🤖 Generated with Claude Code