Skip to content

fix: send measurement time to the API - #1325

Closed
davidberenstein1957 wants to merge 2 commits into
masterfrom
fix/api-emission-timestamp
Closed

fix: send measurement time to the API#1325
davidberenstein1957 wants to merge 2 commits into
masterfrom
fix/api-emission-timestamp

Conversation

@davidberenstein1957

Copy link
Copy Markdown
Collaborator

What changed

ApiClient.add_emission now sends the timestamp carried by the emission payload instead of generating a new one at payload-build time. A small get_measurement_timestamp helper localises the naive EmissionsData.timestamp to an offset-aware ISO string, falls back to get_datetime_with_timezone() when no timestamp is present (hand-built dicts), and logs a warning rather than failing on an unparseable value.

Why

EmissionsData.timestamp records when the measurement window ended (codecarbon/emissions_tracker.py:1063), survives all the way into HTTPOutput._emit (codecarbon/output_methods/http.py:65-68), and was then thrown away by add_emission, which stamped get_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 both file and api output 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_timestamp asserts the POSTed timestamp starts 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 format reformats 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

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

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.44%. Comparing base (065d0e6) to head (0d79a24).

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@davidberenstein1957

Copy link
Copy Markdown
Collaborator Author

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, None, and unparseable timestamps), no per-call log noise, and a comment at _create_run explaining why stamping "now" is correct there, so nobody "fixes" it later.

The one thing this PR has that #1341 lacks is the producer-side comment noting that .astimezone() assumes the local zone because the value comes from datetime.now(). That is worth keeping, so it will be ported across.

Nothing wrong with the work here — the two were developed in parallel against the same bug report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API emissions are timestamped at send time, not measurement time

1 participant