Cryptographically signed, audit-grade carbon ledger for Scope 3 emissions
Project description
carbon-ops
carbon-ops provides tooling for measuring host energy use, estimating carbon
emissions, and writing canonical ledger records. The repository contains the
Python library, a privileged polling daemon, and helper scripts for audit
workflows.
Components
- Library: energy logging helpers, carbon-estimation routines, and ledger utilities that emit canonical JSON lines with hash chaining.
- Governance daemon: polls RAPL counters at 10 Hz, maintains a monotonic accumulator, and serves readings over a Unix domain socket so unprivileged processes have access to wrap-safe totals.
- Examples: reference scripts that show how to assemble the pieces, including the aliasing demo that compares the governance daemon to a 15 s Prometheus-style scraper.
- Documentation: Markdown files and notes that cover deployment, limitations, and planned work.
Use cases
- Collect host telemetry (CPU, GPU, memory, RAPL) for training or inference jobs and store the results as time-stamped metrics.
- Estimate carbon emissions for a completed span using location-aware grid
intensity data. The estimator records the method (
analytical_truncatedormonte_carlo) and confidence interval metadata in the output. - Append audit ledger entries where each JSON object includes the hash of the previous entry, enabling tamper detection.
- Attribute package-level energy to individual processes by combining
governance-daemon readings with per-process CPU time (
allocation_ratio).
Installation
The project targets Python 3.10 and later on Linux hosts. RAPL-based telemetry
requires access to /sys/class/powercap or /dev/cpu/*/msr (kernel modules
intel_rapl_common and msr). Install with all extras to enable testing and
optional providers.
python -m pip install carbon-ops[all,dev]
Local development clones can use the supplied virtual environment helpers in
scripts/ or standard tooling such as pip and venv.
Quick start
from carbon_ops import CarbonEstimator, EnergyLogger
try:
logger = EnergyLogger()
except Exception as exc:
raise SystemExit(f"EnergyLogger initialisation failed: {exc}")
metric = logger.log_metrics("training_step")
estimator = CarbonEstimator()
record = estimator.estimate_over_span(
start_ts=metric["timestamp_start"],
end_ts=metric["timestamp_end"],
energy_wh=metric["energy"]["energy_wh_total"],
)
print(record.to_dict())
If the governance daemon is not available, the energy summary will report
attribution_mode="monitor_only" and execution continues without raising
exceptions.
Telemetry modes
Two RAPL backends are available:
- Sysfs mode (default): reads
/sys/class/powercap/.../energy_ujfiles. All samples are masked to 32 bits before they are accumulated to prevent high-bit noise. - MSR mode (privileged): reads
/dev/cpu/<n>/msrdirectly. The governance daemon fetches MSR0x606(RAPL power unit register), applies a 32-bit mask to RAPL counters (for example MSR0x611), converts to microjoules, and maintains the same accumulator used by the sysfs path. Enable with--rapl-mode=msr [--msr-cpus=…]. Root orCAP_SYS_RAWIOand themsrkernel module are required.
Governance daemon
Start the daemon with the default sysfs reader:
sudo python -m carbon_ops.governor.daemon
A minimal MSR launch targeting the first two sockets:
sudo python -m carbon_ops.governor.daemon --rapl-mode=msr --msr-cpus=0,1
The daemon listens on /var/run/carbon-ops.sock with root:carbon-users
ownership and 0o660 permissions. The library degrades to monitor-only mode if
the socket is unavailable.
Aliasing demonstration
examples/aliasing_demo.py contrasts the 10 Hz governance-daemon output with a mock
Prometheus scraper that polls every 15 seconds. The script exercises a CPU busy
loop, records energy via the Unix socket, and reports the energy that the slow
scraper misses when RAPL wraps (the “11-second anomaly”).
sudo python examples/aliasing_demo.py --duration 120
Ledger output
Ledger entries are written as canonical JSON lines. Each record includes the
previous entry hash (prev_hash), producing a simple hash chain for tamper
resistance. The ledger functions guarantee atomic writes using a temporary file
followed by os.replace.
Testing
Run the test matrix after installing the development dependencies:
python -m pytest
python -m ruff check .
python -m black --check .
python -m mypy --strict .
python -m bandit -r src
The pyproject.toml file contains the exact tool versions used in CI.
Contributing
See CONTRIBUTING.md.
License
Licensed under the terms of LICENSE.
Support
- Issues: https://github.com/scrrlt/carbon-ops/issues
- Discussions: https://github.com/scrrlt/carbon-ops/discussions
- Email: s@scrrlt.dev
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file carbon_ops-0.1.1.tar.gz.
File metadata
- Download URL: carbon_ops-0.1.1.tar.gz
- Upload date:
- Size: 84.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3be0e4dc490545da7fefdb1e041459cde14509acfee6cff755863774825efdfe
|
|
| MD5 |
5918da8fd3c65676401d92f73b272d0a
|
|
| BLAKE2b-256 |
ea94ac09f171ac8cd10713ff48101cc8baf324a2d5420a13139905993fc87542
|
File details
Details for the file carbon_ops-0.1.1-py3-none-any.whl.
File metadata
- Download URL: carbon_ops-0.1.1-py3-none-any.whl
- Upload date:
- Size: 98.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
741369a889b44e510b2ec4e9379e23feab136e85f2ec48c95ff2453dcb05f8c0
|
|
| MD5 |
4cb9b69048d5762dc57deb2b11fe4cbf
|
|
| BLAKE2b-256 |
27ee269be9e9d19f71f292837666e8d89a84dd475647954bec3e71a2409b1f0f
|