Skip to content

feat: add scheduler job metadata to output - #1366

Open
davidberenstein1957 wants to merge 2 commits into
fix/csv-update-dtype-coercionfrom
feat/slurm-integration
Open

feat: add scheduler job metadata to output#1366
davidberenstein1957 wants to merge 2 commits into
fix/csv-update-dtype-coercionfrom
feat/slurm-integration

Conversation

@davidberenstein1957

@davidberenstein1957 davidberenstein1957 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

What this adds

CodeCarbon now reads the batch scheduler job identity out of the environment and stores it on every emissions record. Under SLURM this happens automatically — there is nothing to enable, no new flag, and no code change in a user's batch script. An existing .slurm script starts producing tagged rows as soon as it upgrades.

The point is joinability: with job_id, job_account and node_name on the row, emissions.csv lines up directly against sacct -j <id>, which is what turns a pile of per-run rows into a cluster report. It also retires the CODECARBON_PROJECT_NAME=$SLURM_JOB_ID workaround, which worked but overloaded a field that means something else.

User-facing surface

Seven new CSV columns, all defaulting to "" so nothing changes off a cluster:

scheduler, job_id, job_name, job_user, job_account, job_partition, node_name

Populated from SLURM_JOB_ID, SLURM_JOB_NAME, SLURM_JOB_USER, SLURM_JOB_ACCOUNT, SLURM_JOB_PARTITION and SLURMD_NODENAME.

Any field can also be set or overridden with an environment variable named after it — CODECARBON_SCHEDULER, CODECARBON_JOB_ID, CODECARBON_NODE_NAME and so on. That is the whole story for PBS, LSF and OAR: a site maps its scheduler's variables onto ours in three lines of shell, and we ship a documented contract rather than a backend per scheduler.

No new dependencies — this is os.environ and a dataclass.

How it fits

EmissionsTracker._prepare_emissions_data() is already where run context is assembled onto the record alongside cloud and geography metadata, so this is one more context source in the place that collects context. The API output path lists its fields explicitly in ApiClient.add_emission, and Prometheus labels are an explicit allowlist, so neither contract changes — the new columns land in the CSV only.

Verified

  • New tests/test_schedulers.py: fake SLURM environment produces populated metadata; an empty environment stays inert; a partial environment fills only what is present; the CODECARBON_* contract works standalone and takes precedence over SLURM; and an end-to-end check that the fields reach EmissionsData and its CSV columns. All monkeypatch-style env fixtures — no cluster required.
  • Full suite: 632 passed, 21 skipped (tests/test_viz_data.py excluded, it needs dash which is not in the dev environment).
  • black --check and ruff check clean on the touched files, modulo the repo-wide typing.Dict warnings that predate this branch.

Upgrade note: existing emissions.csv files are rotated once

FileOutput.has_valid_headers compares sorted header lists, so seven new columns mean that on the first run after upgrading, an existing emissions.csv is backed up next to itself and a new file is started with the new header. Nothing is lost, but a pipeline reading a fixed path will find only the new rows in it. Documented in docs/reference/output.md.

tests/test_data/emissions_valid_headers.csv gains the new columns, as it must whenever the CSV schema grows.

Based on #1370

The schema change surfaces a bug in FileOutput.out's "update" mode: it cast each value through the stored column's dtype, and an all-empty text column is read back by pandas as float64, so float("") raised and the write failed. #1370 fixes that at the root by dropping the coercion entirely, so this branch is stacked on fix/csv-update-dtype-coercion and carries no workaround of its own. Rebase onto master once #1370 merges.

Multi-rank double counting is now a runtime warning

SLURM_NTASKS_PER_NODE > 1 with tracking_mode="machine" means every rank measures the whole node and the job's total is multiplied by the rank count. A docs warning does not catch people, so warn_on_multi_rank_double_counting() logs it at tracker init.

Deliberately left out

  • A codecarbon slurm wrapper command. codecarbon monitor -- <cmd> already wraps an arbitrary command, and with metadata detected automatically it needs nothing SLURM-specific. A dedicated command should wait for a job the generic one cannot do.
  • Prolog/epilog integration. Snapshotting energy counters at job start and end would give a centre cluster-wide coverage with no user changes, but it means CodeCarbon running as root on every compute node. That is its own proposal and its own security review.
  • One-tracker-per-node rank election. Only meaningful once something launches trackers on our behalf, and it is the same problem as LOCAL_RANK == 0 in distributed training — worth solving once, generically, when there is a caller. For now the multi-node double-counting hazard is documented as a warning in docs/how-to/slurm.md.
  • Per-job attribution on shared nodes. Node-level power cannot be split between concurrent jobs; that decision blocks any site-wide path, not this labelling work.

Docs updated: docs/reference/output.md gains the field table entries, and docs/how-to/slurm.md gains a "Job metadata in the output" section covering the variable mapping, the sacct join, the other-scheduler contract and the multi-node caveat.

Closes #1355

🤖 Generated with Claude Code

@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.57%. Comparing base (900f7dd) to head (81bc919).

Additional details and impacted files
@@                        Coverage Diff                        @@
##           fix/csv-update-dtype-coercion    #1366      +/-   ##
=================================================================
+ Coverage                          91.42%   91.57%   +0.15%     
=================================================================
  Files                                 49       50       +1     
  Lines                               5051     5083      +32     
=================================================================
+ Hits                                4618     4655      +37     
+ Misses                               433      428       -5     

☔ 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.

davidberenstein1957 and others added 2 commits August 12, 2026 19:49
Read the job identity SLURM already exports into every job step and store
it on the emissions record, so an HPC job's rows are joinable against
`sacct` instead of users smuggling the job id into `project_name`.

Other schedulers map their own variables onto the same fields through
`CODECARBON_SCHEDULER` / `CODECARBON_JOB_*`, which also override the
auto-detected SLURM values.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rebased on fix/csv-update-dtype-coercion (#1370), which fixes the CSV dtype
coercion properly, so the local workaround in file.py is dropped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@davidberenstein1957
davidberenstein1957 changed the base branch from master to fix/csv-update-dtype-coercion August 12, 2026 17:53
@davidberenstein1957
davidberenstein1957 marked this pull request as ready for review August 12, 2026 19:14
@davidberenstein1957
davidberenstein1957 requested a review from a team as a code owner August 12, 2026 19:14
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.

Attach SLURM/scheduler job metadata to the emissions record

1 participant